You are on page 1of 14

UNIVERSIDADE FEDERAL DE SERGIPE DEPARTAMENTO DE COMPUTAO DESENVOLVIMENTO DE SOFTWARE III

ANLISE SOBRE REFATORAO

Profa. Renata Carvalho

SO CRISTVO/SE ABRIL/2013

1.Definio - Refatorao o processo de melhoria de leitura de um programa sem modificar a sua funcionalidade, evitando a manuteno. Alm da melhora do design, a refatorao ajuda no retardamento do processo de decomposio do software, aps sucessivas modificaes. Para se certificar que a refatorao foi efetuada com sucesso preciso gerar teste (automatizados). Caso o resultado do teste antes e depois da refatorao forem iguais, significa dizer que a refatorao foi um sucesso. 2. Sujeiras - Cdigo duplicado Como o nome do problema j diz, ocorre quando funcionalidades de um cdigo esto idnticas na mesma classe, ou em subclasses filhas da mesma superclasse ou ento em classes que no esto relacionadas.

- Mtodo longo Ocorre quando existem mtodos muito longos, com muitos parmetros e variveis locais sem necessidade. Para evitar a falta de entendimento do cdigo necessrio nome-lo de forma curta, sucinta, determinando o escopo do mtodo mesmo sem saber o que h dentro dele.

- Classe extensa Quando se tem uma classe muito grande com vrias variveis de instncias criadas, muito provavelmente dever existir algum mtodo que foi duplicado. Assim como muitas instncias podem gerar cdigo duplicado, mtodos com muito cdigos tambm podem gerar uma carga extra de mtodos que podem ser simplificados.

- Lista de parmetros longa s vezes existem mtodos que necessitam de vrias informaes para concluir seu objetivo. Por isso muitas vezes os programadores abordam uma extensa lista de parmetros em um mtodo, quando na verdade tudo que o mtodo precisa so objetos que podem ser passados a eles de outra forma, atravs de outros mtodos, por exemplo. Existe porm uma exceo a isso: quando no se quer criar uma dependncia entre um objeto e um objeto maior. Nesse caso necessrio desempacotar os dados e envi-los como parmetros. - Mudana divergente Ocorre quando uma classe tem que ser alterada por algum motivo diferente de modos diferentes.

- Amplitude da mudana definido quando sempre h uma mudana de cdigo feita por algum fator externo, por motivos quaisquer. Quando as alteraes esto em toda parte difcil de identifica-las e fazer alguma mudana, fazendo muitas alteraes pequenas em muitas classes diferentes. - Caracterstica Invejada Esse problema ocorre quando um mtodo necessita constantemente de um objeto de outra classe para realizar as operaes necessrias. Porm h mtodos que usam vrios objetos de vrias classes. Nesse caso, coloca-se o mtodo na classe que mais utiliza os objetos. - Dados semanticamente ligados Dados geralmente costumam andar agrupados. Por exemplo, pode-se encontrar trs ou quatro dados juntos em muitos lugares: campos em algumas classes,parmetros em muitas assinaturas de mtodos. Ficamos cientes, ento, que um grupo de dados deve ser criados seus prprios objetos. - Obsesso primitiva Devem ser criadas classes que no so distinguveis dos tipos primrios de dados. - Comando de seleo Em muitos casos, quando existe um comando de seleo (switch), provavelmente existir esse mesmo comando em outra parte do cdigo. Quando for necessrio modificar ou acrescentar algum comando de seleo, dever ser feito em todo o cdigo. Para evitar esse tipo de atraso, pode-se usar o polimorfismo. - Hierarquia de Herana Paralela Esse um caso particular de amplitude da mudana. Ocorre quando se deve criar uma subclasse dentro de uma classe, criando tambm uma subclasse de outra. possvel identificar esse problema pois os prefixos dos nomes em uma classe em uma hierarquia so os mesmo da hierarquia da outra. - Classe preguiosa So classes que no so mais utilizadas devido a esquemas de refatorao ou ento devido a alteraes que foram planejadas mas no executadas. - Generalizao Especulativa Esse tipo de problema acontece quando se tem uma classe que foi criada por mera especulao: a classe no usada e somente foi codificada por meios de precauo. Ela pode ser facilmente identificada quando os nicos usurios de um mtodo ou classe forem os casos de teste.

