“Nós somos aquilo que fazemos repetidamente. Excelência, então, não é um modo de agir, mas um hábito” – Will Durant .
Melhoria constante deve ser o objetivo de qualquer pessoa, hoje você deve ser melhor que ontem e pior do que amanhã, só assim podemos evoluir e chegar a lugares antes nunca imaginados. Se não fosse assim, ainda estaríamos em cavernas escuras fugindo de predadores.
Para dar continuidade ao assunto do post anterior Técnicas comuns de Refatoração, irei descrever mais algumas técnicas comuns de refatoração de código.
Refatoração : Subir Método (Pull Up Method)
Quando duas subclasses possuem o mesmo método, então o método deve ser movido para a superclasse.
Eliminar duplicatas é muito importante, mesmo quando comportamentos duplicados funcionam perfeitamente, eles no futuro podem causar uma série de Bugs, pois com a duplicação, a chance de uma alteração ser feita em um local e esquecida em outro é muito grande.
O caso mais simples da aplicação de Subir Método é quando duas subclasses métodos iguais, neste caso apenas ao copiar esse método para a superclasse resolve o problema.
Outro cenário, mais complicado, é quando subclasses possuem métodos com parâmetros diferentes, escritos de forma diferente, mas que essencialmente possuem o mesmo comportamento. Nesse caso o melhor é com a ajuda de testes, tentar identificar se os métodos realmente são iguais, então a parametrização desses métodos deve ser igualada, para enfim escolher um deles e subi-lo para a superclasse, eliminando o outro.
Um caso especial da aplicação de Subir Método se dá quando uma classe derivada sobrescreve um método da superclasse, mas faz possui exatamente o mesmo comportamento.
Outro caso especial, porém mais estranho de Subir Método, ocorre quando um método é colocado na superclasse, mas referencia atributos e recurso que existem apenas nas classes derivadas, neste o método deve ser abstrato, obrigado cada classe derivada a implementá-lo.
Nesta imagem podemos ver o método “getName()”, que é comum à duas ou mais subclasses de “Emplyee”, sendo movido das subclasses para a super classe, onde ele faz mais sentido existir.
Refatoração : SubirAtributo (Pull Up Field)
Subclasses são desenvolvidas de forma independente e da mesma forma que nos caso de Subir Método, um atributo pode estar duplicado em duas ou mais classes derivadas, nesse caso deve ser movido para a superclasse.
Nesta imagem o atributo “name()”, que é comum à duas ou mais subclasses de “Emplyee”, foi movido das subclasses para a super classe, onde ele faz mais sentido existir.
Refatoração : Descer Método (Push Down Method)
Quando um comportamento existente em uma superclasse é relevante apenas para uma subclasse, deve-se mover este método para a subclasse.
Esta técnica é exatamente oposta a Subir Método, mas da mesma forma faz sentido, quando um método torna-se mais adequado em outro lugar.
Esta técnica é frequentemente usada em conjunto com a técnica Extrair Classe.
Podemos ver o método “getQuota()” é utilizado por apenas uma subclasse de “Emplyee”, neste caso faz mais sentido este método ser movido para a subclasse “Salesman”, para melhorar a coesão da classe pai “Employee”.
Refatoração: Descer Atributo (Push Down Field)
Semelhante a técnica Descer Método, quando um atributo faz sentido para uma das subclasses, esse atributo deve ser movido para a subclasse.
Esta técnica é exatamente oposta a Subir Atributo, mas da mesma forma faz sentido, quando um atributo torna-se mais adequado em outro lugar.
O atributo “quota” é utilizado por apenas uma subclasse de “Emplyee”, neste caso faz mais sentido este atributo ser movido para a subclasse “Salesman”, para melhorar a coesão da superclasse “Employee”.
Refatoração: Extrair Sub-classe (Extract Subclass)
Quando uma classe possui funcionalidades que é usada em apenas algumas de suas instâncias, faz sentido criar uma especialização para classe e mover este subconjunto de funcionalidades para a nova classe especializada.
Essa situação geralmente ocorre quando uma classe possuem um conjunto de características que são ativadas por uma flag ou código especifico.
Como alternativa a esta técnica Extrair Subclasse, pode-se usar Extrair Classe. Isto deixa a escolha entre Herança e Delegação. Optar por Herança torna as coisas mais simples de serem feitas, mas através de delegação se ganha em flexibilidade.
A classe “JobItem” está sendo especializada em “LaborItem”, e o subconjunto de funcionalidades “getUnitPrice()” e “getEmployee()” também foi especializado para a nova classe criada, deste modo a classe “JobItem” fica mais coesa e a classe “LaborItem” fica com comportamento melhor definido.
Refatoração: Extrair Super-classe (Extract Superclass)
Quando duas classes possuem características em comum, deve-se mover esse subconjunto de características para uma superclasse, e especializar esta superclasse com as duas classes iniciais.
Duplicação de código é uma das piores coisas que pode haver em um software, pois uma alteração em um local pode não ser replicada em outro e isso causará inconsistência. A orientação a objetos prove mecanismos para que isso não ocorra, e um desses mecanismos é a herança.
Como alternativa a esta técnica Extrair Superclasse, pode-se usar Extrair Classe . Isto deixa a escolha entre Herança e Delegação. Optar por Herança torna as coisas mais simples de serem feitas, mas através de delegação se ganha em flexibilidade.
Pode-se começar optando pela Herança com Extrair Superclasse e caso as coisas não saiam como previsto, troque a Herança por Delegação.
Na Imagem , as classes “Department” e “Emplyoee” possuem características em comum, e o código nestas classes encontram-se duplicados. Para resolver a situação, as classes foram generalizadas em uma nova classe “Party”, que contem todo o comportamento comum destas classes. O próximo passo é a criação de uma herança da classe “Party” para as classes “Department” e “Employee”, e em seguida, remove-se o código duplicado de “Department” e “Emplyoee”.
Refatoração: Substituir Variável Temporária Por Consulta (ReplaceTempwith Query)
Quando você tem uma variável temporária cujo valor que é o resultado de uma expressão, então você deve substituir essa variável por um método que retorne o valor dessa expressão.
A motivação desta técnica é transformar variáveis temporárias que são locais por métodos que podem ser utilizados em outras partes do código. Além disso, um método bem nomeado é mais compreensível que uma expressão qualquer.
Está técnica é bem parecida com a técnica de extrair método, porém existem diferenças sutis entre as duas. Nesta técnica você não irá substituir uma porção de código com várias linhas, e sim uma única linha onde você atribui a uma variável temporária o valor de uma expressão.
Substituir Variável Temporária Por Consulta é um passo essencial para a utilização da técnica Extrair Método.
A variável temporária “basePrice” que tem o seu valor definido por um expressão, é movido para um novo método “basePrice”, deste modo o valor dessa expressão pode ser utilizado por vários outros métodos desta classe, sem ter o seu código duplicado, além de melhorar a legibilidade do código.
Todas essas técnicas de refatoração de código podem ser facilmente encontradas em IDEs como Eclipse, Netbeans e Intellij, e sua utilização é amplamente recomendada pela comunidade de desenvolvedores em todo mundo.
Para melhor segurança nas refatorações, devemos sempre contar com os testes automatizados, pois estes detectam instantaneamente qualquer coisa que possa ter dado errado durante a refatoração, pois mesmo que o compilador não indique nenhum de compilação, podemos ter alguma erro de lógica ou alguma funcionalidade que passou a ter um comportamento fora do esperado.
Comentários