Anda di halaman 1dari 62

Refatorao de Software

Prof. Dr Marcos L. Chaim


EACH -- USP

Atualizao: Eliane Martins Nov/2010

Material elaborado a partir de slides dos professores Dr. Alfredo Goldman e Dr. Fbio Kon DCC/IME/USP

Conceito
Refatorao o processo de mudana do design uma aplicao sem modificar o seu comportamento original [Opdyke, 1992 apud Mens eTourw, 2004]. Uma [pequena] modificao no sistema que no altera o seu comportamento funcional, mas que melhora alguma qualidade nofuncional.

Conceito
Possveis aspectos de qualidade no-funcional melhorados:

simplicidade flexibilidade clareza desempenho

Objetivos & aplicaes


Prevenir o envelhecimento do design e garantir a flexibilidade adequada para permitir a integrao tranqila de futuras extenses/alteraes [Mens eTourw, 2004] Cdigo legado. Mtodos geis incorporam como uma prtica Extreme Programming.

Exemplos de refatorao
Mudana do nome de variveis Mudanas nas interfaces dos objetos Pequenas mudanas arquiteturais Encapsular cdigo repetido em um novo mtodo Generalizao de mtodos

raizQuadrada(float x) raiz(float x, int n)

Refatorao
Em geral, uma refatorao to simples que parece que no vai ajudar muito. Mas quando se juntam 50 refatoraes, bem escolhidas, em seqncia, o cdigo melhora radicalmente.

Refatorao
Cada refatorao simples. Demora alguns segundos ou alguns poucos minutos para ser realizado. uma operao sistemtica e bvia (ovo de Colombo). O segredo est em ter um bom vocabulrio de refatoraes e saber aplic-las criteriosa e sistematicamente.

Refatorao Sempre Existiu


Mas no tinha um nome. Estava implcito, ad hoc. A novidade est em criar um vocabulrio comum e em catalog-las. Assim podemos utiliz-las mais sistematicamente. Podemos aprender novas tcnicas, ensinar uns aos outros.

Quando Usar Refatorao


Sempre h duas possibilidades:
1. Melhorar o cdigo existente. 2. Jogar fora e comear do 0.

sua responsabilidade avaliar a situao e decidir quando a hora de optar por um ou por outro.

Origens
Surgiu na comunidade de Smalltalk nos anos 80/90. Desenvolveu-se formalmente na Universidade de
Illinois em Urbana-Champaign.

Grupo do Prof. Ralph Johnson.


Tese de PhD de William Opdyke (1992). John Brant e Don Roberts:


The Refactoring Browser Tool

Kent Beck (XP) na indstria.

Estado Atual
Hoje em dia um dos preceitos bsicos de Programao eXtrema (XP). Mas no est limitado a XP, qualquer um pode (e deve) usar em qualquer contexto. No limitado a Smalltalk. Pode ser usado em qualquer linguagem [orientada a objetos].

Catlogo de Refatoraes
[Fowler, 2000] contm 72 refatoraes. Vale a pena gastar algumas horas com [Fowler, 2000]. Anlogo aos padres de projeto orientado a objetos [Gamma et al. 2000] (GoF).

Passos para aplicao de uma refatorao


Detectar quando uma aplicao precisa ser refatorada. Identificar quais refatoraes devem ser aplicadas e onde. Realizar (automaticamente) as refatoraes. [Tourw e Mens, 2003].

Mau cheiro
Cunhada por Beck [Fowler, 2000], o termo mau cheiro (bad smell) refere-se s estruturas no cdigo que sugerem (s vezes gritam pela) possibilidade de refatorao. A partir da identificao de um mau cheiro possvel propor refatoraes adequadas, que podem reduzir ou mesmo eliminar o maucheiro.

Mau Cheiro
Cheiro Cdigo duplicado Mtodo muito longo Classe muito grande
Refatorao a ser aplicada

Intimidade inapropriada

Extract Method (110) Substitute Algorithm (139) Extract Method (110) Replace Temp With Query (120) Introduce Parameter Object (295) Extract Class (149) Extract Subclass (330) Extract Interface (341) Duplicate Observed Data (189) Move Method (142) Move Field (146) Replace Inheritance with Delegation(352)