- Atributo temporrio Ocorre quando um objeto recebe apenas um valor em determinadas circunstancias, sendo complicado de entender porque um objeto normalmente precisa de todas as variveis. Isso ocorre geralmente quando um algoritmo complicado precisa de diversas variveis. - Cadeias de Mensagens Ocorre quando existem sucessivas chamadas de objetos para outros objetos. Isso observvel atravs dos mtodos getThis. - Classe que serve como intermediria Isso ocorre quando muitos mtodos delegam sua funo para outra classe. - Intimidade inapropriada Ocorre quando uma subclasse possui informaes em demasia da sua classe pai. - Classes alternativas com Interfaces Diferentes Ocorre quando existem classes que possuem certa semelhana mas tem interfaces diferentes. - Biblioteca de Classe Incompleta Ocorre quando no h implementao adequada em biblioteca que voc precisaria utilizar. - Classes de Dados Esses tipos de classes no possuem nenhuma funcionalidade especfica. Elas simplesmente armazenam informaes que por ventura sero atribudas a outras classes que a necessitem. - Herana Recusada Ocorre quando a subclasse herda dados e mtodos da superclasse que no so necessrios . O ideal que as superclasses s passem a herana a subclasses que possui funcionalidades em comum. - Comentrios Ocorre quando um mtodo/ classe possui muitos comentrios. Isso ocorre quando mtodo de refatorao no foi feito adequadamente.

