SlideShare a Scribd company logo
1 of 42
Download to read offline
J820

Refactoring

Design no Código

Helder da Rocha (helder@acm.org)

argonavis.com.br
O que é

argonavis.com.br

Uma técnica de design baseada no código
Refactoring (ou refatoramento) permite que se
altere o design de uma aplicação, grande ou
pequena, alterando o seu código diretamente
É uma prática altamente disciplinada e
previsível. Não é hacking puro e simples.
Visa sempre o melhoramento do código
Refatoramento contínuo melhora o código e a
aplicação inteira continuamente
Todo mundo faz (ou já fez), nem sempre de
maneira disciplinada, porém.

2
Quando aplicar

argonavis.com.br

Sempre que possível
Em TDD, refactorings são essenciais já que a
primeira solução, a mais simples, geralmente
não tem o melhor design
Alterações como "tornar variável private" são
um tipo de refatoramento
Afeta não apenas a variável em questão, mas
todos que dependem dela
O refatoramento consiste em fazer todas as
mudanças necessárias para que o código volte a
funcionar após a alteração.

3
Testes são fundamentais

argonavis.com.br

Refatoramento é mexer no código que está
funcionando
É um grande risco se não houver testes para esse
código
Antes de refatorar, escreva testes de unidade para os
elementos que serão alterados
Execute os testes várias vezes durante o processo
Modifique os testes para mantê-los em dia com o
código que testam
Siga o passo-a-passo recomendado por cada
refatoramento. Vários sugerem quando novos testes
devem ser escritos e executados
4
Experiência
Refatoramentos são simplesmente técnicas
para mexer no design do código

argonavis.com.br

Geralmente é para melhorar o código em
relação às boas práticas OO
Em alguns casos pode piorar nesse aspecto
quando há outros objetivos no processo (ex:
performance)

Refatoramentos refletem experiências testadas
Ganha-se tempo ao se utilizar um padrão de
refatoramento em vez de descobrir tudo sozinho
5
Patterns
O conhecimento de Padrões de projeto (Design
Patterns) não é essencial para utilizar
refatoramentos, mas ajuda bastante

argonavis.com.br

Muitos refatoramentos visam transformar o
código de forma a aplicar um padrão
Outros refatoramentos partem de um padrão de
projeto ou produzem padrões no processo

Um conhecimento geral dos padrões GoF traz
grandes benefícios para qualquer desenvolvedor
6
Exemplo interativo de refactoring

argonavis.com.br

A melhor maneira de entender como funciona o
refatoramento é através de um exemplo
interativo
Utilizaremos o exemplo do primeiro capítulo do
livro "Refactoring", de Martin Fowler
O exemplo mostra um código que "cheira mal"
devido a vários problemas que dificultam o seu
reuso, manutenção, compreensão e até
eficiência
Demonstraremos alguns passos que tornarão o
programa bem melhor

7
argonavis.com.br

Exemplo do livro: Locadora de Videos

8
public class Movie {
public static final int
public static final int
public static final int

CHILRENS = 2;
REGULAR = 0;
NEW_RELEASE = 1;

Movie.java

public String _title;
private int _priceCode;
public Movie(String title, int priceCode) {
_title = title;
_priceCode = priceCode;
}

argonavis.com.br

public int getPriceCode() {
return _priceCode;
}
public void setPriceCode(int arg) {
_priceCode = arg;
}
public String getTitle() {
return _title;
}
}

9
Rental.java
class Rental {
private Movie _movie;
private int _daysRented;
public Rental(Movie movie, int daysRented) {
_movie = movie;
_daysRented = daysRented;
}

argonavis.com.br

public int getDaysRented() {
return _daysRented;
}
public Movie getMovie() {
return _movie;
}
}

10
Customer.java 1/3
class Customer {
private String _name;
private Vector _rentals = new Vector;
public Customer(String name) {
_name = name;
}

argonavis.com.br

public void addRental(Rental arg) {
_rentals.addElement(arg);
}
public String getName() {
return _name;
}
....

11
...
public String statement() {

Customer.java 2/3

double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "n";

argonavis.com.br

while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement();
// Determine amounts for each line
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount += 2;
if (each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
...

12
Customer.java 3/3
...
// Add frequent renter points
frequentRenterPoints++;
// Add bonus for a two-day, new-release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&
each.getDaysRented() > 1)
frequentRenterPoints++;

argonavis.com.br

// Show figures for this rental
result += "t" + each.getMovie().getTitle() + "t" +
Sting.valueOf(thisAmount) + "n";
totalAmount += thisAmount;
}
// Add footer lines
result += "Amount owed is " + String.valueOf(totalAmount) + "n";
result += "You earned " + String.valueOf(frequentRenterPoints) +
" frequent renter points";
return result;
}
}

