Refactoring
   Bruno Lui
   @bruno_lui
O que é
Refactoring?
“Processo de alterar e
    melhorar o código
de um software de maneira
 que seu comportamento
    não seja alterado”
“Uma maneira disciplinada de
limpar código, que minimiza as
 chances de introduzir bugs”
Porque refatorar ?
Para melhorar o
design do código
   existente
evitando que ele
fique decadente..
Para ajudar a
encontrar bugs..
Para tornar o código mais
    fácil de entender..
Para tornar o código mais
barato e rápido de modificar
Quando começamos a mergulhar no código ruim, logo
descobrimos várias “oportunidades” para refatorá-lo...
E quanto mais fundo vamos, mais dessas
                  “opotunidades” aparecem..




aumentando nossa vontade de alterar...
Antes de começar a cavar a própria cova,
               saiba que...
A Refatoração
deve ser uma
   prática
sistemática      e

 disciplinada.
Quando refatorar ?
Quando vamos adicionar uma nova funcionalidade



O código que deve ser alterado
     está difícil de entender.



O design não ajuda a adicionar
a nova funcionalidade facilmente
Quando vamos corrigir um bug



Um bug reportado pode ser um
sinal que o código não estava claro
o bastante para evitá-lo.
Quando vamos revisar o código de alguém


 O código pode parecer limpo para mim, mas não para
 minha equipe.


Sugestões podem ajudar
a melhorar o código.
"Decidir quando começar e quando parar
  uma refatoração, é tão importante
     quanto saber como fazê-la."
Quando não refatorar

Muitas aplicações estão totalmente acopladas
                          ao banco de dados.


            Quando um código estiver tão cheio
            de bugs ou com um design muito ruim,
            é melhor começar do zero.
Primeiro passo...

Criar um conjunto de testes sólidos
para garantir que sua refatoração
não quebre o código que está
funcionando.
Técnicas de
refatoração
Extract Method

Transformar um trecho de código em um novo método.

             O seu nome deve explicar seu propósito.



            Muitos problemas vêm de métodos muito
                    grandes e com muita informação.
Remove temp with query

Quando transformamos uma variável temporária usada
   para guardar o resultado de uma expressão em um
                                           método.
double precoBase = quantidade * preco;


if (precoBase > 1000) {
  return precoBase * 0.95;
} else {
  return precoBase * 0.98;
}




   if (precoBase() > 1000) {
       return precoBase() * 0.95;
   } else {
       return precoBase() * 0.98;
   }


   double precoBase() {
       return quantidade * preco;
   }
Move method/field
  Mover um método/atributo quando é ou será usado em
      outras classes além da classe em que está definido.


Métodos: Crie um novo método com o mesmo corpo na classe
mais usada, e apenas delegue a chamada do método antigo para o
novo.


Atributos: Crie um novo atributo em outra classe e use o
encapsulamento para delegar.
Extract class
      Quando uma classe está fazendo o trabalho de duas.


class Person {                class Person {
  String name;                  String name;
  String officeAreaCode;        ...
  String officeNumber;          TelephoneNumber officePhone;
  ...                         }
}



                                class TelephoneNumber {
                                  String areaCode;
                                  String number;
                                }
Hide delegate

Remova a dependência de uma classe que possua um
         delegate para um atributo de outra classe.
class Pessoa {                               class Pessoa {
  Departamento departamento;                   Departamento departamento;

    public Departamento getDepartamento(){       public Pessoa getGerente() {
      return departamento;                         return departamento.getGerente();
    }                                            }
}                                            }

class Departamento {
  private Pessoa gerente;

    public Pessoa getGerente() {
      return gerente;
    }
}




                 gerente = joao.getDepartamento().getGerente();




                         gerente = joao.getGerente();
Remove middle man
                              O contrário do Hide Delegate.
          Crie um método para acessar o atributo encapsulado.




Quando há muitos atributos na classe delegate e você precisa
ficar criando novos métodos toda vez.
Replace data value with object

Quando um item que precisa de um comportamento adicional


                                Order

     Order
     _________________
                                        1
     customer: String
                                Customer
                                _________________

                                name: String
Encapsulate Collection
      Quando somente temos o método para retornar a
                                 collection imutável.

 Criamos métodos para adicionar e remover elementos.


                            Person
Person
                            _________________
_________________

                            getCourses():Unmodifiable Set
getCourses():Set
                            addCourse(:Course)
setCourses(:Set)
                            removeCourse(:Course)
Decompose Conditional

 Uma lógica condicional não muito legível aumenta a complexidade.

Pode facilmente nos confundir e alterar o comportamento desejado.
Decompose Conditional

if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
  charge = quantity * winterRate + winterSeviceCharge;
} else {
  charge = quantity * summerRate;
}




