Ruby versus PHP: minha comparação subjetiva e desleal (Parte 1)

Em: 23/11/2007 Tags: , Referencie do seu blog (Trackback)

Meu trabalho atual envolve muita exportação de dados entre diferentes bancos de dados relacionais. Hoje me deparei com a seguinte situação: precisava extrair dados de uma base MySQL, formatá-los apropriadamente em um arquivo de texto, e então inseri-los no Moodle através de sua interface administrativa (que aceita arquivos tabulares como forma de cadastrar usuários “em lote”).

Minha tabela de origem possuía um campo fullname, mas o Moodle só aceita firstname e lastname. Portanto, ou o meu SELECT quebraria esses campos ou então eu utilizaria alguma linguagem para pré-processar esses arquivos.

E foi aí que Ruby deu conta do recado muito bem. Essa dica vale para qualquer operação rápida de manipulação de arquivos que você não saiba fazer dentro do MySQL ou do Vim.

Minha consulta SQL gerava a seguinte saída (colunas nome de usuário, senha, nome completo e email):

fulano,123456,Fulano da Silva,fulano@teste.com
beltrano,123456,Beltrano da Silva,beltrano@teste.com

Mas o que eu queria era (note a vírgula entre o primeiro nome e o sobrenome):

fulano,123456,Fulano,da Silva,fulano@teste.com
beltrano,123456,Beltrano,da Silva,beltrano@teste.com

Ah, claro, se eu tivesse apenas duas linhas no arquivo eu não teria escrito o programa. Na verdade eram mais de 100. Então decidi escrever o seguinte programa Ruby para me ajudar.

#!/usr/bin/env ruby

File.open(ARGV[0]) do |f| 
  f.each_line do |line|
    username, password, full_name, email = line.split(',')
    first_name, last_name = full_name.split(' ', 2)
    STDOUT << [username, password, first_name, last_name, email].join(',')
  end 
end 

Para utilizar o script, primeiro o defini como executável:

chmod a+x formatador.rb

E em seguida o executei, passando como único parâmetro o caminho para o arquivo de origem. Como estamos utilizando STDOUT para escrever a saída, o resultado do script é impresso no seu terminal (ele é a saída padrão). Você pode direcionar essa saída para um arquivo utilizando o caracter > (no Linux/Unix da vida).

./formatador.rb entrada.txt > saida.txt

A vantagem óbvia de se utilizar STDOUT em vez de se criar outro arquivo dentro do código-fonte é que podemos testar rapidamente o comportamento do script ao deixar a saída ser impressa no terminal.

Embora eu tenha PHP como a minha linguagem de programação “materna”, nem pensei em escrever esse script com ela. Mas enquanto escrevia este artigo pensei “Vamos ver quanto tempo eu levo…”. E isso foi há uns 20 minutos. Isso é algo que me irrita no PHP: eu sempre tenho dificuldade pra escrever as mesmas coisas, sejam elas simples ou complexas. A ordem dos parâmetros de funções da biblioteca padrão geralmente é aleatória, você não sabe se a função leva underscore ou não, você esquece o nome dela (mas você já a utilizou tantas vezes!)… A questão é que enquanto eu levei menos de 5 minutos pra escrever a versão em Ruby, não concluí a versão em PHP por não ter paciência pra tentar descobrir o bug do programa. Para os interessados, a idéia básica era esta.

Note que ele é praticamente uma “tradução literal” do programa Ruby, feitas certas ressalvas:

  • Em Ruby você não precisa fechar o arquivo que você abriu, pois o método File#open faz isso pra você depois que a sua callback é executada. Em PHP você precisa fechar o arquivo explicitamente (em geral esqueço disso).
  • Enquanto em Ruby você itera sobre as linhas de um arquivo utilizando o intuitivo File#each_line (eu nunca me esqueci do nome desse método), em PHP você utiliza o medonho fgets() (já perdi a conta de quantas vezes precisei procurar por esse método na documentação oficial, pois a cada 2 meses sem utilizá-lo esqueço que ele sequer existe, hehe).

Confesso que o PHP poderia ser uma linguagem muito pior: a versão PHP do programa ficou tão compacta quanto a versão Ruby graças a vários “métodos-irmãos” entre as duas linguagens:

  • Em PHP a função list() é utilizado para permitir as atribuições simultâneas que Ruby suporta “nativamente”
  • Em PHP a função explode() quebra uma string em um array. Em Ruby utilizamos Array#split
  • Em PHP a função implode() constrói um array a partir de uma string. Em Ruby utilizamos Array#join

Resumo da ópera: sempre que possível utilize Ruby em vez de PHP. Sua saúde mental agradece.

Artigos relacionados:

5 respostas para “Ruby versus PHP: minha comparação subjetiva e desleal (Parte 1)”

  1. Thânia Clair disse:

    Muito legal! Vou pesquisar se o split do java tb tem uma versão para o segundo parâmetro para a junção da string restante. =)

  2. Éverton disse:

    Eu concordo em todos os aspectos que Ruby é superior, mas neste exemplo PHP não fica atrás não, você poderia ter utilizado a função file, que lê um arquivo inteiro para um array em php.

  3. Caio disse:

    Everton, sua dica comprova meu descontentamento: não lembrava dessa função (de fato acho que nunca havia esbarrado nela), e ela realmente é muito útil. Eu só conhecia a file_get_contents(), mas neste caso a file() realmente é melhor.

    Obrigado pelo comentário ;)

  4. Éverton disse:

    Não por isso, estamos aqui para contribuir mesmo,

    Mas eu concordo plenamente com você, no Ruby todas as funções são bem padronizadas e podem ser encontradas facilmente. Por exemplo sempre que eu quero converter alguma coisa para outra eu procuro por um função toXX, quase sempre esta la, se não estar procuro implementar utilizando o toXX.

    E isso é uma das grande diferenças do Ruby, ninguém (ou quase ninguém) escreve um código Ruby com funções o nomenclatura fora do padrão utilizado pela equipe do próprio Ruby.

  5. actualmind disse:

    Interessante mas no caso não seria mais facil e rapido utilizar awk?

Escreva um comentário (utilize o formato Markdown)