13
Catálogo de refactorings

argonavis.com.br

Assim como padrões de projeto, técnicas de
refatoramento refletem a experiência adquirida por
programadores experientes que pode ser reutilizada
por todos para alcançar resultados desejados mais
rapidamente e de maneira testada
Assim como padrões de projeto, refatoramentos têm
nome. Além disso, têm uma forma reversível de
aplicação, geralmente em passos pequenos
Deve-se sempre executar testes de unidade em cada
passo, para garantir a reversibilidade
Catálogos de refatoramento geralmente descrevem
como implementar cada alteração detalhadamente
14
Extract Method
Problema: Você tem um fragmento de método que
pode ser agrupado em método independente
Solução: transforme o fragmento em um método cujo
nome explique a sua finalidade.

argonavis.com.br

void printOwing(int amount) {
printBanner();
System.out.println ("name: " + _name);
System.out.println ("amount " + amount);
}
void printOwing() {
printBanner();
printDetails(amount);
}
void printDetails(double amount) {
System.out.println ("name: " + _name);
System.out.println ("amount " + amount);
}

15
Replace Method With Method Object

argonavis.com.br

Problema: Você tem um método longo que usa
variáveis locais de tal maneira que não é possível
aplicar Extract Method
Solução: Transforme o método em um objeto para
que todas as variáveis locais virem atributos

class Order... double price() {
double primaryBasePrice;
double secondaryBasePrice;
double tertiaryBasePrice;
// long computation; ...
}

16
Substitute Algorithm
Problema: Algoritmo de método pode ser melhorado.
Solução: substitua o conteúdo do método com um
algoritmo que faça a mesma coisa mas seja melhor.

argonavis.com.br

String foundPerson(String[] people){
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){ return "Don"; }
if (people[i].equals ("John")){ return "John"; }
if (people[i].equals ("Kent")){ return "Kent"; }
} return "";
}

String foundPerson(String[] people){
List candidates =
Arrays.asList(new String[] {"Don", "John", "Kent"});
for (int i=0; i<people.length; i++)
if (candidates.contains(people[i]))
return people[i]; return "";
}

17
Move Method

argonavis.com.br

Problema: Um método é usado por mais recursos de
outra classe que na classe em que é definido.
Solução: crie novo método com corpo similar na classe
em que é mais usado. Transforme o antigo em simples
delegação ou elimine-o.

Veja também:
Move Field

18
Extract Class

argonavis.com.br

Problema: Você tem uma classe fazendo trabalho
que deveria ser feito por duas classes.
Solução: Crie uma nova classe e transfira métodos e
atributos relevantes para ela.

19
Introduce Local Extension

argonavis.com.br

Problema: Uma classe servidora que você está
usando requer vários métodos adicionais, mas você
não pode modificar a classe.
Solução: crie uma nova classe que contém esses
métodos extras. Faça essa extensão uma subclasse ou
um wrapper da original.

20
Hide Delegate

argonavis.com.br

Problema: Um cliente tem acesso e está chamando
uma classe que é delegada pelo objeto que utiliza.
Solução: Crie métodos no servidor para ocultar o
objeto do acesso pelo cliente.

21
Remove Middle-Man

argonavis.com.br

Problema: Uma classe está fazendo delegações
simples em excesso.
Solução: Faça o cliente delegar diretamente.

22
Replace Data Value With Object

argonavis.com.br

Problema: Você tem um item de dados que requer
dados adicionais ou comportamento.
Solução: transforme o item de dados em um objeto.

23
Encapsulate Collection

argonavis.com.br

Problema: Um método retorna uma Coleção (List,
Set, HashMap) - acesso total e ausência de controle
sobre tipos de dados (tudo é Object)
Solução: Faça-o retornar uma visão read-only dos
dados e forneça métodos de adição e remoção.

24
Replace Type Code With Subclass

argonavis.com.br

Problema: Você tem um código de tipo imutável que
afeta o comportamento de uma classe.
Solução: Substitua o código de tipo com uma
subclasse.

25
Replace Type Code With Class

argonavis.com.br

Problema: Uma classe tem um código numérico de
tipo que não afeta seu comportamento
Solução: Substitua o número com uma nova classe.

26
Replace Type Code With State/Strategy

argonavis.com.br