if (notSummer(date)) {
  charge = winterCharge(quantity);
} else {
  charge = summerCharge(quantity);
}
Consolidate Duplicate conditional fragments


        Quando temos o mesmo trecho de código dentro de
                                 uma lógica condicional.

                               Mova-o para fora da lógica.
Consolidate Duplicate conditional fragments

  if (isSpecial()) {
    total = price * 0.95;
    send();
  } else {
    total = price * 0.98;
    send();
  }




  if (isSpecial()) {
    total = price * 0.95;
  } else {
    total = price * 0.98;
  }
  send();
Separate query from modifier

Quando o mesmo método retorna um valor e altera o estado de um
                                                        objeto.

                                              Separe-o em dois métodos.

                               Customer
                  __________________________________
              getTotalOutstandingAndSetReadyForSummaries




                             Customer
                         _________________
                      getTotalOutstanding
                      setReadyForSummaries
Parameterize Method


Vários métodos fazem coisas parecidas mas com valores diferentes.
                        Unifique o método e parametrize o valor.




         Employee                         Employee
     _________________                _________________

  fivePercentRaise()                raise(percentage)
  tenPercentRaise()
Preserve whole object

Quando usamos vários valores de um objeto para passá-los para outro método.

                                    Passe o objeto inteiro por parametro.


                    int low = period.getLow();
                    int high = period.getHigh();

                    withinPlan = plan.withinRange(low, high);




                    withinPlan = plan.withinRange(period);
Martin Fowler
“Qualquer idiota consegue escrever
código que o computador entenda...
...mas só bons
programadores   conseguem
escrever código que outras
   pessoas entendam.”
Referências


                 http://www.slideshare.net/gvespucci/refactoring-an-introduction

                 http://www.slideshare.net/redigon/refactoring-1658371




                                         Imagens
http://www.flickr.com/photos/68751915@N05/6848823919
http://www.flickr.com/photos/raiderslight/2800096351/
http://theassistant.files.wordpress.com/2009/11/013.jpg
http://www.flickr.com/photos/birminghamcityuniversity/5367360800/
http://1.bp.blogspot.com/_9iN8wXq1y_s/TOF3u11KD1I/AAAAAAAAAEg/v3HOYSzJlzo/s1600/why2.jpg
http://greatmiddleway.files.wordpress.com/2012/03/doubt1.jpg
http://www.sxc.hu/photo/1133804
http://tweakyourbiz.com/growth/files/reviews.jpg
http://torwars.com/wp-content/uploads/2012/01/patch-notes-and-bug-fixes-SWTOR.png
http://www.revenuewoo.com/wp-content/uploads/2012/05/BlogUpp_new_features-788925.jpg
Obrigado!

