Groovy ou Ruby? Um breve relato

[color=blue]Não tinha como não publicar isso aqui, para iniciar um debate, acho que agora ficou bem claro , cada tecnologia vai ter seu responsabilidade, mas a evolução é inevitável. [/color]

:arrow:Fonte Groovy ou Ruby

Groovy ou Ruby? Um breve relato.
Publicado por: Felipe Rodrigues de Almeida
em: 03 Out 2008 às 18:58

Como já é de conhecimento publico, a InfoQ Brasil será lançada no dia 20 de Outubro de 2008 incluindo vários artigos e notícias traduzidos para o protuguês, além do livro Scrum e XP direto das trincheiras também traduzido.

Todos que conhecem o portal InfoQ sabem da qualidade de seu conteúdo e pretendemos manter a mesma qualidade na versão brasileira do portal. Para começar bem, iremos cobrir e publicar as apresentações do Rails Summit 2008 ao longo do próximo ano. Esse evento promete ser um marco na história do Ruby e Rails no Brasil e como tal estarei lá pra conferir. =)

Você devem estar se perguntando o que isso tem a ver com o título do post. =)

Eu explico. Eu pedi pro Floyd Marinescu (co-fundador da InfoQ) uma idéia de quantos posts são publicados por mês na InfoQ original. Ele me respondeu o email dizendo que o máximo que ele podia fazer era conseguir um arquivo CSV com o seguinte conteúdo:

Publications.csv

TYPE;DATE;COMMUNITIES 
Interview;15/06/2008;Java 
Article;28/03/2008;Architecture 
Article;23/05/2008;SOA 
News;12/06/2008;.NET 
News;12/06/2008;.NET 
News;10/06/2008;Java 
... continua ... [/code]


Obviamente isso não resolvia meu problema. Nesse arquivo temos o tipo de publicação (Interview, Article, News ou Presentation), tem a data em que foi publicado e a comunidade em que foi publicado o artigo. O que eu pensei? Vou escrever um parser para esse arquivo e assim obter os dados que preciso.

O objetivo era conseguir um resultado como esse:

ANO 
A quantidade de materias desse ano foi: <> 
A media de materias por mes nesse ano foi: <>

ANO 
A quantidade de materias desse ano foi: <> 
A media de materias por mes nesse ano foi: <>

O Total de itens é <>

Decidi que faria esse parser em ruby, abri meu e-editor e comecei a digitar o programa. 15 minutos depois percebi que eu estava indo pelo caminho errado e que não conseguiria o reslutado esperado daquela forma. Meus anos de Java me acostumaram errado. Eu comecei a pensar que deveria haver algum modo mais fácil de fazer aquilo. Decidi então escrever em Groovy, linguagem que possuo mais domínio do que Ruby. Em Groovy não tive dificuldades e construi esse código:
[code]publications.groovy

List items = [] 

new File('publications.csv').splitEachLine(';') { line -> 
items.add(line) 
} 

def range = 2005..2008 

range.each { year -> 
println year 
numItems = items.findAll{it[1] =~ /${year}$/}.size 
println "A quantidade de materias desse ano foi: ${numItems}" 

def average = (numItems/12) as BigInteger 
println "A media de materias por mes nesse ano foi: ${average}" 
def weekAverage = (average/4) as BigInteger 
println "A media de materias por semana nesse ano foi: ${weekAverage}\n\n" 
} 

println "Total de itens em todos os anos: ${items.size}\n"

Foi extremamente fácil e não gastei mais do que 15 minutos para concluir esse código. Decidi então que eu iria escrever o mesmo programa em Ruby, tentando seguir os mesmos passos que realizei em Groovy. O resultado saiu em 10 minutos com o seguinte código:

[code]publications.rb

require ‘csv’

rows = CSV::Reader.parse(File.open(‘publications.csv’),’;’)
@items = rows.to_a

range = 2005…2008