Problema: Você tem código que representa um tipo e
que afeta o comportamento de uma classe mas não
pode usar subclasses
Solução: Represente o tipo com um objeto de estado.

27
Replace Subclass with Fields

argonavis.com.br

Problema: Você tem subclasses que só variam em
métodos que retornam dados constantes
Solução: mova os métodos para atributos de
superclasses e elimine as subclasses

28
Replace Conditional With Polymorphism

argonavis.com.br

double getSpeed() {
switch (_type) {
case EUROPEAN:
return getBaseSpeed();
case AFRICAN:
return getBaseSpeed() getLoadFactor() * _coconuts;
case NORWEIGIAN_BLUE:
return (_isNailed)
? 0
: getBaseSpeed(_voltage);
} throw new RuntimeException
("Should be unreachable");
}

Problema: Você
tem um tipo
condicional que age
diferentemente
dependendo do tipo
de um objeto.
Solução: Mova
cada bloco para
método em uma
subclasse e faça o
método original
abstrato.
29
Parameterize Method

argonavis.com.br

Problema: Vários métodos fazem coisas similares
mas com diferentes valores contidos no corpo do
objeto
Solução: crie um método que usa um parâmetro para
os valores diferentes.

30
Preserve Whole Object
Problema: Você está recebendo diversos valores de
um objeto e passando-os como parâmetros em uma
chamada
Solução: Mande o objeto inteiro

argonavis.com.br

int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
withinPlan = plan.withinRange(low, high);

withinPlan = plan.withinRange(daysTempRange());

31
Replace Constructor With Factory Method
Problema: Você quer poder realizar mais que simples
construção quando cria um objeto (ou ter mais controle
e flexibilidade ao criar objetos)
Solução: Substitua construtor com um factory method

argonavis.com.br

Employee (int type) {
_type = type;
}

static Employee create(int type) {
return new Employee(type);
}

32
Extract Subclass

argonavis.com.br

Problema: Uma classe tem recursos que só são
utilizados em algumas instâncias
Solução: crie uma subclasse para esse conjunto de
recursos.

33
Extract Superclass

argonavis.com.br

Problema: Você tem duas classes com recursos
similares.
Solução: crie uma subclasse e mova os recursos
comuns à superclasse.

34
Extract Interface

argonavis.com.br

Problema: Vários clientes usam o mesmo
subconjunto da interface de uma classe, ou duas
classes têm parte de sua interface em comum
Solução: extraia o subconjunto em uma interface

35
argonavis.com.br

Form Template Method
Problema: Você tem dois
métodos em subclasses
que realizam passos
similares na mesma
ordem, porém os passos
são implementados de
forma diferente
Solução: Coloque os
passos em métodos com a
mesma assinatura e
depois puxe-os acima na
hierarquia.
36
Replace Inheritance With Delegation

argonavis.com.br

Problema: Uma subclasse usa apenas uma parte da
interface da superclasse ou não deseja herdar dados
Solução: Crie um atributo de dados para a
superclasse, ajuste os métodos para delegar à
superclasse e remova a estrutura de subclasse

37
Replace Delegation With Inheritance

argonavis.com.br

Problema: Você usa delegação e está frequentemente
escrevendo pequenas delegações para toda a interface
Solução: Faça a classe que delega uma subclasse da
delegada

38
Alguns "cheiros ruins" e suas soluções
Código duplicado
Extract Method, Extract Class, Pull Up Method, Form
Template Method

Intimidade inapropriada
Mome Method, Change Bidirectional Association to
Unidirectional, Replace Inheritance with Delegation

argonavis.com.br

Classe gigante
Extract Class, Extract Subclass, Extract Interface,
Replace Data Value with Object

Método gigante
Extract Method, Replace Method with Method Object,
Decompose Conditional
39
Mais Refatoramentos
Veja o catálogo do Martin Fowler (do livro Refactoring)
em www.refactoring.com/catalog
Procure descobrir refatoramentos específicos para a
área no quel você está pesquisando

argonavis.com.br

J2EE
Aplicações gráficas
Concorrência e programação paralela

Refatoramento, Padrões de Projeto, estratégias
(aplicações de patterns / idioms) e Melhores Práticas
estão sempre relacionados
Todos fornecem experiências valiosas que melhoram a
produtividade e utilização dos recursos de uma linguagem
na solução de problemas de design.
40
Fontes

argonavis.com.br

[1] Martin Fowler, "Refactoring: improving the design of
existing code". Addison-Wesley Object Technology
Series, 2000
[2] Martin Fowler. "On-line Refactoring Catalog".
www.refactoring.com/catalog/. Fonte dos diagramas e
imagens.

