2. Extract Interface
Utilizar interface ao invés de
classes concretas podem ajudar no
design, no polimorfismo e
especialmente em testes.
3. public class PayTransaction extends Transaction {
public PayTransaction (Database db,
TransactionRecorder log) {
public void run() {
...
}
}
}
4. Parâmetros como Database db e
TransactionRecorder log podem ser opcionais em
um testes, na verdade criaremos superclasses
com uma implementação simples ou vazia dos
métodos existentes.
Também as interface costumam melhorar o
modelo do código, pois pensa-se primeiro nos
métodos necessários sem sua implementação e
nos parâmetros necessário.
5. • A maioria das IDEs atuais traz ferramentas
como Extract Interface. Procure usá-las
especialmente quando há muitas
implementações da classe.
• Cuidado com os métodos estáticos, pois eles
não podem fazer parte da interface.
• Procure extrair os métodos de forma
incremental à medida que se escreve testes
para os mesmos(Testes da classe final).
6. Passo a passo
• Criar a interface com nome
apropriado sem nenhum método.
• Implementar a interface nas
classes desejadas
• Substituir as chamadas das
classes pela da interface.
• O código não irá compilar
enquanto não se extrair as
assinaturas dos métodos para
interface.
7. Extract Implementer
Mesma finalidade de Extract
Interface, no entanto, a classe se
tornará a Interface e a será criada
uma cópia idêntica da classe atual,
mas com outro nome.
8. Razões
• Em geral o nome da classe atual é
o nome ideal para interface, pois é
nela que contém a “idéia”, e a
classe é como a idéia será
executada.
• Muitos usam prefixos em
interfaces, no entanto, é muito
ruim trabalhar com tais nomes
pois fere o princípio conhecido
como “well-named”.
9. “This class is too big and I don't want
it to get any bigger”
10. RuleParser
- current: string
- variables: Hasmap
- currentPosition: int
+ evaluate(string): int
+ branchExpression(Node left, Node right): int
+ causalExpression(Node left, Node right): int
+ variableExpression(Node node): int
+ nextTerm(): string
- hasMoreTerms(): boolean
+ addVariable(string name, int value)
11. Em geral, as classe apresentam nomes
com prefixos ou sufixos similares como
segue abaixo:
evaluate branchingExpression nextTerm addVariable
causalExpression hasMoreTerms
variableExpression
valueExpression
13. Heurística
• Group methods – agrupar métodos por
nome ou funcionalidade. É pouco
custoso e facilita o entendimento em
grandes classes.
• Look at Hidden Methods – Classes
grandes costumam ter diversos
métodos privados, se necessário
converta-os em públicos para testes.
Muitas vezes chega-se a conclusão de
criar uma nova classe com esses
métodos.
14. Heurística
• Look for decisions that can change –
foque nas tomadas de decisões dos
métodos já criados, verifique se usa
conexão com banco de dados, grandes
APIs, hard-coded.
• Look for internal relationships – Em
geral classes muito grandes com
diversos atributos e métodos não são
chamam um pelo outro em todos os
lugares, então, conclui que pode-se
descobrir quais métodos devem ser
testados.
15. Heurística
• Look for the Primary Resposibility –
Tente descrever uma classe em uma
única fase.
• When all else fails, do some Scratch
Refactoring.
• Focus on the current work – Mude
apenas o necessário. Não se trata de
uma reforma completa, apenas uma
refatoração suficiente para que haja
maior sentimento de confiança na
alteração real.
16. Feature sketch
• É um esquema muito útil e simples
para descobrir o relacionamento
interno entre os métodos e atributos
das classes.
• Agrupa-se os métodos e atributos
por similaridade de nome ou
funcionalidade.
17. Reservation
- duration: int
- dailyRate: int
- date: Date
- customer: Costumer
- fees: List
+ extend(days)
+ extendForWeek()
+ addFee(FeeRider)<<delegates>>
- getPrincipalFee(): int
+ getTotalFee() :int
+ getAdditionalFee(): int
18. Esquema da classe Reservation
duration
extend
extendForWeek
dailyRate
addFee
date
customer
fees
getPrincipalFee
getAdditionalFees
getTotalFee
19. Métodos aglomerados em Reservation
extend
duration
extendForWeek
addFee
dailyRate
date
fees
customer
getPrincipalFee
getAdditionalFees
getTotalFee
20. Métodos aglomerados em outra classe
duration
extend
extendForWeek
dailyRate
addFee
date
getAdditionalFees
customer fees
getTotalFee
getPrincipalFee
21. Interface segragation Principle
Grandes classes que implementam
interfaces geralmente não usufruem
de todos os métodos, então, é mais
interessante criar diversas
interfaces menores e implementar
quantas forem necessárias nas
classes.
22. Ao adicionar novas funcionalidades lembre-se...
...que ao adicionar novas
funcionalidades, acima de tudo, o
design atual já funcionava. Sejam
classes grandes ou sem padrões, elas
atualmente exercem funções e muitas
vezes de maneira eficiente.
23. Working with Legacy Code by Michael Feather
Recomendação do autor:
• Livro Refactoring: Improving the Design of Existing Code
(Martin Fowler)