3. Compondo mtodos 3.1 Extrair Mtodos Esse tipo de tcnica efetivada quando se tem um fragmento de cdigo que pode ser agrupado.
void imprimirDivida() { Enumeration e = pedidos.elements(); double divida = 0; //imprimir cabealho System.out.println(Cliente deve:) while (e.naoTemMaisElementos()) { Pedido cada = (Pedido) e.nextElement(); divida = divida + cada.lerQuantia(); System.out.println(nome); System.out.println(divida); } }

Extraindo o cdigo, temos:


void imprimirDivida() { Enumeration e = pedidos.elements(); double divida = 0; imprimirCabecalho(); while (e.naoTemMaisElementos()) { Pedido cada = (Pedido) e.nextElement(); divida = divida + cada.lerQuantia(); System.out.println(nome); System.out.println(divida); private void imiprimirCabecalho(){ System.out.println(Cliente deve:) } } 3.2. Internalizar mtodos

Ocorre quando o contedo de um mtodo totalmente intuitivo, no tendo, portanto, necessidade de destrinch-lo.
Int ganhaPremio() { return (qtdCompras()) ? boolean qtdCompras(){ return compras >10; } } 1 : 0;

Aplicando a tcnica de internalizar mtodo:


Int ganhaPremio () { return ((compras > 10)) ? 1 : 0 }

3.3 Internalizar varivel temporria Ocorre quando se tem uma varivel temporria que recebe uma nica atribuio de uma expresso simples e essa varivel atrapalha outras refatoraes.
Int preco = getPreco(); Return (preco > 500)

Utilizando a tecnica de refatorao, temos:


Return (getPreco() > 500); 3.4 Substituir Varivel Temporria por Consulta

Ocorre quando est usando uma varivel temporria para armazenar o resultado de uma expresso.
double basePrice = _quantity * _itemPrice; if (basePrice > 1000) return basePrice * 0.95; else return basePrice * 0.98;

Utilizando a refatorao, temos.


if (basePrice() > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; double basePrice() { return _quantity * _itemPrice; }

3.5. Introduzir Varivel Explicativa Ocorre com o motivo de auxiliar o programador quando h uma expresso complexa.
if ( (platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0 ) { // do something }

Aplicando a tcnica de refatorao, temos:

final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1; final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1; final boolean wasResized = resize > 0; if (isMacOs && isIEBrowser && wasInitialized() && wasResized) { // do something }

Alm dessas tcnicas existem: Diviso de variveis temporrias - Ocorre quando se tem uma varivel temporria que recebe mais de uma vez uma atribuio, porm no uma varivel de lao. Remoo de atribuies para parmetros Ocorre quando o cdigo faz uma atribuio a um parmetro Substituio de algoritmo Ocorre a substituio de um algoritmo por um mais fcil de ser entendido.

4. Movendo Caractersticas entre Objetos. 4.1 Mover Mtodo Ocorre quando um mtodo est usando ou sendo usado por mais recurso de outra classe do que a classe no qual ele est agrupado.
class Project { Person[] participants; } class Person { int id; boolean participate(Project p) { for(int i=0; i<p.participants.length; i++) { if (p.participants[i].id == id) return(true); } return(false); } }

Aps aplicar a tcnica:


class Project { Person[] participants; boolean participate(Person x) { for(int i=0; i<participants.length; i++) { if (participants[i].id == x.id) return(true); } return(false); } } class Person {

int id; }

4.2 Movendo atributo Um campo ser usado por outra classe mais do que a classe do que ele est previamente definido. Sendo assim ns tiramos o mtodo X da Classe A para uma Classe B. 4.3 Extrao de Classe Ocorre quando uma classe est fazendo o papel de outras duas. 4.4 Incorporao de Classe Ocorre quando uma classe no est desempenhando um papel importante, podendo ser agrupado em uma outra classe. 4.5 Introduo de Mtodo Estrangeiro Ocorre quando voc precisa adicionar um mtodo a uma classe, porm no pode modific-la.
Date newStart = new Date (previousEnd.getYear(), previousEnd.getMonth(), previousEnd.getDate() + 1);

Aplicando o mtodo de refatorao, temos:


Date newStart = nextDay(previousEnd); private static Date nextDay(Date arg) { return new Date (arg.getYear(),arg.getMonth(), arg.getDate() + 1);

5. Organizando Dados 5.1 Auto Encapusular Campo Ocorre quando se acessa um campo diretamente porm o acoplamento dessa campos se torna imprprio.
private int _low, _high; boolean includes (int arg) { return arg >= _low && arg <= _high; }

Aplicando o mtodo, temos:


private int _low, _high; boolean includes (int arg) { return arg >= getLow() && arg <= getHigh(); } int getLow() {return _low;} int getHigh() {return _high;}

5.2 Substituir Atributo por Objeto Ocorre quando se tem um dado que precisa do mesmo comportamento de outros mtodos ou de dados adicionais. 5.3 Mudar de Valor para Referncia Ocorre quando se tem uma classe com muitas instncias iguais e quer substituir por um objeto. 5.4 Mudar de Referncia para Valor Ocorre quando se tem um objeto por referncia pequeno, sem modificao e difcil de gerenciar 5.5 Substituir Vetor por Objeto Ocorre quando se possui um vetor com valores semnticos diferentes
String[] row = new String[3]; row [0] = "Liverpool"; row [1] = "15";

Aps a aplicao da tcnica, temos:


Performance row = new Performance(); row.setName("Liverpool"); row.setWins("15");

Alm dessas tcnicas, tempos: Duplicar Dados Observador, Transformar Associao unidirecional em Biderecional; Transformar Associao Bidirecional em Unidirecional, etc

6. Simplificando expresses Condicionais. 6.1. Decompor Condicional Ocorre quando se tem uma estrutura condicional complicada
if (date.before (SUMMER_START) || date.after(SUMMER_END)) charge = quantity * _winterRate + _winterServiceCharge; else charge = quantity * _summerRate;

Aps a aplicao da tcnica:


if (notSummer(date)) charge = winterCharge(quantity); else charge = summerCharge (quantity);

6.2 Consolidar Expresso Condicional Ocorre quando se tem um conjunto de tcnicas condicionais com o mesmo valor resultante.
double disabilityAmount() { if (_seniority < 2) return 0; if (_monthsDisabled > 12) return 0; if (_isPartTime) return 0; // compute the disability amount

Aps a aplicao da tcnica


double disabilityAmount() { if (isNotEligableForDisability()) return 0; // compute the disability amount

6.3 Consolidar Fragmentos Condicionais Duplicados Ocorre quando o mesmo tipo de cdigo aparece em todos os ramos existentes de uma expresso condicional.
if (isSpecialDeal()) { total = price * 0.95; send(); } else { total = price * 0.98; send(); }

Aps a adio da tcnica, temos:


if (isSpecialDeal()) total = price * 0.95; else total = price * 0.98; send();

6.4 Remover Flag de Controle Ocorre quando se tem uma varivel que est fazendo o papel de flag de controle para expresses booleanas 6.5 Substituir Condio Aninhada por Clusulas-Guarda Ocorre quando um mtodo tem lgica condicional que no deixa claro o fluxo normal da execuo
double getPayAmount() { double result; if (_isDead) result = deadAmount(); else { if (_isSeparated) result = separatedAmount(); else { if (_isRetired) result = retiredAmount(); else result = normalPayAmount(); }; } return result; };

Aps a aplicao da tcnica:


double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retiredAmount(); return normalPayAmount(); };

Alm dessas, tambm existem as tcnicas: Substituir Comando Condicional por polimorfismo; Introduzir Objeto Nulo; Introduzir Assero;

7. Simplificando Chamadas de Mtodos 7.1. Renomear Mtodo necessrio modificar o nome de um mtodo quando ele no revela o que realmente proporciona. 7.2 Acrescentar Parmetro Um mtodo necessita de informaes que no foram passadas a ele. 7.3 Separar a Consulta do Modificador Ocorre quando se tem um mtodo que retorna um valor porm altera o estado de um objeto.

7.4 Parametrizar Mtodo Diversos mtodos fazem coisas semelhantes porm com diferentes valores contidos no corpo do mtodo. 7.5 Substituir Parmetro por Mtodos Explcitos Ocorre quando um mtodo que executa diferentes cdigos de acordo com os valores de um parmetro enumerado.

8. Lidando com Generalizaes 8.1 Subir Campo na Hierarquia Ocorre quando duas subclasses tem o mesmo campo. Para resolver esse problema, esse campo dever ser deslocado para a classe pai, assim todas as duas classes tero acesso a essa campo. 8.2 Subir Mtodo na Hierarquia. Ocorre quando duas subclasses tem o mesmo mtodo. Para resolver esse problema, esse mtodo dever ser deslocado para a classe pai, assim todas as duas classes tero acesso a essa mtodo. 8.3 Subir o corpo do Construtor na Hierarquia Ocorre quando se tem construtores nas subclasses quase idnticos ao construtor da classe pai.
class Manager extends Employee... public Manager (String name, String id, int grade) { _name = name; _id = id; _grade = grade; }

Com a aplicao do mtodo, temos:


public Manager (String name, String id, int grade) { super (name, id); _grade = grade; }

8.4 Descer Campo na Hierarquia Ocorre quando um campo usado apenas por algumas subclasses, assim um campo existente em uma classe pai passada a uma classe filho e depois excluda.

8.5 Extrair Subclasse Ocorre quando uma classe tem caractersticas que so usadas apenas em algumas instncias.

8.6 Extrair SuperClasse Ocorre quando se tem duas classes com caractersticas semelhantes.

Alm das tcnicas j citadas existem: Extrair Interface; Condensar Hierarquia; Criar um Mtodo Padro; Substituir Herana por Delegao; Substituir Delegao por Herana

9. Referencias Bibliogrficas FOWLER, Martin. Refatoracao Aperfeioando o projeto de cdigo existente. http://www.refactoring.com/catalog/index.html