41
Curso J820
Produtividade e Qualidade em Java:
Ferramentas e Metodologias
Revisão 1.1

© 2002, 2003, Helder da Rocha
(helder@acm.org)

argonavis.com.br

More Related Content

What's hot

TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSFábio Miranda
 
Dojo de programação - Dia de Java - UFSCar
Dojo de programação - Dia de Java - UFSCarDojo de programação - Dia de Java - UFSCar
Dojo de programação - Dia de Java - UFSCarLuiz Ribeiro
 
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Caelum
 
Como escrever bons testes! - Dex transforming days
Como escrever bons testes! - Dex transforming days Como escrever bons testes! - Dex transforming days
Como escrever bons testes! - Dex transforming days Danilo Pereira De Luca
 
Como o Cucumber Funciona
Como o Cucumber FuncionaComo o Cucumber Funciona
Como o Cucumber FuncionaLaís Berlatto
 
DDD + BDD + TDD - RF 2015
DDD + BDD + TDD - RF 2015 DDD + BDD + TDD - RF 2015
DDD + BDD + TDD - RF 2015 Eduardo Bregaida
 

What's hot (11)

TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOS
 
Dojo de programação - Dia de Java - UFSCar
Dojo de programação - Dia de Java - UFSCarDojo de programação - Dia de Java - UFSCar
Dojo de programação - Dia de Java - UFSCar
 
BDD: Cucumber + Selenium + Java
BDD: Cucumber + Selenium + JavaBDD: Cucumber + Selenium + Java
BDD: Cucumber + Selenium + Java
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
 
GUI Aplicações Gráficas
GUI Aplicações Gráficas GUI Aplicações Gráficas
GUI Aplicações Gráficas
 
Como escrever bons testes! - Dex transforming days
Como escrever bons testes! - Dex transforming days Como escrever bons testes! - Dex transforming days
Como escrever bons testes! - Dex transforming days
 
Labs Jogos Java
Labs Jogos JavaLabs Jogos Java
Labs Jogos Java
 
Como o Cucumber Funciona
Como o Cucumber FuncionaComo o Cucumber Funciona
Como o Cucumber Funciona
 
POO - 09 - Entradas e Saídas em Java
POO - 09 - Entradas e Saídas em JavaPOO - 09 - Entradas e Saídas em Java
POO - 09 - Entradas e Saídas em Java
 
DDD + BDD + TDD - RF 2015
DDD + BDD + TDD - RF 2015 DDD + BDD + TDD - RF 2015
DDD + BDD + TDD - RF 2015
 

Similar to Refactoring técnica de design baseada no código

Domain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHDomain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHGiovanni Bassi
 
ZeroBugsProject - Técnicas de programação efetivas
ZeroBugsProject - Técnicas de programação efetivasZeroBugsProject - Técnicas de programação efetivas
ZeroBugsProject - Técnicas de programação efetivasRafael Chinelato Del Nero
 
Intro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverIntro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverEduardo Jorge
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoJuciellen Cabrera
 
Refactory Worshop
Refactory WorshopRefactory Worshop
Refactory Worshopguestd37c23
 
qualidade de código: boas práticas, princípios e padrões
qualidade de código: boas práticas, princípios e padrõesqualidade de código: boas práticas, princípios e padrões
qualidade de código: boas práticas, princípios e padrõesedgarddavidson.com
 
Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Natanael Fonseca
 
Pattners Everywhere, Even in Javascript
Pattners Everywhere, Even in JavascriptPattners Everywhere, Even in Javascript
Pattners Everywhere, Even in JavascriptGustavo Corrêa Alves
 
Exemplos de Design Patterns em Java
Exemplos de Design Patterns em JavaExemplos de Design Patterns em Java
Exemplos de Design Patterns em Javaalexmacedo
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
Boas Práticas de programação WordPress
Boas Práticas de programação WordPressBoas Práticas de programação WordPress
Boas Práticas de programação WordPressThiago Mendes
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojofabioginzel
 
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)Carlos Duarte do Nascimento
 
Desenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App EngineDesenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App EngineCampus Party Brasil
 
Padrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgePadrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgeLorran Pegoretti
 
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a dia
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a diaSobre code smells, refactoring e design: como SOLID pode te ajudar no dia a dia
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a diaElaine Naomi
 

Similar to Refactoring técnica de design baseada no código (20)

Domain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHDomain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BH
 
