Refactoring

Code Smells – Duplicação de Código


 

Semana passada postei uma tradução do artigo em inglês sobre Code Smells, escrito pelo Martin Fowler. Pretendo criar alguns posts rápidos comentando sobre smells clássicos e possíveis formas de combatê-los. Por hoje, vamos ver em Ruby como combater duplicação de códigos usando um design pattern conhecido como Template Method.

 

Identificando o problema

 

Um cenário muito comum ao desenvolvermos software é nos depararmos com a seguinte situação: uma quantidade significativa de código que resolve um problema X, mas que precisa sofrer pequenas alterações para resolver também o problema Y, Z e “n” outros problemas muito parecidos entre si.

Vamos supor que você esteja trabalhando em um projeto que precisa gerar boletos bancários para diversos bancos. Ao olhar o código do sistema em produção, você percebe que  algum desenvolvedor no passado (que já saiu da empresa, afinal ninguém quer assumir a culpa) resolveu brilhantemente isolar o código para gerar boletos bancários para o Itaú em uma classe chamada BoletoItau – classe essa que parece com a seguinte:

 Parabéns para o desenvolvedor que resolveu isolar o código acima em uma classe. Mas, quando esse mesmo desenvolvedor teve que gerar um boleto para o banco Santander (que parece muito com o boleto do Itaú) ele fez algo muito, muito ruim: ele duplicou a classe BoletoItau, criando a BoletoSantander:

 

Agora você, que esta com a tarefa para criar boletos para o Banco do Brasil, se vê diante das opções: perpetuar esse legado de código duplicado, ou refatorar o código acima para algum design pattern existente. Não se deixe seduzir pelo lado negro da força, gaste um tempinho e resolva permanentemente esse problema com o Template Method.

tumblr_mp8dtqhOmI1sx2peuo1_500

 Darth Vader tá vendo você querendo manter a POG.

 

Identificando o que permanece igual

 

A chave central desse dilema é identificar o que se repete entre os códigos semelhantes e isolá-los em uma classe que servirá de base para todas as subclasses.  Uma definição formal do pattern Template seria:

A idéia geral do Pattern Template Method é criar uma classe base abstrata com um método que sirva de esqueleto. Esse método possui o processamento que pode variar, realizando chamadas a métodos abstratos, que serão fornecidos por subclasses concretas. (Design Patterns in Ruby)

No exemplo anterior, vemos que as principais diferenças entre as classes BoletoItau e BoletoSantander se encontra no método gerar_boleto. Para transformar o método gerar_boleto em um Template Method, eu preciso antes transformar o código que ele executa em chamadas as métodos que serão sobrescritos por cada subclasse, que no meu exemplo, será cada Banco.

Uma proposta da classe Boleto seria:

  Com isso, a cada novo Banco, eu posso simplesmente extender a classe base Boleto e sobrescrever os métodos desejados. Os bancos poderiam ficar da seguinte forma:

 

Conclusão

 

O exemplo foi bastante reduzido para não tornar este post em uma dissertação acadêmica, mas adianto que  existe um mar de técnicas que podem ser aplicadas para melhorar ainda mais esse exemplo.

Caso queira uma recomendação de livro, indico o Design Patterns – Elements of Reusable Object-Oriented Software, que é um livro mais abrangente sobre o tema. Caso queria algo mais prático, tem o excelente Refactoring to Patterns (Java) que é um livro mais prático sobre Patterns. Em Ruby, existe o Design Patterns in Ruby, que usei como base para este post – e possivelmente usarei como base para os próximos posts.


I'm Pedro Mendes, a passionate developer and technology enthusiast. This blog covers programming and technology in the broadest sense possible. It's the place I collect my thoughts, work and findings to share with the public.

View Comments