Programação limpa em Java
Módulo 01 - Nomenclatura, Funções e Comentários
                                            Data: 17/07/2012
                          Formador: Marcio Romualdo da Silva
                        Email: marcioromualdo@yahoo.com.br



1
Objetivos

 Geral:
   No final da sessão o formando será capaz de escrever código Java de forma
  limpa, clara e de fácil manutenção.

 Específicos:
   No final da sessão o formando será capaz de, na linguagem Java:
      Criar variáveis com nomes significativos, sem precisar de comentários.
      Criar funções com nomes significativos, sem precisar de comentários.
      Escrever funcões pequenas com apenas uma única intenção.
      Escrever comentários que ajudam na leitura clara do código.
      Identificar os comentários que atrapalham a leitura clara   do código.




    2
 Código Sujo versus Código Limpo 




3
O que é um código limpo?

 Simples e direto


 Legível (readable)


 Elegante e eficiênte


 Com mínimas dependências para   fácil manutenção

 Com nomes significativos


 Sem duplicação



    4
Por quê você escreveu código sujo?


 Estava tentando ir mais rápido? Estava com pressa?


 Seu chefe poderia ficar zangado se você tomasse tempo para limpar o código?


 Estava cansado de trabalhar no projeto e queria acabar logo?


 Havia outras coisas   havia prometido terminar e o tempo era curto?




    5
O custo total da sujeira




   Assim que a sujeira aumenta, a produtividade da equipa diminui, aproximando do
  zero.




  6
Nomes Significativos

 Use nomes que revelem a sua intenção!


   Compare:

        int d; // elapsed time in days

   Com:

        int elapsedTimeInDays;




    7
Nomes Significativos

 Use   nomes que revelem a sua intenção!

   Qual o propósito deste código?


  public List getThem() {
    List list1 = new ArrayList();
    for (int[] x : theList) {
       if (x[0] == 4) {
          list1.add(x);
       }
    }
    return list1;
  }

    8
Nomes Significativos

 Nós podems melhorar o código consideravelmente:



  public List getFlaggedCells() {
    List flaggedCells = new ArrayList();
    for (int[] cell : gameBoard) {
       if (cell[STATUS_VALUE] == FLAGGED) {
          flaggedCells.add(cell);
       }
    }
    return flaggedCells;
  }


   9
Nomes Significativos

 Faça distinções significativas entre as variáveis!


     Nomeação usando números em série (a1, a2, .. aN) é o oposto de nomeação intencional.

  public static void copyChars(char a1[], char a2[]) {
     for (int i = 0; i < a1.length; i++) {
        a2[i] = a1[i];
     }
  }




      10
Nomes Significativos

 A função se lê muito melhor quando “source” e “destination” são usados como
argumentos.


  public static void copyChars(char source[], char destination[]) {
    for (int i = 0; i < source.length; i++) {
       destination[i] = source[i];
    }
  }




    11
Nomes Significativos
 Use nomes pronunciáveis!

   Compare:
     class DtaRcrd102 {
        private Date genymdhms;
        private Date modymdhms;
        private final String pszqint = "102";
        /* ... */
     }

   Com:                                         Conversa inteligente: “Olá, João,
     class Customer {                            dê uma olhada nos dados deste
        private Date generationDate;             cliente! A data de geração do
        private Date modificationDate;           está carregada com a data de
        private final String recordId = "102";   amanhã! Como isto é possível?”
        /* ... */
     }

       12
Nomes Significativos
                                 Use nomes fáceis de encontrar (Searchable Names)!
     Se   uma variável deve ser usada em vários lugares no código, dê um nome de fácil procura.

                                 Compare:
    int s = 0;
    for (int j=0; j<10; j++) {
      s += (t[j])/5;
    }

                          Com:
    int NUMBER_TASKS = 10;
    int sum = 0;
    for (int j=0; j < NUMBER_TASKS; j++) {
      sum += (taskEstimate[j]) / WORK_DAYS_PER_WEEK;
    }
      13