ZeroBugsProject - Técnicas de programação efetivas
ZeroBugsProject - Técnicas de programação efetivasZeroBugsProject - Técnicas de programação efetivas
ZeroBugsProject - Técnicas de programação efetivas
 
Intro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverIntro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserver
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no código
 
Refactory Worshop
Refactory WorshopRefactory Worshop
Refactory Worshop
 
qualidade de código: boas práticas, princípios e padrões
qualidade de código: boas práticas, princípios e padrõesqualidade de código: boas práticas, princípios e padrões
qualidade de código: boas práticas, princípios e padrões
 
Code Smells
Code SmellsCode Smells
Code Smells
 
Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Pattners Everywhere, Even in Javascript
Pattners Everywhere, Even in JavascriptPattners Everywhere, Even in Javascript
Pattners Everywhere, Even in Javascript
 
Working with legacy code 3
Working with legacy code 3Working with legacy code 3
Working with legacy code 3
 
Exemplos de Design Patterns em Java
Exemplos de Design Patterns em JavaExemplos de Design Patterns em Java
Exemplos de Design Patterns em Java
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
Clean Code
Clean CodeClean Code
Clean Code
 
Boas Práticas de programação WordPress
Boas Práticas de programação WordPressBoas Práticas de programação WordPress
Boas Práticas de programação WordPress
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojo
 
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
 
Desenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App EngineDesenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App Engine
 
Padrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e BridgePadrões de projeto - Adapter, Proxy, Composite e Bridge
Padrões de projeto - Adapter, Proxy, Composite e Bridge
 
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a dia
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a diaSobre code smells, refactoring e design: como SOLID pode te ajudar no dia a dia
Sobre code smells, refactoring e design: como SOLID pode te ajudar no dia a dia
 

More from Denis L Presciliano

Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsDenis L Presciliano
 
Coleções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsColeções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsDenis L Presciliano
 
Funcamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteFuncamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteDenis L Presciliano
 
Reuso com Herança e Composição
Reuso com Herança e ComposiçãoReuso com Herança e Composição
Reuso com Herança e ComposiçãoDenis L Presciliano
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntDenis L Presciliano
 
Tipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoTipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoDenis L Presciliano
 
Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Denis L Presciliano
 
Configuração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntConfiguração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntDenis L Presciliano
 
Programação Orientada a objetos em Java
Programação Orientada a objetos em JavaProgramação Orientada a objetos em Java
Programação Orientada a objetos em JavaDenis L Presciliano
 

More from Denis L Presciliano (20)

Funmentos de Objetos Remotos
Funmentos de Objetos RemotosFunmentos de Objetos Remotos
Funmentos de Objetos Remotos
 
Fundamentos de JDBC
Fundamentos de JDBCFundamentos de JDBC
Fundamentos de JDBC
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
 
Classes internas
Classes internasClasses internas
Classes internas
 
Entrada e Saída
Entrada e SaídaEntrada e Saída
Entrada e Saída
 
Coleções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsColeções Propriedade, Resources e Strings
Coleções Propriedade, Resources e Strings
 
Funcamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteFuncamentos de Programação Concorrente
Funcamentos de Programação Concorrente
 
Testes de Unidade com JUnit
Testes de Unidade com JUnitTestes de Unidade com JUnit
Testes de Unidade com JUnit
 
Erros, exceções e asserções
Erros, exceções e asserçõesErros, exceções e asserções
Erros, exceções e asserções
 
Interfaces e Porlimosfismo
Interfaces e PorlimosfismoInterfaces e Porlimosfismo
Interfaces e Porlimosfismo
 
Reuso com Herança e Composição
Reuso com Herança e ComposiçãoReuso com Herança e Composição
Reuso com Herança e Composição
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache Ant
 
Pacotes e Encapsulamento
Pacotes e EncapsulamentoPacotes e Encapsulamento
Pacotes e Encapsulamento
 
Como criar classes e objetos
Como criar classes e objetosComo criar classes e objetos
Como criar classes e objetos
 
Tipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoTipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxo
 
Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Como usar a documentação da API Java 2
Como usar a documentação da API Java 2
 
Configuração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntConfiguração do ambiente JEdit + Ant
Configuração do ambiente JEdit + Ant
 
Programação Orientada a objetos em Java
Programação Orientada a objetos em JavaProgramação Orientada a objetos em Java
Programação Orientada a objetos em Java
 
Introdução a tecnologia Java
Introdução a tecnologia JavaIntrodução a tecnologia Java
Introdução a tecnologia Java
 
Fundamentos de Sockets
Fundamentos de SocketsFundamentos de Sockets
Fundamentos de Sockets
 