Refactoring

  • 1.
    Refactoring Bruno Lui @bruno_lui
  • 2.
  • 3.
    “Processo de alterare melhorar o código de um software de maneira que seu comportamento não seja alterado”
  • 4.
    “Uma maneira disciplinadade limpar código, que minimiza as chances de introduzir bugs”
  • 5.
  • 6.
    Para melhorar o designdo código existente evitando que ele fique decadente..
  • 7.
  • 8.
    Para tornar ocódigo mais fácil de entender..
  • 9.
    Para tornar ocódigo mais barato e rápido de modificar
  • 10.
    Quando começamos amergulhar no código ruim, logo descobrimos várias “oportunidades” para refatorá-lo...
  • 11.
    E quanto maisfundo vamos, mais dessas “opotunidades” aparecem.. aumentando nossa vontade de alterar...
  • 12.
    Antes de começara cavar a própria cova, saiba que...
  • 13.
    A Refatoração deve seruma prática sistemática e disciplinada.
  • 14.
  • 15.
    Quando vamos adicionaruma nova funcionalidade O código que deve ser alterado está difícil de entender. O design não ajuda a adicionar a nova funcionalidade facilmente
  • 16.
    Quando vamos corrigirum bug Um bug reportado pode ser um sinal que o código não estava claro o bastante para evitá-lo.
  • 17.
    Quando vamos revisaro código de alguém O código pode parecer limpo para mim, mas não para minha equipe. Sugestões podem ajudar a melhorar o código.
  • 18.
    "Decidir quando começare quando parar uma refatoração, é tão importante quanto saber como fazê-la."
  • 19.
    Quando não refatorar Muitasaplicações estão totalmente acopladas ao banco de dados. Quando um código estiver tão cheio de bugs ou com um design muito ruim, é melhor começar do zero.
  • 20.
    Primeiro passo... Criar umconjunto de testes sólidos para garantir que sua refatoração não quebre o código que está funcionando.
  • 21.
  • 22.
    Extract Method Transformar umtrecho de código em um novo método. O seu nome deve explicar seu propósito. Muitos problemas vêm de métodos muito grandes e com muita informação.
  • 23.
    Remove temp withquery Quando transformamos uma variável temporária usada para guardar o resultado de uma expressão em um método.
  • 24.
    double precoBase =quantidade * preco; if (precoBase > 1000) { return precoBase * 0.95; } else { return precoBase * 0.98; } if (precoBase() > 1000) { return precoBase() * 0.95; } else { return precoBase() * 0.98; } double precoBase() { return quantidade * preco; }
  • 25.
    Move method/field Mover um método/atributo quando é ou será usado em outras classes além da classe em que está definido. Métodos: Crie um novo método com o mesmo corpo na classe mais usada, e apenas delegue a chamada do método antigo para o novo. Atributos: Crie um novo atributo em outra classe e use o encapsulamento para delegar.
  • 26.
    Extract class Quando uma classe está fazendo o trabalho de duas. class Person { class Person { String name; String name; String officeAreaCode; ... String officeNumber; TelephoneNumber officePhone; ... } } class TelephoneNumber { String areaCode; String number; }
  • 27.
    Hide delegate Remova adependência de uma classe que possua um delegate para um atributo de outra classe.
  • 28.
    class Pessoa { class Pessoa { Departamento departamento; Departamento departamento; public Departamento getDepartamento(){ public Pessoa getGerente() { return departamento; return departamento.getGerente(); } } } } class Departamento { private Pessoa gerente; public Pessoa getGerente() { return gerente; } } gerente = joao.getDepartamento().getGerente(); gerente = joao.getGerente();
  • 29.
    Remove middle man O contrário do Hide Delegate. Crie um método para acessar o atributo encapsulado. Quando há muitos atributos na classe delegate e você precisa ficar criando novos métodos toda vez.
  • 30.
    Replace data valuewith object Quando um item que precisa de um comportamento adicional Order Order _________________ 1 customer: String Customer _________________ name: String
  • 31.
    Encapsulate Collection Quando somente temos o método para retornar a collection imutável. Criamos métodos para adicionar e remover elementos. Person Person _________________ _________________ getCourses():Unmodifiable Set getCourses():Set addCourse(:Course) setCourses(:Set) removeCourse(:Course)
  • 32.
    Decompose Conditional Umalógica condicional não muito legível aumenta a complexidade. Pode facilmente nos confundir e alterar o comportamento desejado.
  • 33.
    Decompose Conditional if (date.before(SUMMER_START)|| date.after(SUMMER_END)) { charge = quantity * winterRate + winterSeviceCharge; } else { charge = quantity * summerRate; } if (notSummer(date)) { charge = winterCharge(quantity); } else { charge = summerCharge(quantity); }
  • 34.
    Consolidate Duplicate conditionalfragments Quando temos o mesmo trecho de código dentro de uma lógica condicional. Mova-o para fora da lógica.
  • 35.
    Consolidate Duplicate conditionalfragments if (isSpecial()) { total = price * 0.95; send(); } else { total = price * 0.98; send(); } if (isSpecial()) { total = price * 0.95; } else { total = price * 0.98; } send();
  • 36.
    Separate query frommodifier Quando o mesmo método retorna um valor e altera o estado de um objeto. Separe-o em dois métodos. Customer __________________________________ getTotalOutstandingAndSetReadyForSummaries Customer _________________ getTotalOutstanding setReadyForSummaries
  • 37.
    Parameterize Method Vários métodosfazem coisas parecidas mas com valores diferentes. Unifique o método e parametrize o valor. Employee Employee _________________ _________________ fivePercentRaise() raise(percentage) tenPercentRaise()
  • 38.
    Preserve whole object Quandousamos vários valores de um objeto para passá-los para outro método. Passe o objeto inteiro por parametro. int low = period.getLow(); int high = period.getHigh(); withinPlan = plan.withinRange(low, high); withinPlan = plan.withinRange(period);
  • 39.
  • 40.
    “Qualquer idiota consegueescrever código que o computador entenda...
  • 41.
    ...mas só bons programadores conseguem escrever código que outras pessoas entendam.”
  • 42.
    Referências http://www.slideshare.net/gvespucci/refactoring-an-introduction http://www.slideshare.net/redigon/refactoring-1658371 Imagens http://www.flickr.com/photos/68751915@N05/6848823919 http://www.flickr.com/photos/raiderslight/2800096351/ http://theassistant.files.wordpress.com/2009/11/013.jpg http://www.flickr.com/photos/birminghamcityuniversity/5367360800/ http://1.bp.blogspot.com/_9iN8wXq1y_s/TOF3u11KD1I/AAAAAAAAAEg/v3HOYSzJlzo/s1600/why2.jpg http://greatmiddleway.files.wordpress.com/2012/03/doubt1.jpg http://www.sxc.hu/photo/1133804 http://tweakyourbiz.com/growth/files/reviews.jpg http://torwars.com/wp-content/uploads/2012/01/patch-notes-and-bug-fixes-SWTOR.png http://www.revenuewoo.com/wp-content/uploads/2012/05/BlogUpp_new_features-788925.jpg
  • 43.