Nomes Significativos
 Programadores Java não necessitam de notações hungaras (sName,   iAge,
etc) nem de colocarem qualquer prefixo nas variáveis.

 Compare:
   public class Part {
     private String description;
     void setDescription(String str_description) {
          description = str_description;
     }
   }
 Com:
   public class Part {
     String description;
     void setDescription(String description) {
         this.description = description;
      }
   }

     14
Funções

 As funções devem ser pequenas!


 Transparente óbvias!


 Sem duplicação!


 Fazem apenas uma coisa!


 Têm nomes descritivos e significativos!
   Não tenha medo de escolher um nome longo!
   Um nome longo e descritivo é melhor que um nome curto e enigmático.




    15
Funções – Número ideial de argumentos

 O número ideial de argumentos em uma função é zero.


 Depois vem um, seguido por dois.


 Três argumentos deverão ser evitados quando possível.


 Mais de quatro argumentos requerem uma justificação especial.


 Por quê?
   Argumentos são difíceis de ponto de vista dos testes. Imaginem a dificuldade em escrever
  todos os casos de testes para assegurar que as várias combinações dos argumentos trabalham
  corretamente.




    16
Funções - Argumentos booleanos (true / false)

 Argumentos booleanos são feios. Passando um booelan em uma função é uma
prática terrível.

 Ele imediatamente complica a assinatura do método,             proclamando em voz alta
que a função faz mais de uma coisa:
   Faz um   coisa se o argumento for true e outra coisa se o argumento false!


 Neste caso, nós devemos dividir a função em duas!




     17
Funções - Como escrever funções

 Quando eu escrevo funções, elas saem longas e complicadas.
 Elas têm um monte de “Ifs“ e “loops”.
 Os nomes são arbitrários, e existe duplicação de código.




 Então eu refino o código,
 dividindo em mais funções (que só fazem uma coisa),
 trocando os nomes,
 eliminando a duplicação.




    18
Comentários

 Comentários mentem. Nem sempre, e não intencionalmente, mas com muita
frequência.
   A razão é   simples. Programadores não podem realisticamente mantê-los!

 Uma das razões para escrever comentários é ver um código
                                                         confuso e
desorganizado . Então pensamos: vamos escrever um comentário!
   Antes   de gastar tempo com comentários no código, é melhor limpá-lo, reescrevendo-o!




    19
Comentários - Explique-se no código

 Compare:
  // Check to see if the employee is eligible for full benefits
  if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) {
     …
  }


 Com:
  if (employee.isEligibleForFullBenefits()) {
      …
  }

   Leva   poucos segundos de pensamento para sabermos a intenção do código.




      20
Comentários - Bons comentários

 Alguns comentários são necessários ou benéficos.



-- Comentários Legais (Legal Comments)
  Algumas vezes a nossa empresa nos força a escrever certos comentários por razões legais.

  // Copyright (C) 2003,2004,2005 by Infosistema, Inc. All rights reserved.
  // Released under the terms of the GNU General Public License version 2 or later.




    21
Comentários - Bons comentários
-- Comentários de explicação da intenção

  // This is our best attempt to get a race condition
  // by creating large number of threads.
  for (int i = 0; i < 25000; i++) {
     WidgetBuilderThread widgetBuilderThread =
          new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
     Thread thread = new Thread(widgetBuilderThread);
     thread.start();
  }

 Podem não concordar com a solução do programador, mas ao menos sabem o que
ele estava tentando fazer.




    22
Comentários - Bons comentários

-- Comentários de Clarificação

 Algumas vezes ajudam a traduzir o significado de códigos obscuros.


         assertTrue(a.compareTo(b) == 0); // a == b
         assertTrue(a.compareTo(b) != 0); // a != b

 É um risco substancial, é claro, que os comentários de clarificação estejam
incorretos. Então tomem cuidado para que sejam precisos!




    23
Comentários - Bons comentários