range.each {|year|
puts year
@thisYearItems = []
@items.each {|item|
if (item[1] =~ /#{year}$/) != nil
@thisYearItems << item
end
}
numItems = @thisYearItems.size
puts “A quantidade de materias desse ano foi: #{numItems}”

average = (numItems/12)
puts “A media de materias por mes nesse ano foi: #{average}”
weekAverage = (average/4)
puts “A media de materias por semana nesse ano foi: #{weekAverage}\n\n”
}

puts “Total de itens em todos os anos: #{@items.size}\n\n”[/code]

Dessa experiência pude observar várias semelhanças entre as duas linguagens e também algumas diferenças. Os pontos que mais me chamaram a atenção foram o seguinte:
Groovy possue mais métodos de conveniência do que Ruby. Esses métodos são projetados para oferecer mais comodidade para o desenvolvedor. Isso fez com que o programa escrito em Groovy utilizasse apenas 23 linhas de código, enquanto o programa em Ruby utiliza 29 linhas.
Ruby foi mais performático neste caso (rodando ambos como script).
Ambas são linguagens extremamento flexiveis e poderosas com recursos e facilidades muito boas. Eu não tentei escrever esse programa em Java e nem em C, mas imagino que teriamos pelo menos o dobro de linhas de código. Se alguém se habilitar a fazer essa experiência, eu agradeço.

Analisem os dois exemplos e tirem suas próprias concluões sobre qual delas é mais a sua cara.

Isso me deu uma ótima idéia para postar sobre Groovy on Rails e Ruby on Rails. Também pretendo postar sobre meta-programação nestas duas linguagens.’

Pra terminar o post vale a pena mostrar o resultado, assim já dá uma idéia de quanto conteúdo teremos na InfoQ Brasil.

2006
A quantidade de materias desse ano foi: 949
A media de materias por mes nesse ano foi: 79
A media de materias por semana nesse ano foi: 19

2007
A quantidade de materias desse ano foi: 1525
A media de materias por mes nesse ano foi: 127
A media de materias por semana nesse ano foi: 31

2008
A quantidade de materias desse ano foi: 878
A media de materias por mes nesse ano foi: 73
A media de materias por semana nesse ano foi: 18

Total de itens em todos os anos: 3352

Conto com a participação de todos vocês nesse novo e promissor portal brasileiro. =)
Tags: | Ruby | Groovy |

Não é mais facil colocar apenas o link para o blog, do que duplicar toda a informação do post aqui no forum? :lol:

Já tinha lido este post diretamente no blog, achei bem interessante.

O código equivalente em Java é bem mais verboso (embora eu não leia todas as linhas dentro de um array, o que potencialmente permite a leitura de arquivos muito grandes, o que obviamente não é o caso do CSV passado pelo pessoal do InfoQ).

class Estatisticas {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader (new FileReader ("publications.csv"));
        int[] nMaterias = new int[2008 + 1]; // para simplificar. Olhe o espaço gasto!
        int totalMaterias = 0;
        DateFormat df = new SimpleDateFormat ("dd/MM/yyyy");
        df.setLenient (false);
        for (String linha = br.readLine(); linha != null; linha = br.readLine()) {
            try {
                String[] campos = linha.split (";");
                Date dt = df.parse (campos [1]);
                Calendar cal = Calendar.getInstance(); 
                cal.setTime (dt);
                int year = cal.get (Calendar.YEAR);
                if (2005 <= year && year <= 2008) {
                     nMaterias [year]++;
                     totalMaterias++;
                }
            } catch (Exception ex) {
            }
        }
	br.close();
        for (int i = 2005; i <= 2008; ++i) {
            System.out.println (i);
            System.out.printf ("A quantidade de materias desse ano foi: %d%n", nMaterias[i]);   
            System.out.printf ("A media de materias por mes nesse ano foi: %d%n", nMaterias[i]/12);
            System.out.printf ("A media de materias por semana nesse ano foi: %d%n%n", nMaterias[i]/52);
        }
        System.out.printf ("Total de itens em todos os anos: %d%n", totalMaterias);
    }
}