Aplicando uma refatorao


Antes de comear a refatorao, verifique se voc tem um conjunto slido de testes para verificar a funcionalidade do cdigo a ser refatorado. Refatoraes podem adicionar erros. Os testes vo ajud-lo a detectar erros se eles forem criados.

Formato de Cada Entrada no Catlogo


Nome da refatorao. Resumo da situao na qual ela necessria e o que ela faz. Motivao para us-la (e quando no us-la). Mecnica, i.e., descrio passo a passo. Exemplos para ilustrar o uso.

Extract Method (110)


Nome: Extract Method Resumo: Voc tem um fragmento de cdigo que poderia ser agrupado. Mude o fragmento para um novo mtodo e escolha um nome que explique o que ele faz.

Extract Method (110)


Motivao: uma das refatoraes mais comuns. Se um mtodo longo demais ou difcil de entender e exige muitos comentrios, extraia trechos do mtodo e crie novos mtodos para eles. Isso vai melhorar as chances de reutilizao do cdigo e vai fazer com que os mtodos que o chamam fiquem mais fceis de entender. O cdigo fica parecendo comentrio.

Extract Method (110)


Mecnica:

Crie um novo mtodo e escolha um nome que explicite a sua inteno (o nome deve dizer o que ele faz, no como ele faz). Copie o cdigo do mtodo original para o novo.

Extract Method (110)


Mecnica (cont.):

Procure por variveis locais e parmetros utilizados pelo cdigo extrado.


Se variveis locais forem usadas apenas pelo cdigo extrado, passe-as para o novo mtodo. Caso contrrio, veja se o seu valor apenas atualizado pelo cdigo. Neste caso substitua o cdigo por uma atribuio. Se tanto lido quando atualizado, passe-a como parmetro.

Compile e teste.

Extract Method (110)