-- Comentários TODO (para fazer)
   Algumas  vezes é razoável deixar notas em forma de comentários //TODO
   São tarefas deviam ter sido feitas, mas por algum motivo não pode ser feita no momento.
   Pode ser um lembrete para apagar um recurso substituído (deprecated)
   Pode ser um lembrete para alguém olhar para o problema
      (Neste caso, pode-se também   usar //FIXME)
   Pode   ser um lembrete para fazer um mudança que está pendente de um evento planeado.

-- Comentários Javadocs em bibliotecas públicas (Public APIs)
   Não existe   nada mais útil e satisfatório que um bons comentários javadocs em bibliotecas
  públicas!




    24
Comentários - Maus comentários

-- Comentários de ruído (Noise Comments)

   Apenas reafirmam o óbvio e não fornecem novas informações.

     /** The day of the month. */
     private int dayOfMonth;


     /**
     * Returns the day of the month.
     *
     * @return the day of the month.
     */
     public int getDayOfMonth() {
          return dayOfMonth;
     }


          25
Comentários - Maus comentários

-- Comentários com atribuições Bylines

  /* Created by Marcio Silva */
  String name = “test“;

  /* Added by Marcio Silva */
  If (!customer.equals(“”)) {


 Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc)
que irão nos lembrar quem alterou o código!




    26
Comentários - Maus comentários
-- Códigos antigos comentados (Commented-Out Code)

    InputStreamResponse response = new InputStreamResponse();
    response.setBody(formatter.getResultStream(), formatter.getByteCount());
    // InputStream resultsStream = formatter.getResultStream();
    // StreamReader reader = new StreamReader(resultsStream);

 Outras pessoas que vêm o código comentário não têm coragem de apagá-lo.
 Elas pensam que eles estão lá por algum motivo.
     São importantes?
     Deixaram paralembrar uma mudança iminente ?
     Ou alguém comentou anos atrás e simplesmente não limpou ?


 Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc) que irão nos
lembrar as alterações no código!




      27
Comentários - Maus comentários
-- Comentários com muita informação (Too Much Information)


 Não coloquem discussões        históricas ou irrelevante s em seus comentários.
 Alguém lendo o código não tem necessidade ler toda esta informação.

/*
     RFC 2045 - Multipurpose Internet Mail Extensions (MIME)
     Part One: Format of Internet Message Bodies
     section 6.8. Base64 Content-Transfer-Encoding
     The encoding process represents 24-bit groups of input bits as output
     strings of 4 encoded characters. Proceeding from left to right, a
     24-bit input group is formed by concatenating 3 8-bit input groups.
     These 24 bits are then treated as 4 concatenated 6-bit groups, each
     of which is translated into a single digit in the base64 alphabet.
     When encoding a bit stream via the base64 encoding, the bit stream
     must be presumed to be ordered with the most-significant-bit first.
     That is, the first bit in the stream will be the high-order bit in
     the first 8-bit byte, and the eighth bit will be the low-order bit in
     the first 8-bit byte, and so on.
         28
*/
Síntese

 Para termos um código         limpo em Java, devemos:
 Criar variáveis com nomes significativos


  Criar funções com nomes significativos


  Escrever funções pequenas com apenas uma   intenção

  Escrever apenas bons comentários que ajudam na leitura clara   do código




  29
Próxima Sessão?

 Módulo 02
  Formatar o código fonte de maneira organizada     e estruturada
  Identificar as diferenças entre objetos e estrutura de dados
  Criar classes limpas e de fácil leitura




   30
Cuide bem do seu código!




         Mantenha-o limpo!
31
Muito Obrigado!
           
               Formador: Marcio Romualdo da Silva
             Email: marcioromualdo@yahoo.com.br




32