[quote=rlazoti]Não é mais facil colocar apenas o link para o blog, do que duplicar toda a informação do post aqui no forum? :lol:

Já tinha lido este post diretamente no blog, achei bem interessante.[/quote]
Não queria que as pessoas perde-se tempo indo para o link, já adiantei a informação, -" se repitada?.; - não é pois esta sendo discutida aqui , no GUJ.

[quote=thingol]O código equivalente em Java é bem mais verboso (embora eu não leia todas as linhas dentro de um array, o que potencialmente permite a leitura de arquivos muito grandes, o que obviamente não é o caso do CSV passado pelo pessoal do InfoQ).
[/quote]
Talvez o caso não fosse de um unico recurso que cabe ao CSV, mas a quantidade reduzida de código a ser processado por linhas de comandos.

:smiley:

awk -F \; '{ total[$1]++ } END{ for(i in total) printf("No ano %d tivemos %d materias, %02.2f por mes, %02.2f por semana\n",i,total[i],total[i]/12,total[i]/48); }' arquivo.cvs

Detalhe que, para saber quantas materias foram publicadas por ano, vc pode fazer

cut -d \; -f 1 arquivo.cvs | sort | uniq -c 

Sinceramente??? Sei que muitos aqui se matam pelas linguangens script e tals, mas vou falar a verdade;
Funcionais: sim; econômicas: sim; menos código: sim; eficiente: talvez; Legíveis: nem um pouco; compreesiveis: muitos menos!

Resumindo, daqui um pouco vamos estar escrevendo assim
/??#4*& 33)($* 1*)@#*39. Ai o NERD fala, olha que legal o código que escrevi!!! Ou seja regredindo, saimos de assembly fomos pra linguagens de mais alto nivel que podiam ser lidas por seres normais, e agora de volta ao inferno, em suma, SER HUMANO!!!
Mas vai ser a ONDA!, pq alguem chegou primeiro e disse que era massa, que ia acabar com o java e por ai vai!!
Sinceramente, talvez hoje eu deva aprender Ruby(por prazer) pq to nesse forum desde de 2005 e sempre escuto esse papo que RoR é o futuro da nação, e agora 4 anos depois: WHERE IS THE RUBY, nao consigo ver nada significante!

Um jeito seria pensar na saida do progama como a quantidade de materias publicas em funcao do periodo. Neste caso duas coisas precisariam ser ditas:

  1. definir funcao:
    contador-fn = “conta os resultados nao-nulos obtidos do mapeamento da pesquisa do padrao de busca por cada linha do arquivo.”

