23
Working with legacy code

Working with legacy code 3

Embed Size (px)

DESCRIPTION

A presentation about Michael Feathers' Book "Working with legacy code 3"

Citation preview

Page 1: Working with legacy code 3

Working with legacy code

Page 2: Working with legacy code 3

Extract Interface

Utilizar interface ao invés de classes concretas podem ajudar no design, no polimorfismo e especialmente em testes.

Page 3: Working with legacy code 3

public class PayTransaction extends Transaction {

public PayTransaction (Database db, TransactionRecorder log) {

public void run() {

...

}

}

}

Page 4: Working with legacy code 3

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.

Page 5: Working with legacy code 3

• 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).

Page 6: Working with legacy code 3

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.

Page 7: Working with legacy code 3

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.

Page 8: Working with legacy code 3

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”.

Page 9: Working with legacy code 3

“This class is too big and I don't want it to get any bigger”

Page 10: Working with legacy code 3

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)

Page 11: Working with legacy code 3

evaluate branchingExpression nextTerm addVariable

causalExpression hasMoreTerms

variableExpression

valueExpression

Em geral, as classe apresentam nomes com prefixos ou sufixos similares como segue abaixo:

Page 12: Working with legacy code 3

RuleEvaluator+ evaluate(string)+ addVariable(string, int)

SymbolTable+ addVariable(string, int)

RuleParser+ parse(string): Expression

TermTokenizer+ nextTerm(): string+ hasMoreTerms: boolean

Expression+ evaluateWith(SymbolTable)

Page 13: Working with legacy code 3

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.

Page 14: Working with legacy code 3

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.

Page 15: Working with legacy code 3

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.

Page 16: Working with legacy code 3

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.

Page 17: Working with legacy code 3

Reservation- duration: int- dailyRate: int- date: Date- customer: Costumer- fees: List+ extend(days)+ extendForWeek()+ addFee(FeeRider)<<delegates>>- getPrincipalFee(): int+ getTotalFee() :int+ getAdditionalFee(): int

Page 18: Working with legacy code 3

duration

getPrincipalFee

extend

dailyRateextendForWeek

date

customer

getTotalFeegetAdditionalFees

fees

addFee

Esquema da classe Reservation

Page 19: Working with legacy code 3

duration

getPrincipalFee

extend

dailyRate

extendForWeek

date

customer

getTotalFeegetAdditionalFees

fees

addFee

Métodos aglomerados em Reservation

Page 20: Working with legacy code 3

duration

getPrincipalFee

extend

dailyRate

extendForWeek

date

customer

getTotalFee

getAdditionalFees

fees

addFee

Métodos aglomerados em outra classe

Page 21: Working with legacy code 3

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.

Page 22: Working with legacy code 3

...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.

Ao adicionar novas funcionalidades lembre-se...

Page 23: Working with legacy code 3

Working with Legacy Code by Michael Feather

Recomendação do autor:

• Livro Refactoring: Improving the Design of Existing Code (Martin Fowler)