Código limpo

  • 1.
    Programação limpa emJava Módulo 01 - Nomenclatura, Funções e Comentários Data: 17/07/2012 Formador: Marcio Romualdo da Silva Email: marcioromualdo@yahoo.com.br 1
  • 2.
    Objetivos  Geral:  No final da sessão o formando será capaz de escrever código Java de forma limpa, clara e de fácil manutenção.  Específicos:  No final da sessão o formando será capaz de, na linguagem Java:  Criar variáveis com nomes significativos, sem precisar de comentários.  Criar funções com nomes significativos, sem precisar de comentários.  Escrever funcões pequenas com apenas uma única intenção.  Escrever comentários que ajudam na leitura clara do código.  Identificar os comentários que atrapalham a leitura clara do código. 2
  • 3.
     Código Sujoversus Código Limpo  3
  • 4.
    O que éum código limpo?  Simples e direto  Legível (readable)  Elegante e eficiênte  Com mínimas dependências para fácil manutenção  Com nomes significativos  Sem duplicação 4
  • 5.
    Por quê vocêescreveu código sujo?  Estava tentando ir mais rápido? Estava com pressa?  Seu chefe poderia ficar zangado se você tomasse tempo para limpar o código?  Estava cansado de trabalhar no projeto e queria acabar logo?  Havia outras coisas havia prometido terminar e o tempo era curto? 5
  • 6.
    O custo totalda sujeira  Assim que a sujeira aumenta, a produtividade da equipa diminui, aproximando do zero. 6
  • 7.
    Nomes Significativos  Usenomes que revelem a sua intenção!  Compare: int d; // elapsed time in days  Com: int elapsedTimeInDays; 7
  • 8.
    Nomes Significativos  Use nomes que revelem a sua intenção!  Qual o propósito deste código? public List getThem() { List list1 = new ArrayList(); for (int[] x : theList) { if (x[0] == 4) { list1.add(x); } } return list1; } 8
  • 9.
    Nomes Significativos  Nóspodems melhorar o código consideravelmente: public List getFlaggedCells() { List flaggedCells = new ArrayList(); for (int[] cell : gameBoard) { if (cell[STATUS_VALUE] == FLAGGED) { flaggedCells.add(cell); } } return flaggedCells; } 9
  • 10.
    Nomes Significativos  Façadistinções significativas entre as variáveis!  Nomeação usando números em série (a1, a2, .. aN) é o oposto de nomeação intencional. public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } } 10
  • 11.
    Nomes Significativos  Afunção se lê muito melhor quando “source” e “destination” são usados como argumentos. public static void copyChars(char source[], char destination[]) { for (int i = 0; i < source.length; i++) { destination[i] = source[i]; } } 11
  • 12.
    Nomes Significativos  Usenomes pronunciáveis!  Compare: class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqint = "102"; /* ... */ }  Com: Conversa inteligente: “Olá, João, class Customer { dê uma olhada nos dados deste private Date generationDate; cliente! A data de geração do private Date modificationDate; está carregada com a data de private final String recordId = "102"; amanhã! Como isto é possível?” /* ... */ } 12
  • 13.
    Nomes Significativos  Use nomes fáceis de encontrar (Searchable Names)!  Se uma variável deve ser usada em vários lugares no código, dê um nome de fácil procura.  Compare: int s = 0; for (int j=0; j<10; j++) { s += (t[j])/5; }  Com: int NUMBER_TASKS = 10; int sum = 0; for (int j=0; j < NUMBER_TASKS; j++) { sum += (taskEstimate[j]) / WORK_DAYS_PER_WEEK; } 13
  • 14.
    Nomes Significativos  ProgramadoresJava não necessitam de notações hungaras (sName, iAge, etc) nem de colocarem qualquer prefixo nas variáveis.  Compare: public class Part { private String description; void setDescription(String str_description) { description = str_description; } }  Com: public class Part { String description; void setDescription(String description) { this.description = description; } } 14
  • 15.
    Funções  As funçõesdevem ser pequenas!  Transparente óbvias!  Sem duplicação!  Fazem apenas uma coisa!  Têm nomes descritivos e significativos!  Não tenha medo de escolher um nome longo!  Um nome longo e descritivo é melhor que um nome curto e enigmático. 15
  • 16.
    Funções – Númeroideial de argumentos  O número ideial de argumentos em uma função é zero.  Depois vem um, seguido por dois.  Três argumentos deverão ser evitados quando possível.  Mais de quatro argumentos requerem uma justificação especial.  Por quê?  Argumentos são difíceis de ponto de vista dos testes. Imaginem a dificuldade em escrever todos os casos de testes para assegurar que as várias combinações dos argumentos trabalham corretamente. 16
  • 17.
    Funções - Argumentosbooleanos (true / false)  Argumentos booleanos são feios. Passando um booelan em uma função é uma prática terrível.  Ele imediatamente complica a assinatura do método, proclamando em voz alta que a função faz mais de uma coisa:  Faz um coisa se o argumento for true e outra coisa se o argumento false!  Neste caso, nós devemos dividir a função em duas! 17
  • 18.
    Funções - Comoescrever funções  Quando eu escrevo funções, elas saem longas e complicadas.  Elas têm um monte de “Ifs“ e “loops”.  Os nomes são arbitrários, e existe duplicação de código.  Então eu refino o código,  dividindo em mais funções (que só fazem uma coisa),  trocando os nomes,  eliminando a duplicação. 18
  • 19.
    Comentários  Comentários mentem.Nem sempre, e não intencionalmente, mas com muita frequência.  A razão é simples. Programadores não podem realisticamente mantê-los!  Uma das razões para escrever comentários é ver um código confuso e desorganizado . Então pensamos: vamos escrever um comentário!  Antes de gastar tempo com comentários no código, é melhor limpá-lo, reescrevendo-o! 19
  • 20.
    Comentários - Explique-seno código  Compare: // Check to see if the employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) { … }  Com: if (employee.isEligibleForFullBenefits()) { … }  Leva poucos segundos de pensamento para sabermos a intenção do código. 20
  • 21.
    Comentários - Bonscomentários  Alguns comentários são necessários ou benéficos. -- Comentários Legais (Legal Comments) Algumas vezes a nossa empresa nos força a escrever certos comentários por razões legais. // Copyright (C) 2003,2004,2005 by Infosistema, Inc. All rights reserved. // Released under the terms of the GNU General Public License version 2 or later. 21
  • 22.
    Comentários - Bonscomentários -- Comentários de explicação da intenção // This is our best attempt to get a race condition // by creating large number of threads. for (int i = 0; i < 25000; i++) { WidgetBuilderThread widgetBuilderThread = new WidgetBuilderThread(widgetBuilder, text, parent, failFlag); Thread thread = new Thread(widgetBuilderThread); thread.start(); }  Podem não concordar com a solução do programador, mas ao menos sabem o que ele estava tentando fazer. 22
  • 23.
    Comentários - Bonscomentários -- Comentários de Clarificação  Algumas vezes ajudam a traduzir o significado de códigos obscuros. assertTrue(a.compareTo(b) == 0); // a == b assertTrue(a.compareTo(b) != 0); // a != b  É um risco substancial, é claro, que os comentários de clarificação estejam incorretos. Então tomem cuidado para que sejam precisos! 23
  • 24.
    Comentários - Bonscomentários -- Comentários TODO (para fazer)  Algumas vezes é razoável deixar notas em forma de comentários //TODO  São tarefas deviam ter sido feitas, mas por algum motivo não pode ser feita no momento.  Pode ser um lembrete para apagar um recurso substituído (deprecated)  Pode ser um lembrete para alguém olhar para o problema  (Neste caso, pode-se também usar //FIXME)  Pode ser um lembrete para fazer um mudança que está pendente de um evento planeado. -- Comentários Javadocs em bibliotecas públicas (Public APIs)  Não existe nada mais útil e satisfatório que um bons comentários javadocs em bibliotecas públicas! 24
  • 25.
    Comentários - Mauscomentários -- Comentários de ruído (Noise Comments)  Apenas reafirmam o óbvio e não fornecem novas informações. /** The day of the month. */ private int dayOfMonth; /** * Returns the day of the month. * * @return the day of the month. */ public int getDayOfMonth() { return dayOfMonth; } 25
  • 26.
    Comentários - Mauscomentários -- Comentários com atribuições Bylines /* Created by Marcio Silva */ String name = “test“; /* Added by Marcio Silva */ If (!customer.equals(“”)) {  Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc) que irão nos lembrar quem alterou o código! 26
  • 27.
    Comentários - Mauscomentários -- Códigos antigos comentados (Commented-Out Code) InputStreamResponse response = new InputStreamResponse(); response.setBody(formatter.getResultStream(), formatter.getByteCount()); // InputStream resultsStream = formatter.getResultStream(); // StreamReader reader = new StreamReader(resultsStream);  Outras pessoas que vêm o código comentário não têm coragem de apagá-lo.  Elas pensam que eles estão lá por algum motivo.  São importantes?  Deixaram paralembrar uma mudança iminente ?  Ou alguém comentou anos atrás e simplesmente não limpou ?  Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc) que irão nos lembrar as alterações no código! 27
  • 28.
    Comentários - Mauscomentários -- Comentários com muita informação (Too Much Information)  Não coloquem discussões históricas ou irrelevante s em seus comentários.  Alguém lendo o código não tem necessidade ler toda esta informação. /* RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies section 6.8. Base64 Content-Transfer-Encoding The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. When encoding a bit stream via the base64 encoding, the bit stream must be presumed to be ordered with the most-significant-bit first. That is, the first bit in the stream will be the high-order bit in the first 8-bit byte, and the eighth bit will be the low-order bit in the first 8-bit byte, and so on. 28 */
  • 29.
    Síntese  Para termosum código limpo em Java, devemos: Criar variáveis com nomes significativos  Criar funções com nomes significativos  Escrever funções pequenas com apenas uma intenção  Escrever apenas bons comentários que ajudam na leitura clara do código 29
  • 30.
    Próxima Sessão?  Módulo02  Formatar o código fonte de maneira organizada e estruturada  Identificar as diferenças entre objetos e estrutura de dados  Criar classes limpas e de fácil leitura 30
  • 31.
    Cuide bem doseu código! Mantenha-o limpo! 31
  • 32.
    Muito Obrigado!  Formador: Marcio Romualdo da Silva Email: marcioromualdo@yahoo.com.br 32