(count (remove nil? (map (find (pattern ano) linha) arquivo))

  1. utilizar a funcao contadora no programa principal que por sua vez consiste em:
    total materias = “acumulacao do resultado obtido do mapeamento da funcao contadora atraves dos anos.”

(acumula + (map contador-fn periodo))

em Clojure ficaria assim…

[code](def arquivo (seq (.split (slurp “arquivo.csv”) “\n”)))

(def periodo (range 2005 2009))

(str "Total: " (apply +
(map (fn [ano]
(let [pot (remove nil? (map #(re-find (re-pattern (str ano)) %) arquivo))]
(do (println (str ano ": " (count pot))))
(count pot)))
periodo)))[/code]

Sinceramente??? Sei que muitos aqui se matam pelas linguangens script e tals, mas vou falar a verdade;
Funcionais: sim; econômicas: sim; menos código: sim; eficiente: talvez; Legíveis: nem um pouco; compreesiveis: muitos menos!

Resumindo, daqui um pouco vamos estar escrevendo assim
/??#4*& 33)($* 1*)@#*39. Ai o NERD fala, olha que legal o código que escrevi!!! Ou seja regredindo, saimos de assembly fomos pra linguagens de mais alto nivel que podiam ser lidas por seres normais, e agora de volta ao inferno, em suma, SER HUMANO!!!
Mas vai ser a ONDA!, pq alguem chegou primeiro e disse que era massa, que ia acabar com o java e por ai vai!!
Sinceramente, talvez hoje eu deva aprender Ruby(por prazer) pq to nesse forum desde de 2005 e sempre escuto esse papo que RoR é o futuro da nação, e agora 4 anos depois: WHERE IS THE RUBY, nao consigo ver nada significante![/quote]

Você pega um único exemplo e já sai esculachando toda uma classe de linguagens de programação? Nem todos os scripts são um jogo Perl Golf.

Sem falar que você pode fazer um código ilegível mesmo nas linguagens de mais alto nível.

Obs: Se você soubesse unix shell script, o exemplo que citou seria um dos mais legíveis.

Sinceramente??? Sei que muitos aqui se matam pelas linguangens script e tals, mas vou falar a verdade;
Funcionais: sim; econômicas: sim; menos código: sim; eficiente: talvez; Legíveis: nem um pouco; compreesiveis: muitos menos!

Resumindo, daqui um pouco vamos estar escrevendo assim
/??#4*& 33)($* 1*)@#*39. Ai o NERD fala, olha que legal o código que escrevi!!! Ou seja regredindo, saimos de assembly fomos pra linguagens de mais alto nivel que podiam ser lidas por seres normais, e agora de volta ao inferno, em suma, SER HUMANO!!!
Mas vai ser a ONDA!, pq alguem chegou primeiro e disse que era massa, que ia acabar com o java e por ai vai!!
Sinceramente, talvez hoje eu deva aprender Ruby(por prazer) pq to nesse forum desde de 2005 e sempre escuto esse papo que RoR é o futuro da nação, e agora 4 anos depois: WHERE IS THE RUBY, nao consigo ver nada significante![/quote]

Vejamos, isso é legivel?:

System.out.println(uniq ( true , sort ( cut (';',1, 'arquivo.cvs' ) ) ) ); 

Para ser legivel vc deveria conhecer a assinatura desses 3 metodos: cut, sort e uniq

O que eu fiz com pipes e comandos basicos do unix para mim é legivel.

RTFM :slight_smile:

[quote=Bruno Laturner]
Sem falar que você pode fazer um código ilegível mesmo nas linguagens de mais alto nível.

Obs: Se você soubesse unix shell script, o exemplo que citou seria um dos mais legíveis.[/quote]

Entretanto nao é possivel fazer codigo legivel usando linguagem de baixo nivel. Logo sua segunda afirmacao nao é verdadeira.

[quote=cmoscoso][quote=Bruno Laturner]
Sem falar que você pode fazer um código ilegível mesmo nas linguagens de mais alto nível.

Obs: Se você soubesse unix shell script, o exemplo que citou seria um dos mais legíveis.[/quote]

Entretanto nao é possivel fazer codigo legivel usando linguagem de baixo nivel. Logo sua segunda afirmacao nao é verdadeira.[/quote]

Shell script não é uma linguagem de baixo nível, nem o código é ilegível.

Legibilidade requer em primeiro lugar o conhecimento da linguagem. Não adianta falar que um livro é bem escrito se a pessoa nem sabe o significa do que está lá.

[quote=Bruno Laturner][quote=cmoscoso][quote=Bruno Laturner]
Sem falar que você pode fazer um código ilegível mesmo nas linguagens de mais alto nível.

Obs: Se você soubesse unix shell script, o exemplo que citou seria um dos mais legíveis.[/quote]

Entretanto nao é possivel fazer codigo legivel usando linguagem de baixo nivel. Logo sua segunda afirmacao nao é verdadeira.[/quote]

Shell script não é uma linguagem de baixo nível, nem o código é ilegível.

Legibilidade requer em primeiro lugar o conhecimento da linguagem. Não adianta falar que um livro é bem escrito se a pessoa nem sabe o significa do que está lá.[/quote]

Uma coisa que queria melhor entender, a legibilidade requer o conhecimento da linguagem (mas se for o caso de usar uma ferramenta que gere código), se tivesse que usar o AndroMDA, até aonde eu posso pensar em especialização por uma linguagem ou promover um desenvolvimento que envolva até implementação visual, ou isso não seria possível, não sei até onde posso afirmar isso… !!!, mas na certa já são muitas empresa que trabalham sobre modelo ou worflows que produzam desenvolvimento pelo o domínio do problema

[code]#publications.rb
require ‘csv’

rows = CSV::Reader.parse(File.open(‘publications.csv’),’;’)

@items = rows.to_a

(2005…2008).each do |year|
puts year
@thisYearItems = @items.find_all {|item| item[1] =~ /#{year.to_s}$/ }
numItems = @thisYearItems.size
puts “A quantidade de materias desse ano foi: #{numItems}”

average = (numItems/12)
puts “A media de materias por mes nesse ano foi: #{average}”
weekAverage = (average/4)
puts “A media de materias por semana nesse ano foi: #{weekAverage}\n\n”
end

puts “Total de itens em todos os anos: #{@items.size}\n\n”
[/code]

E isso que eu fiz aqui rapidinho, dá pra melhorar…

Isso só demonstra falta de conhecimento na linguagem, e sair por ae publicando artigos sem noção…

[quote=Bruno Laturner]
Shell script não é uma linguagem de baixo nível, nem o código é ilegível.[/quote]

Entao experimenta fazer um forum usando shell script.

[quote=Bruno Laturner]
Legibilidade requer em primeiro lugar o conhecimento da linguagem. Não adianta falar que um livro é bem escrito se a pessoa nem sabe o significa do que está lá.[/quote]

Conhecimento da linguagem e fundamental, principalmente a linguagem de dominio utilizada pelo cliente. E se alguem pretende oferecer uma solucao, sim este alguem precisa conhecer o problema (isso incluiria a linguagem utilizada para descrever o problema!).

Dito isso, a legibilidade a que me refiro esta relacionado com a capacidade de implementar com precisao essa linguagem do dominio (no caso poderia ser materias publicadas, periodo, totalizacao) numa GPL, seja ela groovy, ruby, clojure, etc.

A principio nao importa se pra isso serao utilizadas 2 linhas, ou 1 e meia, apenas o codigo precisa fazer sentido pro “cliente”.

[quote=cmoscoso]
A principio nao importa se pra isso serao utilizadas 2 linhas, ou 1 e meia, apenas o codigo precisa fazer sentido pro “cliente”.[/quote]
Código [size=24]?[/size] , isso sendo baseado em uma APF foi isso que você quis dizer, não entendi tal objetivo que vá fazer sentindo ao cliente “ele é algum implementador”

[quote=Marcio Duran][quote=cmoscoso]
A principio nao importa se pra isso serao utilizadas 2 linhas, ou 1 e meia, apenas o codigo precisa fazer sentido pro “cliente”.[/quote]
Código [size=24]?[/size] , isso sendo baseado em uma APF foi isso que você quis dizer, não entendi tal objetivo que vá fazer sentindo ao cliente “ele é algum implementador”[/quote]

APF [size=24]?[/size]

Marcio,

Sim, o cliente pode ser implementador, mas geralmente digamos que seja o analista de negocio…

De fato a legibilidade da implementacao nao importa, mas da sua interface exposta, esta portanto deve ser descrita em termos da linguagem de dominio, para que seja familiar ao analista de negocio.

Faz sentido agora?

:arrow:Análise de Pontos de Função (APF) é uma técnica para a medição de projetos de desenvolvimento de software, visando estabelecer uma medida de tamanho, em Pontos de Função (PF), considerando a funcionalidade implementada, sob o ponto de vista do usuário. A medida é independente da linguagem de programação ou da tecnologia que será usada para implementação.

É algo que o proprio Fabio Kung mencionou que DSL não é para gerente, isso não é um pouco de conhecidencia :arrow: http://blog.caelum.com.br/category/dsl/ .