Flay, eliminando repetições em código Ruby

November 13th, 2008 § 2 comments

Flay é uma ferramenta útil para cercear repetições de código em programas Ruby. Analisando o código semanticamente, o Flay é capaz de pegar repetições em casos que geralmente passam despercebidos no melhor dos códigos.

Em algumas casos, a repetição será inevitável e mesmo necessária para deixar o código mais legível. Geralmente, entretanto, repetição significa código que ainda não está DRY o suficiente.

Instalação

Para instalar o Flay, basta rodar o comando gem:

~$ sudo gem install flay

Esse comando instala a gem em si e um executável que pode ser usado na linha de comando.

Um exemplo

Para demonstrar o uso da ferramenta, vamos rodar o Flay contra o código mais recente do Active Record:

O resultado (um trecho apenas), depois de alguns minutos de trabalho com a CPU a 100%, é o seguinte:

Matches found in :defn (mass = 290)
  ./test/cases/associations/join_model_test.rb:237
  ./test/cases/associations/join_model_test.rb:262
  ./test/cases/associations/join_model_test.rb:271
  ./test/cases/associations/join_model_test.rb:623
  ./test/cases/associations/join_model_test.rb:650

Matches found in :defn (mass = 270)
  ./test/cases/validations_test.rb:929
  ./test/cases/validations_test.rb:937
  ./test/cases/validations_test.rb:945
  ./test/cases/validations_test.rb:953
  ./test/cases/validations_test.rb:961
  ./test/cases/validations_test.rb:969

Matches found in :defn (mass = 236)
  ./test/cases/validations_i18n_test.rb:491
  ./test/cases/validations_i18n_test.rb:510
  ./test/cases/validations_i18n_test.rb:529
  ./test/cases/validations_i18n_test.rb:549

Matches found in :scope (mass = 204)
  ./test/migrations/duplicate/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_1/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_2/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_3/3_innocent_jointable.rb:12
  ./test/migrations/missing/4_innocent_jointable.rb:12
  ./test/migrations/valid/3_innocent_jointable.rb:12

Matches found in :call (mass = 172)
  ./test/models/author.rb:64
  ./test/models/project.rb:17

Matches found in :defn (mass = 171)
  ./test/cases/validations_test.rb:977
  ./test/cases/validations_test.rb:991
  ./test/cases/validations_test.rb:1079

Note especialmente código que está sendo repetido em arquivos diferentes. No caso acima, como o código está em arquivos de teste, é provável que a repetição seja desejável para não poluir o escopo dos mesmos.

Vamos tomar um outra caso na biblioteca em si:

Matches found in :if (mass = 165)
  ./lib/active_record/associations/has_and_belongs_to_many_association.rb:82
  ./lib/active_record/associations/has_many_association.rb:100
  ./lib/active_record/associations/has_many_through_association.rb:194

O código repetido em questão é o seguinte:

if @reflection.options[:counter_sql]
  @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
elsif @reflection.options[:finder_sql]
  # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
  @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
  @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
else
  @counter_sql = @finder_sql
end

Vendo os arquivos, é possível observar que o código é o mesmo. Considerando que os três arquivos representam classes com um pai em comum seria possível reduzir a repetição movendo o código para um método a classe pai.

Esse tipo de repetição tende a sumir com refatoramentos e o código acima provavelmente sumirá por um processo similar (alguém se habilita para um patch?).

Conclusão

Como é possível perceber, o Flay representa mais uma forma de observar o seu código em busca de coisas que podem ser melhoradas. É claro que isso não deve ser converter em uma obsessão de remover toda e qualquer repetição, o que demoraria mais tempo do que codificar coisas novas.

Como de usual, sugestões, críticas e dúvidas são bem-vindos.

Tagged

§ 2 Responses to Flay, eliminando repetições em código Ruby"

Leave a Reply

Your email address will not be published. Required fields are marked *

What's this?

You are currently reading Flay, eliminando repetições em código Ruby at Superfície Reflexiva.

meta