Exemplo Sem Variveis Locais
void imprimeDivida () { Enumerate e = _pedidos.elementos (); double divida = 0.0; // imprime cabealho System.out.println (***************************); System.out.println (*** Dvidas do Cliente ****); System.out.println (***************************); // calcula dvidas while (e.temMaisElementos ()){ Order cada = (Order) e.proximoElemento (); divida += cada.valor (); } // imprime detalhes System.out.println (nome: + _nome); System.out.println (divida total: + divida); }

Extract Method (110)


Exemplo Sem Variveis Locais
void imprimeDivida () { Enumerate e = _pedidos.elementos (); double divida = 0.0; imprimeCabecalho (); // calcula dvidas while (e.temMaisElementos ()){ Order cada = (Order) e.proximoElemento (); divida += cada.valor (); } //imprime detalhes System.out.println(nome: + _nome); System.out.println(divida total: + divida); } void imprimeCabecalho () { System.out.println (***************************); System.out.println (*** Dvidas do Cliente ****); System.out.println (***************************); }

Extract Method (110)


Exemplo COM Variveis Locais
void imprimeDivida () { Enumerate e = _pedidos.elementos (); double divida = 0.0; imprimeCabecalho (); // calcula dvidas while (e.temMaisElementos ()){ Order cada = (Order) e.proximoElemento (); divida += cada.valor (); } imprimeDetalhes (divida); } void imprimeDetalhes (double divida) { System.out.println(nome: + _nome); System.out.println(divida total: + divida); }

Extract Method (110)


com atribuio
void imprimeDivida () { imprimeCabecalho (); double divida = calculaDivida (); imprimeDetalhes (divida); } double calculaDivida () { Enumerate e = _pedidos.elementos (); double divida = 0.0; while (e.temMaisElementos ()){ Order cada = (Order) e.proximoElemento (); divida += cada.valor (); } return divida; }

Extract Method (110)


depois de compilar e testar
void imprimeDivida () { imprimeCabecalho (); double divida = calculaDivida (); imprimeDetalhes (divida); } double calculaDivida () { Enumerate e = _pedidos.elementos (); double resultado = 0.0; while (e.temMaisElementos ()){ Order cada = (Order) e.proximoElemento (); resultado += cada.valor (); } return resultado; }

Extract Method (110)


depois de compilar e testar D para ficar mais curto ainda:
void imprimeDivida () { imprimeCabecalho (); imprimeDetalhes (calculaDivida ()); }

Mas no necessariamente melhor pois um pouco menos claro.

Inline Method (117)


Nome: Inline Method Resumo: a implementao de um mtodo to
clara quanto o nome do mtodo. Substitua a chamada ao mtodo pela sua implementao.

Motivao: bom para eliminar indireo


desnecessria. Se voc tem um grupo de mtodos mal organizados, aplique Inline Method em todos eles seguido de uns bons Extract Method s.

Inline Method (117)


Mecnica:

Verifique se o mtodo no polimrfico ou se as suas subclasses o especializam. Ache todas as chamadas e substitua pela implementao. Compile e teste. Remova a definio do mtodo. Dica: se for difcil -> no faa.

Inline Method (117)


Exemplo:
int bandeiradaDoTaxi (int hora) { return (depoisDas22Horas (hora)) ? 2 : 1); } int depoisDas22Horas (int hora) { return hora > 22; } int bandeiradaDoTaxi (int hora) { return (hora > 22) ? 2 : 1); }

Replace Temp with Query (120)


Nome: Replace Temp with Query Resumo: Uma varivel local est sendo usada para
guardar o resultado de uma expresso. Troque as referncias a esta expresso por um mtodo.

Motivao: Variveis temporrias encorajam


mtodos longos (devido ao escopo). O cdigo fica mais limpo e o mtodo pode ser usado em outros locais.

Replace Temp with Query (120)


Mecnica:

Encontre variveis locais que so atribudas uma nica vez


Se temp atribuda mais do que uma vez use Split Temporary Variable (128)

Declare temp como final Compile (para ter certeza) Extraia a expresso
Mtodo privado - efeitos colaterais

Compile e teste

Replace Temp with Query (120)


double getPreco() { int precoBase = _quantidade * _precoItem; double fatorDesconto; if (precoBase > 1000) fatorDesconto = 0.95; else fatorDesconto = 0.98; return precoBase * fatorDesconto; } double getPreco() { final int precoBase = _quantidade * _precoItem; final double fatorDesconto; if (precoBase > 1000) fatorDesconto = 0.95; else fatorDesconto = 0.98; return precoBase * fatorDesconto; }

Replace Temp with Query (120)


double getPreco() { final int precoBase = precoBase(); // 1 final double fatorDesconto; if (precoBase > 1000) fatorDesconto = 0.95; //2 else fatorDesconto = 0.98; return precoBase * fatorDesconto; } private int precoBase() { return _quantidade * _precoItem; }

Replace Temp with Query (120)

double getPreco() { final double fatorDesconto; if (precoBase() > 1000) fatorDesconto = 0.95; //2 else fatorDesconto = 0.98; return precoBase() * fatorDesconto; } private int precoBase() { return _quantidade * _precoItem; }

Replace Temp with Query (120)


double getPreco() { final double fatorDesconto; if (precoBase() > 1000) fatorDesconto = 0.95; //2 else fatorDesconto = 0.98; return precoBase() * fatorDesconto; } private int fatorDesconto() { if (precoBase() > 1000) return 0.95; return 0.98; } private int precoBase() { return _quantidade * _precoItem; }

Replace Temp with Query (120)


double getPreco() { final double fatorDesconto = fatorDesconto(); return precoBase() * fatorDesconto; } private int fatorDesconto() { if (precoBase() > 1000) return 0.95; return 0.98; } private int precoBase() { return _quantidade * _precoItem; }

Replace Temp with Query (120)


resultado final

double getPreco() { return precoBase() * fatorDesconto(); } private int fatorDesconto() { if (precoBase() > 1000) return 0.95; return 0.98; } private int precoBase() { return _quantidade * _precoItem; }

Replace Inheritance With Delegation (352) Motivao: herana uma tcnica


excelente, mas muitas vezes, no exatamente o que voc quer. s vezes, ns comeamos herdando de uma outra classe mas da descobrimos que precisamos herdar muito pouco da superclasse. Descobrimos que muitas das operaes da superclasse no se aplicam subclasse. Neste caso, delegao mais apropriado.

Replace Inheritance With Delegation (352) Resumo: Quando uma subclasse s usa
parte da funcionalidade da superclasse ou no precisa herdar dados: na subclasse, crie um campo para a superclasse, ajuste os mtodos apropriados para delegar para a ex-superclasse e remova a herana.

Replace Inheritance With Delegation (352)


Mecnica:

Crie um campo na subclasse que se refere a uma instncia da superclasse, inicialize-o com this Mude cada mtodo na subclasse para que use o campo delegado Compile e teste aps mudar cada mtodo
Cuidado com as chamadas a super

Remova a herana e crie um novo objeto da superclasse Para cada mtodo da superclasse utilizado, adicione um mtodo delegado Compile e teste

Replace Inheritance With Delegation (352)


Exemplo: pilha subclasse de vetor.
Class MyStack extends Vector { public void push (Object element) { insertElementAt (element, 0); } public Object pop () { Object result = firstElement (); removeElementAt (0); return result; }

Replace Inheritance With Delegation (352)


Crie campo para superclasse.
Class MyStack extends Vector { private Vector _vector = this; public void push (Object element) { _vector.insertElementAt (element, 0); } public Object pop () { Object result = _vector.firstElement (); _vector.removeElementAt (0); return result; }

Replace Inheritance With Delegation (352)


Remova herana.
Class MyStack extends Vector { private Vector _vector = this; new Vector (); public void push (Object element) { _vector.insertElementAt (element, 0); } public Object pop () { Object result = _vector.firstElement (); _vector.removeElementAt (0); return result; }

Replace Inheritance With Delegation (352)


Crie os mtodos de delegao que sero necessrios.
public int size () { return _vector.size (); } public int isEmpty () { return _vector.isEmpty (); } }// end of class MyStack

Collapse Hierarchy (344)


Resumo: A superclasse e a subclasse no so
muito diferentes. Combine-as em apenas uma classe.

Motivao: Depois de muito trabalhar com uma


hierarquia de classes, ela pode se tornar muito complexa. Depois de refator-la movendo mtodos e campos para cima e para baixo, voc pode descobrir que uma subclasse no acrescenta nada ao seu projeto. Remova-a.

Collapse Hierarchy (344)


Mecnica:

Escolha que classe ser eliminada: a superclasse ou a subclasse Use Pull Up Field (320) and Pull Up Method (322) ou Push Down Method (328) e Push Down Field (329) para mover todo o comportamento e dados da classe a ser eliminada Compile e teste a cada movimento Ajuste as referncias classe que ser eliminada
isto afeta: declaraes, tipos de parmetros e construtores.

Remova a classe vazia Compile e teste

Collapse Hierarchy (344)


Esquema

Class A

Class A+B Class B

Pull UP Field (320)


Resumo: A superclasse e a subclasse tm os mesmos
atributos (field). Mova os atributos repetidos para a superclasse.

Motivao: Subclasses desenvolvidas independentemente


umas das outras, ou aps refatorao, podem ter caractersticas (features) duplicadas. Atributos podem ser duplicados. Estes no necessariamente tm o mesmo nome em todas as subclasses. A forma de determinar se tal acontece verificar como os atributos so usados por outros mtodos. Se eles so usados da mesma forma, pode-se generaliz-los.

http://sourcemaking.com/refactoring/extract-interface

Pull UP Field (320)


Mecnica:

Inspecione todos os atributos candidatos para ver se no so usados de forma similar. Se os atributos no tm o mesmo nome, d-lhe o nome que vai ser usado quando ele subir para a superclasse. Compile e teste. Crie um novo atributo na superclasse. Se o atributo era privado nas subclasses, deve-se coloc-lo como protegido na superclasse. Apague o atributo nas subclasses. Compile e teste.

http://sourcemaking.com/refactoring/extract-interface

Pull UP Field (320)


Esquema

Class A

Class A tipo

Class B tipo

Class C Class B tipo_dado Class C

Replace Conditional With Polymorphism (255)


class Viajante { double getBebida () { switch (_type) { case ALEMAO: return cerveja; case BRASILEIRO: return pinga + limao; case AMERICANO: return coca_cola; } throw new RunTimeException (Tipo desconhecido!); } }

Replace Conditional With Polymorphism (255)


class Alemao extends Viajante { double getBebida () { return cerveja; } } class Brasileiro extends Viajante { double getBebida () { return pinga + limao; } } class Americano extends Viajante { double getBebida () { return coca_cola; } }

Extract Interface
Resumo: Vrios clientes usam o mesmo subconjunto da
interface da classe, ou vrias classes tm partes de suas interfaces em comum.

Motivao: Classes usam umas s outras de vrias formas.


Pode-se ter, por exemplo, um grupo de clientes usando um subconjunto das responsabilidades da classe. E ainda, uma classe pode colaborar com qualquer classe que trate um certo grupo de requisies. Nestes casos, til transformar esse subconjunto de responsabilidades em algo com existncia prpria, para ficar claro e explcito seu uso no sistema. Dessa forma fica mais fcil de ver como as responsabilidades se dividem. E tambm, ao se inserir novas classes que implementem esse subconjunto, fica mais fcil de ver o que se encaixa nesse subconjunto.

Extract Interface
Mecnica:

Crie uma interface vazia. Declare as operaes comuns na interface. Declare as classes relevantes que devem implementar a interface. Ajuste as declaraes de tipos nos clientes para usar a interface.

http://sourcemaking.com/refactoring/extract-interface

Extract Interface
Esquema

interface

IX M1( ) M2( ) M3( )

Class B M1( ) M2( ) M3( ) M4( ) M5( ) M6( ) Class B M1( ) M2( ) M3( ) M4( ) M5( ) M6( )

Princpios Bsicos
Refatorao muda o programa em passos pequenos. Se voc comete um erro, fcil consertar. Qualquer um pode escrever cdigo que o computador consegue entender. Bons programadores escrevem cdigo que pessoas conseguem entender. Trs repeties? Est na hora de refatorar. Quando voc sente que preciso escrever um comentrio para explicar o cdigo melhor, tente refatorar primeiro.

Ferramentas para Refatorao


Refactoring Browser Tool. D suporte automatizado para uma srie de refatoraes. Pode melhorar em muito a produtividade. Existem h vrios anos para Smalltalk. J h vrios para C++ e Java. Iniciativas acadmicas (Ralph@UIUC). Agora, integrado no Eclipse e no Visual Works.

Refactoring Browser Tool


It completely changes the way you think about
programming. Now I use probably half [of the time] refactoring and half entering new code, all at the same speed. Kent Beck. A ferramenta torna a refatorao to simples que ns mudamos a nossa prtica de programao.
http://st-www.cs.uiuc.edu/~brant/RefactoringBrowser

Concluses
Refatorao uma tcnica para tornar software mais simples, mais fceis de serem entendidos mais manutenvel. Consiste de modificaes simples, que no alteram a funcionalidade do cdigo, mas que realizadas repetidamente melhoram muito o software. Refatoraes foram catalogadas para uso sistemtico e so apoiadas por ferramentas.

Bibliografia
Erich Gamma et al. Padres de Projeto Solues reutilizveis de software orientado a objetos, Bookman, 2000. Martin Fowler. Refactoring: improving the design of existing code. Addison-Wesley. 2000. Tom Mens e Tom Tourw, A Survey of Software Refactoring, IEEE Transactions on Software Engineering, 30(2): 126-139, 2004. Tom Tourw e Tom Mens, Identifying Refactoring Opportunities Using Logic Meta Programming, Proceedings of the Seventh European Conference on Software Maintenance and Reegineering (CSMR 03), 2003. William F. Opdyke, Refactoring Object-oriented Frameworks. Ph.D thesis, University of Illinois at Urbana-Champaign, 1992.

Informaes
www.refactoring.com www.ime.usp.br/~kon/presentations

Anda mungkin juga menyukai