Refactoring técnica de design baseada no código

  • 1. J820 Refactoring Design no Código Helder da Rocha (helder@acm.org) argonavis.com.br
  • 2. O que é argonavis.com.br Uma técnica de design baseada no código Refactoring (ou refatoramento) permite que se altere o design de uma aplicação, grande ou pequena, alterando o seu código diretamente É uma prática altamente disciplinada e previsível. Não é hacking puro e simples. Visa sempre o melhoramento do código Refatoramento contínuo melhora o código e a aplicação inteira continuamente Todo mundo faz (ou já fez), nem sempre de maneira disciplinada, porém. 2
  • 3. Quando aplicar argonavis.com.br Sempre que possível Em TDD, refactorings são essenciais já que a primeira solução, a mais simples, geralmente não tem o melhor design Alterações como "tornar variável private" são um tipo de refatoramento Afeta não apenas a variável em questão, mas todos que dependem dela O refatoramento consiste em fazer todas as mudanças necessárias para que o código volte a funcionar após a alteração. 3
  • 4. Testes são fundamentais argonavis.com.br Refatoramento é mexer no código que está funcionando É um grande risco se não houver testes para esse código Antes de refatorar, escreva testes de unidade para os elementos que serão alterados Execute os testes várias vezes durante o processo Modifique os testes para mantê-los em dia com o código que testam Siga o passo-a-passo recomendado por cada refatoramento. Vários sugerem quando novos testes devem ser escritos e executados 4
  • 5. Experiência Refatoramentos são simplesmente técnicas para mexer no design do código argonavis.com.br Geralmente é para melhorar o código em relação às boas práticas OO Em alguns casos pode piorar nesse aspecto quando há outros objetivos no processo (ex: performance) Refatoramentos refletem experiências testadas Ganha-se tempo ao se utilizar um padrão de refatoramento em vez de descobrir tudo sozinho 5
  • 6. Patterns O conhecimento de Padrões de projeto (Design Patterns) não é essencial para utilizar refatoramentos, mas ajuda bastante argonavis.com.br Muitos refatoramentos visam transformar o código de forma a aplicar um padrão Outros refatoramentos partem de um padrão de projeto ou produzem padrões no processo Um conhecimento geral dos padrões GoF traz grandes benefícios para qualquer desenvolvedor 6
  • 7. Exemplo interativo de refactoring argonavis.com.br A melhor maneira de entender como funciona o refatoramento é através de um exemplo interativo Utilizaremos o exemplo do primeiro capítulo do livro "Refactoring", de Martin Fowler O exemplo mostra um código que "cheira mal" devido a vários problemas que dificultam o seu reuso, manutenção, compreensão e até eficiência Demonstraremos alguns passos que tornarão o programa bem melhor 7
  • 8. argonavis.com.br Exemplo do livro: Locadora de Videos 8
  • 9. public class Movie { public static final int public static final int public static final int CHILRENS = 2; REGULAR = 0; NEW_RELEASE = 1; Movie.java public String _title; private int _priceCode; public Movie(String title, int priceCode) { _title = title; _priceCode = priceCode; } argonavis.com.br public int getPriceCode() { return _priceCode; } public void setPriceCode(int arg) { _priceCode = arg; } public String getTitle() { return _title; } } 9
  • 10. Rental.java class Rental { private Movie _movie; private int _daysRented; public Rental(Movie movie, int daysRented) { _movie = movie; _daysRented = daysRented; } argonavis.com.br public int getDaysRented() { return _daysRented; } public Movie getMovie() { return _movie; } } 10
  • 11. Customer.java 1/3 class Customer { private String _name; private Vector _rentals = new Vector; public Customer(String name) { _name = name; } argonavis.com.br public void addRental(Rental arg) { _rentals.addElement(arg); } public String getName() { return _name; } .... 11
  • 12. ... public String statement() { Customer.java 2/3 double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "n"; argonavis.com.br while (rentals.hasMoreElements()) { double thisAmount = 0; Rental each = (Rental) rentals.nextElement(); // Determine amounts for each line switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: thisAmount += 2; if (each.getDaysRented() > 2) thisAmount += (each.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: thisAmount += each.getDaysRented() * 3; break; case Movie.CHILDRENS: thisAmount += 1.5; if (each.getDaysRented() > 3) thisAmount += (each.getDaysRented() - 3) * 1.5; break; } ... 12
  • 13. Customer.java 3/3 ... // Add frequent renter points frequentRenterPoints++; // Add bonus for a two-day, new-release rental if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) frequentRenterPoints++; argonavis.com.br // Show figures for this rental result += "t" + each.getMovie().getTitle() + "t" + Sting.valueOf(thisAmount) + "n"; totalAmount += thisAmount; } // Add footer lines result += "Amount owed is " + String.valueOf(totalAmount) + "n"; result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; return result; } } 13
  • 14. Catálogo de refactorings argonavis.com.br Assim como padrões de projeto, técnicas de refatoramento refletem a experiência adquirida por programadores experientes que pode ser reutilizada por todos para alcançar resultados desejados mais rapidamente e de maneira testada Assim como padrões de projeto, refatoramentos têm nome. Além disso, têm uma forma reversível de aplicação, geralmente em passos pequenos Deve-se sempre executar testes de unidade em cada passo, para garantir a reversibilidade Catálogos de refatoramento geralmente descrevem como implementar cada alteração detalhadamente 14
  • 15. Extract Method Problema: Você tem um fragmento de método que pode ser agrupado em método independente Solução: transforme o fragmento em um método cujo nome explique a sua finalidade. argonavis.com.br void printOwing(int amount) { printBanner(); System.out.println ("name: " + _name); System.out.println ("amount " + amount); } void printOwing() { printBanner(); printDetails(amount); } void printDetails(double amount) { System.out.println ("name: " + _name); System.out.println ("amount " + amount); } 15
  • 16. Replace Method With Method Object argonavis.com.br Problema: Você tem um método longo que usa variáveis locais de tal maneira que não é possível aplicar Extract Method Solução: Transforme o método em um objeto para que todas as variáveis locais virem atributos class Order... double price() { double primaryBasePrice; double secondaryBasePrice; double tertiaryBasePrice; // long computation; ... } 16
  • 17. Substitute Algorithm Problema: Algoritmo de método pode ser melhorado. Solução: substitua o conteúdo do método com um algoritmo que faça a mesma coisa mas seja melhor. argonavis.com.br String foundPerson(String[] people){ for (int i = 0; i < people.length; i++) { if (people[i].equals ("Don")){ return "Don"; } if (people[i].equals ("John")){ return "John"; } if (people[i].equals ("Kent")){ return "Kent"; } } return ""; } String foundPerson(String[] people){ List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"}); for (int i=0; i<people.length; i++) if (candidates.contains(people[i])) return people[i]; return ""; } 17
  • 18. Move Method argonavis.com.br Problema: Um método é usado por mais recursos de outra classe que na classe em que é definido. Solução: crie novo método com corpo similar na classe em que é mais usado. Transforme o antigo em simples delegação ou elimine-o. Veja também: Move Field 18
  • 19. Extract Class argonavis.com.br Problema: Você tem uma classe fazendo trabalho que deveria ser feito por duas classes. Solução: Crie uma nova classe e transfira métodos e atributos relevantes para ela. 19
  • 20. Introduce Local Extension argonavis.com.br Problema: Uma classe servidora que você está usando requer vários métodos adicionais, mas você não pode modificar a classe. Solução: crie uma nova classe que contém esses métodos extras. Faça essa extensão uma subclasse ou um wrapper da original. 20
  • 21. Hide Delegate argonavis.com.br Problema: Um cliente tem acesso e está chamando uma classe que é delegada pelo objeto que utiliza. Solução: Crie métodos no servidor para ocultar o objeto do acesso pelo cliente. 21
  • 22. Remove Middle-Man argonavis.com.br Problema: Uma classe está fazendo delegações simples em excesso. Solução: Faça o cliente delegar diretamente. 22
  • 23. Replace Data Value With Object argonavis.com.br Problema: Você tem um item de dados que requer dados adicionais ou comportamento. Solução: transforme o item de dados em um objeto. 23
  • 24. Encapsulate Collection argonavis.com.br Problema: Um método retorna uma Coleção (List, Set, HashMap) - acesso total e ausência de controle sobre tipos de dados (tudo é Object) Solução: Faça-o retornar uma visão read-only dos dados e forneça métodos de adição e remoção. 24
  • 25. Replace Type Code With Subclass argonavis.com.br Problema: Você tem um código de tipo imutável que afeta o comportamento de uma classe. Solução: Substitua o código de tipo com uma subclasse. 25
  • 26. Replace Type Code With Class argonavis.com.br Problema: Uma classe tem um código numérico de tipo que não afeta seu comportamento Solução: Substitua o número com uma nova classe. 26
  • 27. Replace Type Code With State/Strategy argonavis.com.br Problema: Você tem código que representa um tipo e que afeta o comportamento de uma classe mas não pode usar subclasses Solução: Represente o tipo com um objeto de estado. 27
  • 28. Replace Subclass with Fields argonavis.com.br Problema: Você tem subclasses que só variam em métodos que retornam dados constantes Solução: mova os métodos para atributos de superclasses e elimine as subclasses 28
  • 29. Replace Conditional With Polymorphism argonavis.com.br double getSpeed() { switch (_type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() getLoadFactor() * _coconuts; case NORWEIGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); } throw new RuntimeException ("Should be unreachable"); } Problema: Você tem um tipo condicional que age diferentemente dependendo do tipo de um objeto. Solução: Mova cada bloco para método em uma subclasse e faça o método original abstrato. 29
  • 30. Parameterize Method argonavis.com.br Problema: Vários métodos fazem coisas similares mas com diferentes valores contidos no corpo do objeto Solução: crie um método que usa um parâmetro para os valores diferentes. 30
  • 31. Preserve Whole Object Problema: Você está recebendo diversos valores de um objeto e passando-os como parâmetros em uma chamada Solução: Mande o objeto inteiro argonavis.com.br int low = daysTempRange().getLow(); int high = daysTempRange().getHigh(); withinPlan = plan.withinRange(low, high); withinPlan = plan.withinRange(daysTempRange()); 31
  • 32. Replace Constructor With Factory Method Problema: Você quer poder realizar mais que simples construção quando cria um objeto (ou ter mais controle e flexibilidade ao criar objetos) Solução: Substitua construtor com um factory method argonavis.com.br Employee (int type) { _type = type; } static Employee create(int type) { return new Employee(type); } 32
  • 33. Extract Subclass argonavis.com.br Problema: Uma classe tem recursos que só são utilizados em algumas instâncias Solução: crie uma subclasse para esse conjunto de recursos. 33
  • 34. Extract Superclass argonavis.com.br Problema: Você tem duas classes com recursos similares. Solução: crie uma subclasse e mova os recursos comuns à superclasse. 34
  • 35. Extract Interface argonavis.com.br Problema: Vários clientes usam o mesmo subconjunto da interface de uma classe, ou duas classes têm parte de sua interface em comum Solução: extraia o subconjunto em uma interface 35
  • 36. argonavis.com.br Form Template Method Problema: Você tem dois métodos em subclasses que realizam passos similares na mesma ordem, porém os passos são implementados de forma diferente Solução: Coloque os passos em métodos com a mesma assinatura e depois puxe-os acima na hierarquia. 36
  • 37. Replace Inheritance With Delegation argonavis.com.br Problema: Uma subclasse usa apenas uma parte da interface da superclasse ou não deseja herdar dados Solução: Crie um atributo de dados para a superclasse, ajuste os métodos para delegar à superclasse e remova a estrutura de subclasse 37
  • 38. Replace Delegation With Inheritance argonavis.com.br Problema: Você usa delegação e está frequentemente escrevendo pequenas delegações para toda a interface Solução: Faça a classe que delega uma subclasse da delegada 38
  • 39. Alguns "cheiros ruins" e suas soluções Código duplicado Extract Method, Extract Class, Pull Up Method, Form Template Method Intimidade inapropriada Mome Method, Change Bidirectional Association to Unidirectional, Replace Inheritance with Delegation argonavis.com.br Classe gigante Extract Class, Extract Subclass, Extract Interface, Replace Data Value with Object Método gigante Extract Method, Replace Method with Method Object, Decompose Conditional 39
  • 40. Mais Refatoramentos Veja o catálogo do Martin Fowler (do livro Refactoring) em www.refactoring.com/catalog Procure descobrir refatoramentos específicos para a área no quel você está pesquisando argonavis.com.br J2EE Aplicações gráficas Concorrência e programação paralela Refatoramento, Padrões de Projeto, estratégias (aplicações de patterns / idioms) e Melhores Práticas estão sempre relacionados Todos fornecem experiências valiosas que melhoram a produtividade e utilização dos recursos de uma linguagem na solução de problemas de design. 40
  • 41. Fontes argonavis.com.br [1] Martin Fowler, "Refactoring: improving the design of existing code". Addison-Wesley Object Technology Series, 2000 [2] Martin Fowler. "On-line Refactoring Catalog". www.refactoring.com/catalog/. Fonte dos diagramas e imagens. 41
  • 42. Curso J820 Produtividade e Qualidade em Java: Ferramentas e Metodologias Revisão 1.1 © 2002, 2003, Helder da Rocha (helder@acm.org) argonavis.com.br