Notas do Editor

  • #7 Assim que a produtividade diminui, a gestão faz somente um coisa que eles podem: Adicionam mais pessoas no projeto na esperança de aumentar a produtividade. Mas as novas pessoas não conhecem o design do sistema. Toda a gente fica debaixo de uma enorme pressão para aumentar a produtividade.
  • #10 flaggedCells = bandeiras marcadas gameBoard = tabuleiro
  • #16 One way to know that a function is doing more than “one thing” is if you can extract another function from it with a name that is not merely a restatement of its implementation.
  • #17 Quando uma função parece precisar de mais do que dois ou três argumentos, é provável que alguns desses argumentos deve ser envolvido em uma classe própria. Compare: Circle makeCircle(double x, double y, double radius); Com: Circle makeCircle(Point center, double radius);
  • #18 The method call render(true) is just plain confusing to a poor reader. Mousing over the call and seeing render(boolean isSuite) helps a little, but not that much. We should have split the function into two: renderForSuite() and renderForSingleTest().
  • #20 We know it’s a mess. So we say to ourselves, “Ooh, I’d better comment that!” No! You’d better clean it! Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.
  • #21 In many cases it’s simply a matter of creating a function that says the same thing as the comment you want to write.
  • #25 Seja o que for um TODO, não é desculpa para deixar um mau código no sistema.
  • #26 Sometimes we see comments that are nothing but noise. They restate the obvious and provide no new information.
  • #28 Those systems will remember the code for us. We don’t have to comment it out any more. Just delete the code. We won’t lose it. Promise.
  • #29 Alguém lendo o seu código não tem necessidade ler toda esta informação.