Código Limpo – Parte 05

Oi pessoal, tudo bem?

Realmente faz tempo que não postava algo, mas é por que o projeto de bloco da Pós-Graduação está tomando muito tempo. Então está complicado criar os posts.

Vamos continuar falando sobre Código Limpo? Os antigos posts você encontra aqui: Parte 01, Parte 02, Parte 03, Parte 04.

  • Copiar e Colar (mesmo em códigos não OO) -> Evitem isso ao máximo. Ao realizar uma tarefa existe uma enorme facilidade em copiar código de um lugar, e aplicar onde precisamos alterar. Com essa replicação de código estamos aumentando a dificuldade de manutenção, quebrando bons padrões de programação e talvez até propagando bugs.

    Imagine que existe um método com um complexo cálculo, onde é necessário aplicá-lo a outras partes do sistema. Ao invés de fazer alterações bem pensadas para deixar o método mais genérico, alguns desenvolvedores, acabam por escolher o mais fácil que seria copiar, colar. Após copiar e colar basta fazer pequenos ajustes. Imagine agora que após certo tempo nota-se que existe um erro no cálculo e alteramos o método inicial e o que foi replicado, mas o antigo programador não falou que esse código foi replicado mais 3x. Imaginou? Seria mais fácil ter criado apenas um método que fosse invocado em todas as partes do sistema.Reflita nisso. Quando você pensar “Eu já fiz esse código antes…”, quer dizer que é hora de parar, pensar e ver que está acontecendo uma provável duplicação:
    • Códigos não OO -> Crie apenas uma função e utilize-a de qualquer lugar do sistema.
    • Códigos OO -> Hora de aplicar super classes, classes abstrata, etc.
  • Remover código desnecessário -> Já reparou a quantidade códigos comentados existem em programas legados? Por exemplo:
    // user.setCreditCardByDate(credidCard, new Date());
    user.setCreditCard(credidCard);
    list.add(user);
    //for(int a = 0; i < list.size(); i++){
        //daoUser.deleteCredidCardHistory(list.get(i));
        //Logger.debug("im here!!!!");
    //}
    daoUser.deleteCredidCardHistory(list);

    Se esse método já está ultrapassado, por que mantê-lo? As vezes é normal deixar o código antigo enquanto se faz testes, mas salvá-los? Se você está incerto de sua alteração, é melhor pensar duas vezes antes de salvá-la por definitivo.
    Se tivermos um versionador qual seria o propósito de salvar um código comentado? Uma vez que temos essa ferramenta para consultar o antigo código sempre.

    O código salvo tem que ser um código limpo, que seja fácil de entender, objetivo. Quando um código apresenta vários códigos antigos comentados, o código atual perde um pouco do foco pois o desenvolvedor pode querer entender o código antigo comentado.

    Olhe como ficaria mais limpo o código:

    user.setCreditCard(credidCard);
    list.add(user);
    daoUser.deleteCredidCardHistory(list);
  • Conhecimento da linguagem -> Procure sempre aprimorar seu conhecimento na linguagem. Algumas vezes a própria linguagem já contém métodos prontos e já funcionais para você. “Não existe a necessidade reinventar a roda”. Mantenha-se informado sobre sua linguagem de desenvolvimento, se informe das novidades. Quando você receber uma tarefa que exige algo que você não fez ainda, pesquise.
    Um exemplo que uma vez encontrei, e virou piada na empresa, está no pedaço de código abaixo:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            i = 13;
        }
        // Do stuff
    }

    Vocês podem ver que ao invés de usar a palavra break, o desenvolvedor alterou o valor do contador. Sendo que poderia ser feito de forma mais fácil e com mais estilo:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            break;
        }
        // Do stuff
    }

    Talvez você pense: “Bem, estava funcionando não estava?” Eu te responderei que sim, mas também acrescento que você não irá virar piada se você estiver sempre querendo conhecer sua ferramenta de trabalho. Outra coisa a se pensar é, e se realmente fosse necessário alterar o valor do contador? Se o total subisse para 100 ao invés de 10? Teria que aumentar o valor do contador junto com o valor total de loops. Não vale a pena.

  • TODO – As IDEs de hoje nos ajudam muito com esse lembrete. Facilmente podemos escrever “// TODO” (em português “A Fazer”), e ver essas referências que estão por todo classe/sistema. Realmente é muito simples colocar esse lembrete em meio ao nosso código, pode nos lembrar de tudo que realmente está pendente.TODO
    O problema é que assim como é fácil criar é fácil esquecer. Uma vez que isso vire prática na empresa, milhares de TODOs poderão aparecer na view de Tasks em pouco tempo, com isso, vão ficar poluídos a view e seu código.
    Uma saída seria evitar esse tipo de abordagem, uma vez que você sabe que não existe previsão para realizar a alteração marcada no TODO. (Para mais informações dessa abordagem: Watch out for TODO comments! By Alexandre Gazola).
    Outra saída seria criar tags personalizadas. Para isso, a tag TODO poderia ter seu uso definido apenas para ações rápidas e que serão finalizadas antes do código ser salvo no versionador. Poderíamos criar, por exemplo: “// REMAKE …” ou então “// REFACTOR …” E pelas IDEs é possível filtrar por tags customizadas.
  • Perca seu orgulho – Creio que uma das maiores barreiras do ser humano é essa, perder o orgulho. Talvez você tenha uma tarefa a fazer, tenha 30 anos como desenvolvedor e com isso acaba por não comentar com ninguém ou trocar idéias sobre sua tarefa. Orgulho é algo que apenas prejudica o ser humano. A melhor coisa a se fazer é ter um bate papo rápido com algumas pessoas da equipe para coletar idéias, mescle todas, e pode ter certeza que seu código tem tudo para ter bons padrões de projeto, as corretas tecnologias e uma boa modelagem OO.
    Não é só por que alguém acabou de entrar na equipe que ele não irá ter conhecimento algum. Conversar e trocar idéias irá levar seu projeto a um novo patamar.
    Deixe seu orgulho de lado, ele não irá te levar a lugar algum.

Por hoje é só qualquer observação basta colocar. Não sei quando irei postar novamente por causa da Pós-Graduação, mas em breve terei várias tutoriais para colocar aqui.

Até mais! o_

Código Limpo – Parte 04

Olá, tudo bem? Para melhorar nosso código, vamos continuar o estudo sobre código limpo? Os outros artigos estão aqui: Parte UmParte DoisParte Três.

Hoje será abordado Constantes e Exceptions.

  • Formato do nome – A constante tem seu nome escrito em caixa alta “COR”; e separado por “_” quando é um nome composto: “GOL_CONTRA”. Não começar com “_” pois não existe necessidade, essa técnica era utilizada em outras linguagens para diferenciar método de atributo.
  • Nome define o uso – Uma constante fica clara graças ao se nome, que deve ser objetivo. Ela deve ser entendível onde quer que seja utilizada. Caso você tenha uma constante de log, por exemplo, utilizando apenas LOG como nome não seria tão claro como LOGGER. A diferença é clara quanto à própria definição da palavara, LOG é algo gerado e LOGGER é quem gera. Não importa onde esteja o nome LOGGER, sempre conseguiremos entender a função dessa constante.
  • Quando constantes são necessárias – Devemos sempre estar atentos quanto a repetições. Sempre que estamos repetindo uma ação ou valor tem algo errado acontecendo. Vamos supor que temos um método que altera o placar em uma partida de futebol:
    public void changeScore(Team team, int goal){
        this.fullScore(team, gol);
    }

    E esse método é utilizado da seguinte forma para registrar um gol contra:

    public void recordOwnGoal(Team team){
        match.changeScore(team, -1);
    }

    Imagine toda vez que fosse necessário informar um gol contra a algum método; teríamos sempre que escrever o “-1″ por exemplo:“registrarGolParaJogador(jogador, -1);”. Por que não criar uma constante? Com essa constante iríamos poder eliminar um método. Veja como o processo final para registrar um gol contra ficaria:

    //Our declared Constant in the Match class.
    public static final int OWN_GOAL = -1;
    
    public void changeScore(Team team, int goal){
        this.fullScore(team, goal);
    }

    Note que não existe mais a necessidade de utilizar o método “registrarGolContra”, pois a única razão de sua existência era colocar o valor do gol como negativo. Com isso, ao chamar o método alterarPlacar bastaria passar a constante GOL_CONTRA ao invés de ter que chamar/criar um método para isso ( alterarPlacar(time, GOL_CONTRA); ). Constantes são muito bem vindos por exemplo, em construção de templates: “ADICIONAR_LINHA_SIMPLES”, “ADICIONAR_LINHA_COMPOSTA”, “PARAGRAFO”, e outros mais. Basta notar, está sempre tendo que passar um mesmo valor? É hora de utilizar uma constante.

  • Existe uma razão, qual é? – Ao criar uma captura de exceção devemos nos ater ao porque daquela captura. Devemos sempre focar no fato de que, se algum método declara que uma exceção pode ser lançada, um tratamento deve ser dada para ela. Devemos sempre ver o melhor modo de tratar esse infortúnio, alguns exemplos seriam: o que mostrar ao usuário (exceção tratada), como tratar as ações inacabadas (arquivos, transações com db, log, etc).
    Ao ignorar um exceção, não tratando seu objeto do tipo “Exception”, estamos simplesmente desrespeitando o contrato do método o que poderia acarretar problemas para o usuário e à sua aplicação.
  • Exception impossível de acontecer, mas é declarada? Certa vez enquanto alterava um código, notei que ao testar a funcionalidade ela não funcionava e não apontava erro. E mesmo revisando meu código ví que ele estava correto e não achei problema algum.
    O que fazer para achar o erro? Debug!
    Comecei a percorrer o código e me deparei com o seguinte código:

    //...
    validateCreditCard(creditCard);
    //...
    }catch(CreditCardInUseException){
        //Impossible to get here
    }

    Quando o método de validar cartão crédito foi criado realmente não havia a possibilidade de o cartão estar em uso, e por isso o comentário descrevia que seria impossível chegar ali. Mas vemos nesse caso dois pontos passíveis de melhorias:

    1. Método não coeso – note que o método de validar o cartão lança uma exceção que às vezes é valida e outras não. Existe dentro deste método uma regra de negócio que diferencia seu comportamento, e a diferença de comportamento altera o tratamento dado a sua assinatura (futuro assunto sobre OO); uma solução seria separar esse método que está tendo tantos comportamentos diferentes, pois ele está em um estado “delicado” tendo muitas decisões dentro dele.
      Para uma exceção acontecer, ela deve ser tratada e em nosso caso – quando o código foi criado – não tinha como acontecer nenhum tratamento. Se existe um método que declara uma exceção que nunca irá acontecer, tem algo errado!
    2. Se uma exceção é lançada, ela tem o seu motivo e ela deve ser tratada. Perceba que se a exceção estivesse sendo tratada, e no mínimo, com “System.out.println();” haveria uma mensagem informando que algo aconteceu. Digo no mínimo, pois poderíamos dar diversos tratamentos como registrar em log, enviar email, etc. Algo estava acontecendo, uma exceção sendo lançada, mas nenhuma ação estava sendo tomada. Lembre-se: “Se uma exceção é lançada, existe um motivo e ela deve ser levada em consideração.”.
  • Mensagens de erros claras – As mensagens de erros devem ser claras, de modo que um usuário possa entender. Afinal, é ele quem estará lendo e tem a “obrigação” de entender. Evite mensagens como: “Ação Ilegal!” ou “Erro!”. Esse tipo de mensagem não esclarece em nada o usuário, e pelo contrário, apenas fará com que ele fique mais confuso.
    Um bom momento de se escrever as mensagens de erro é enquanto se desenvolve/refatora a função, pois você estará ciente de todo o processo.
  • Escrevendo mensagens de erro – Ao escrever uma mensagem de erro evite pensar: “Vou colocar a mensagem assim, pois está bem claro que é sobre esse assunto que estamos falando.”. Será? O usuário não pensa como desenvolvedor, ele não tem que saber que o valor X vem da tela Y e é necessário para chegar à tela Z.
    Quando estiver em dúvida de como colocar a mensagem, olhe para tela e tente esquecer tudo o que você sabe sobre ela e pense: “Sendo alguém que nada sabe sobre desenvolvimento, como entenderia melhor essa mensagem de erro?” Adapte essa pergunta ao que você está desenvolvendo, mude seu modo de pensar e mantenha seu foco no usuário. Uma outra boa opção é chamar um colega do trabalho para dar uma opinião.
  • Evite certas mensagens de erro ao desenvolver – Enquanto estiver a desenvolver, evite mensagens como: “Ta vendo? Por sua culpa gerou erro!” ou “Seu Zé Mané, digita alguma coisa aqui!”. Às vezes é divertido e até mesmo gera certo alívio quando uma mensagem desse tipo é exibida, mas é aí que mora o perigo. Imagina se essa mensagem permanece salva no código e é enviada ao cliente. Por mais divertido que seja, é melhor evitar.
  • Log4J – Uma boa ferramenta que poderá ser util na hora de registrar exceções é o Log4J. Com essa biblioteca é possível registrar log em diferentes tipos de níveis e outras opções mais. Pretendo ainda escrever um tutorial sobre ela, mas enquanto não fica pronto, vai aí uma dica para quem se interessar: http://www.guj.com.br/article.show.logic?id=130

Espero que essas dicas possam ter ajudado.
Até a próxima pessoal.

Código Limpo – Parte 03

Olá, tudo bem?

Vamos falar sobre a terceira parte do tema: “Código limpo”? Os primeiros artigos você encontra a seguir: Código Limpo – Parte 01, Código Limpo – Parte 02

Eu alterei a ordem do tema Código Limpo e hoje estaremos falando sobre Comentários:

  • Comente explicando o “por que” – Seu comentário deve explicar o porquê de sua execução e não “como”. A parte do “como” deve ser explicada pelo próprio código. Acontece que ao colocar o comentário de como o método funciona o código tende ficar mau feito, com péssimos padrões. Você começa a confiar que seu comentário irá explicar como o método deve funcionar, mas na verdade, o código deve ser “auto-explicável”.
    /**
     * This method publishes the documents using a proxy connection
     * to save the files in the necessary patterns
     * There is a loop (repetition) on going while the methods does not end
     * 
     */
    public void publishDocuments(){
        // some code...
    }

    No comentário do método está escrito o que ele faz, o modo como ele executa o processo, mas isso tem que ser percebido ao ler o código. Caso seja um pacote de classes exportadas, qual a finalidade do usuário ler esse tipo de comentário? O usuário precisa apenas saber o que esse método faz e pronto. Olhe como ficaria mais claro com o comentário mais objetivo:

    /**
     * Method that publishes the files, in html, which save them 
     * Applying w3c patterns.
     * 
     */
    public void publishDocuments(){
        // some code...
    }

    O comentário ele descreve o objetivo do método, o porquê de sua existência, e não dá descrições sobre sua implementação.

  • Sem abreviaturas – Não utilize abreviações em seus comentários, eles dificultam a leitura.
    //Hold ref to cli PPV
    Account account = daoFactory().getDaoAccount.getAccount();
    //Holds the reference to the clients Pay Per View
    Account account = daoFactory().getDaoAccount.getAccount();

    Comentando sem abreviar você gasta pouco tempo a mais digitando, mas deixa o código bem mais claro para quem o ler pela primeira vez. Lembre: “você cria o código para os outros lerem, ele te define como profissional”.

  • Não documentar o óbvio – Existem códigos que não tem a necessidade de serem documentados. Ao fazer isso, a qualidade do seu código irá diminuir. E pior, fazer isso é tão fácil…
    /**
     *Methods that calculates the bill total value
     * 
     */
    public void calculateBillTotalValue(Customer customer, Bill notPaidBill){
        // Creates the closed bill date with "today" date
        Date closedBillDate = new Date();
        
        // Sets unPaidBills to zero
        int unPaidBills = 0;
    
        // Check if the bills has the payment delayed
        if (notPaidBill.isPaymentDelayed(closedBillDate)){
            // If the payment is delayed add some interest
            notPaidBill.addInterest(closedBillDate);
        }
        
        // some code...
    }

    O código acima não precisava daquele tipo de comentário, e o comentário do método apenas repete o nome do método. Quando seu código está bem claro, não é necessário comentar todas as linhas.

    /**
     * Method that calculates the total bill value that has to be paid, add interest if needed.
     * 
     */
    public void calculateBillTotalValue(Customer customer, Bill notPaidBill){
        Date closedBillDate = new Date();
        int unPaidBills = 0;
    
        if (notPaidBill.isPaymentDelayed(closedBillDate)){
            notPaidBill.addInterest(closedBillDate);
        }
        
        // some code...
    }

    Conseguimos ler o código de modo claro, sem a necessidade de comentários desnecessários. O acúmulo de comentários repetitivos deixa seu código sujo, enorme, difícil de se ler, e ainda por cima, pode irritar o leitor. Sem falar que aumenta o tempo de desenvolvimento, pois serão muitas linhas escritas e formatadas sendo que acabam por ser desnecessárias.

  • /* fim for */ ou /* fim while */ – Colocar essa anotação ao final de uma repetição é útil apenas quando se tem uma seqüência aninhada de repetições.
    while ( /*  while controller */){
        while ( /*  while controller */){
            while ( /*  while controller */){
                
            }/* end while */
        }/* end while */
    }/* end while */
    car.turnOffEngine();

    Esse tipo de comentário torna mais claro a leitura quando temos uma seqüência de repetições aninhadas, mas fica prejudicial quando temos apenas uma repetição.

    while ( /*  while controller */){
    }/* end while */
    car.turnOffEngine();

    OBS.: No caso de muitas repetições aninhadas pode-se pensar em separá-las e colocando-as em métodos separados.

  • Comentários em excesso [1] – Quando se comenta em excesso, seu código fica poluído, difícil de ler. O foco de quem lê acaba indo para os comentários, quando o real foco tinha que ser o código escrito. Quando seu código está limpo e objetivo existe uma necessidade mínima em ter que comentar todo o código, aumentando a facilidade inclusive de localizar alguns bugs que acontecem com relação a regras de negócio, pois o foco passa de ser o comentário e vai para o código.
  • Comentários em excesso [2] – Ao notar uma quantidade enorme de comentários para um método ou algum cálculo talvez seja hora de refatorar o método. Seu código deve sempre ser claro, de fácil entendimento. Não deve existir a necessidade de escrever muitas palavras para descrever sua função.
  • Informar, caso exista, conseqüências – Sempre deixe claras as conseqüências de se executar o método. Existem métodos que podem ter conseqüências que realmente venham a afetar o comportamento do sistema de um modo não esperado. Como por exemplo: irá limpar dados temporários, apagar dados do banco de dados, iniciar, a cada chamada do método, uma conexão remota que irá pesar o processamento da máquina.
  • Necessidade dos comentários – Um código bem definido pode eliminar a maioria dos comentários. Utilize comentários apenas quando necessário, e deixe que seu código fale por ele mesmo.

Espero que esse artigo possa ter agregado valor ao seu conhecimento. Dúvidas? Basta comentar que eu respondo.

Até a próxima

Código Limpo – Parte 02

Boa noite pessoal, tudo bem?
Vamos continuar com o assunto de como manter um código limpo? A primeira parte do assunto, você encontra aqui: Código Limpo – Parte 01.

Falemos um pouco sobre variáveis de escopo e atributos.

OBS.: Toda vez que eu escrever atributos eu estarei me referindo aos dois casos, ok? Tanto como variáveis de escopo (parametros de métodos, definições de variáveis dentro de loops), tanto quanto atributos de classe. Apenas para não ter que repetir atributo/variável toda hora aumentando o texto.

    • Usar camelCase no nome do atributo – essa dica é uma dica básica e bastante encontrada por aí. Facilita a leitura e é utilizado em convenções de várias linguagens de programação. Alguns exemplos seriam:
          String disapprovedStudent;
          double totalDivide;
          boolean isManager;

      Uma vantagem é que é mais fácil ler na forma camelCase do que:

          List player_own_goals;
          List playerOwnGoals;

      Uma desvantagem seria em um nome grande:

      Map allYellowHousesFromTheBlock;

      Ou seja, utilize e não abuse. ;)

    • Nome de lista no plural – para que colocar nome “listaPessoa” se colocar “pessoas” já dá o mesmo sentido? E existe uma diferença enorme entre pessoa e pessoasanalisando o conceito da palavra. Mantenha esse conceito em mente e verás como seu código ficará legível. Veja só o “foreach” como ficaria:
          List houses = new ArrayList();
          // adds the houses from the block at the list
          for (House house: houses) {
              this.ringBell(house);
              this.runForYouLife();
          }

      Perceba que ao ler o nome da lista “casas” fica claro que estamos falando de um conjunto de “casa”. Quanto mais frequente esse tipo de nomeclatura for utilizada em seu sistema, mais claro ficará para quem estiver lendo, o que o atributo significa e o seu valor no método.

    • Devemos dar nomes reais que sejam fáceis de falar, nomes que se “auto-expliquem”. Imagine só, caso você visse a seguinte declaração:
      public class Car{
          //... some code
          boolean caCra;
          //... some code
      }

      O que ela deve significar? Qual seria sua utilidade? Como se fala? Imagine você chamando seu colega de trabalho, e ao tentar explicar o que estás a fazer, ele pergunta: “Ta, mas você está falando de qual atributo?”! Como você falaria?
      Sendo o nome direto, objetivo e “falável” você já pode imaginar o que significa, e ao comentar o código com alguém, seria mais fácil de ser dito e a pessoa que o ouvir poderia se lembrar dessa parte do código facilmente. Ah sim, qual seria o nome mesmo daquele atributo?

      public class Car{
          //... some code
          boolean isCarCrashed;
          //... some code
      }
    • Caso você veja o código a seguir, cuidado pois ele pode trazer muito entendimento incorreto:
          int value1, value2, value3;
          // ou
          String name1, name2, name3;

      O que poderia significar o um, dois ou três? Veja que em nenhum momento o atributo dá a entender onde deveria ser utilizado, e qual seria sua função. O código fica difícil de entender. Caso você tenha o azar de cair em if/else/while aninhados com esse tipo de atributo, é hora de levantar e ir pegar um café por que a tarde será longa… Imagine a seguinte situação:

          String str1, str2, str3, str4;
          //... some code
          str4 = str3.substring(4,8) + str1.concat(str2);

      Agora, imagine se o código tivesse sido escrito assim:

          String userLogin, userPassword, lastLoginDate, userAccessKey;
          //... some code
          userAccessKey = lastLoginDate.replaceAll("/", "-") + userLogin.concat("-" + userPassword);

      Conseguimos entender o que esse código está fazendo apenas pelos nomes dos atributos. Se estiver dentro de um método que tenha um nome claro então… Faz a combinação para deixar qualquer programador que leia o seu código feliz. Eu vi um caso em que semanticamente (pois era um estudo de OO) ao qual não haveria outra possibilidade de se colocar nomes que não tivesse 1 e 2 no final. Caso você tenha em mente o mesmo conceito e percepção, de que o projeto perderia coesão e sua definição se os atributos não tivessem o número no final, vá em frente e implemente seu código.

    • Os nomes dos atributos têm que sempre manter sentio ao contexto ao qual estão sendo utilizados. Sempre que ao ler o nome de um atributo ele tem que fazer sentido no trecho em que está aparecendo.
          //... some code
          int total = 0;
          for (Trade tradedBall : tratedBalls) {
              total += tradedBall.getTotalTratedItens();
          }
          for (Trade tratedHelmet : tratedHelmets) {
              total += tratedHelmet.getTotalTratedItens();
          }
          StockFacade stockFacade = FacadeFactory.getStockFacade();
          stockFacade.updateAmountTratedItens(total);
          //... some code in the same method
          //...
          //... 15 lines after
          double totalSpent = financialFacade.calculateSpentValue(spentValuesWithEmployees + (valuePerIten * total));
          return totalSpent;

      Quem é esse total que apareceu do nada ali no cálculo final? De onde veio esse valor? Qual o papel dele nesse método? Agora, imagina se ao invés de total fosse totalItensTrocados? Leia o código novamente trocando o total pelo nome sugerido.
      Essa é a diferença de se manter um nome que sempre tenha valor no contexto em que está sendo utilizado.

    • Não especificar na frente do nome do atributo o seu tipo. É muito comum se encontrar intIdade, strNome, dtNascimento. Você pode se perguntar: Que mal há nisso? Lembre que uma das boas práticas seria o fato do próprio nome do atributo se “auto-explicar”? Colocando o atributo na frente existem algumas desvantagens:
      • Incentivo às más nomenclaturas – é muito mais fácil pensar em colocar dtNascimento do que dataNascimento. Com isso, a idéia de nomes “auto-explicativos” iria começar a falhar. Poderiam nomes estranho como dtNas ou dtMNat (dataMorteNatural).
      • Variação na abreviação do tipo – seria fácil começar a encontrar algumas variações como: strNome, stNome, sNome, ou nmNome(se fosse apenas nome resolveria). Até aí nada de exagerado, agora imagine se sua aplicação tem um javascript e nele você começa a ver: cbDtIni ou então txNmCp. Qual seria a sua reação? Você saberia explicar cada um deles? Creia em mim, não é exagero, eu já vi atributos com esse tipo de nome.

      Evite esse tipo de prática, esse tipo de nome nos seu atributo irá causar uma leitura de código demorada e trabalhosa.

  • Já pensou em ter atributos de nomes pequenos e fáceis de digitar? Suponhamos que em seu programa você tenha uma variável chamada “todosOsAliensDoUniverso”. Agora imagine você tendo que digitar isso toda vez… Se bem que se essa variável se chamasse “aliens” seria… hum… Bem mais fácil de digitar e deu a entender que é uma lista. Não tem hora que você está fazendo aquele código legal e você pensa: “Caramba, tenho que digitar esse nome de novo?!”. Com um auto-completar hoje das IDEs tem ficado mais facil, mas imagine a pessoa ter que escolher entre 5 nomes toda hora, sendo que ela poderia estar a digitá-caso ele fosse pequeno…  Lembre-se, o nome de um atributo não deve afastar pessoas.
  • Espaço entre seus atributos – um código que envolva cálculos sem espaço entre seus atributos, fica um código que causa dor de cabeça! Vejamos um exemplo:
    total=salesPerDay(today)-(COMMITTEE_PERCENTAGE*vendors+totalSoldItens);

    Um código ganha mais clareza quando se tem espaços entre seus atributos:

    total = salesPerDay(today) - (COMMITTEE_PERCENTAGE * vendors + totalSoldItens);
  • Evitar o envio de atributos nulos – o envio de atributos nulos é a raiz de muitos nullPointers! Imagine só, você está acessando um método que nunca usou, mas falaram para você: “Vai lá, coloque o código chamando o método e envie o produto para o cliente. Pode confiar que esse método nunca deu erro!”. Só que não te explicaram que não poderia passar null. Com isso, uma imagem muito feia apareceria para o cliente e a confiança do cliente no programa ficaria afetada.

Bem pessoal, espero que esse artigo de hoje possa lhes ajudar.

Esse assunto terá continuação.

Até mais. [=

Código Limpo – Parte 01

Já pensou no que as pessoas dizem sobre você após lerem seu código? Não me refiro apenas às pessoas das quais hoje você convive, imagine sobre a primeira empresa que você trabalhou, será que seu código é elogiado? Se seu companheiro de trabalho for ler e entender seu ultimo código, será que ele poderá ter um surto psicótico? O que você pensa, hoje, sobre a qualidade do código que deixaram para você alterar? Qual o nível de habilidade você daria para essa pessoa?

A pergunta que vai ecoar é: “Após analisarem nosso código, eles poderão nos indicar como referência para desenvolvimento?” (ouch!).

Para que isso aconteça, devemos adotar certas boas práticas e costumes enquanto estivermos fazendo nosso “if de cada dia”. Como esse conteúdo é extenso, vou dividi-lo em várias partes.

Como exemplo, iremos utilizar um sistema de consulta à informações das partidas de futebol. Eis um breve resumo: “O sistema Futebol Show tem por objetivo informar dados das partidas. O sistema deve conter: data/horário das partidas agendadas, local da partida, times que estarão jogando (e seus jogadores), trio de arbitragem. Ao final de cada jogo, o sistema retornará a quantidade de gols (total, e gol marcado por cada jogador), o resultado, soma dos cartões aplicados pelo juiz”.

1 – Classes

  • É aconselhável que as classes tenham nomes de substantivos. No nosso exemplo, poderíamos identificar: Partida, Estádio (local da partida), Time, Arbitragem, Jogadores. Isso lhe ajudará a pensar e entender o que está sendo feito, e para onde o sistema está caminhando. Dar-te-á uma melhor visão do contexto. Imagine se colocássemos Estádio como String na classe Partida. Se pedissem para adicionar mais tarde capacidade de pessoas, teríamos que criar mais um atributo em Partida, a classe partida começaria a perder sua Coesão, pois quem deve saber a capacidade de pessoa no estádio é o Estádio, não a Partida.
  • Nome das classes no singular. Se você acabasse de ler uma classe nomeada como Jogadores. O que vem a sua cabeça? Provavelmente, um conjunto de Jogadores. Bem óbvio, mas acreditem, já vi acontecer de encontrar nome de classes no plural. E ao questionar o porquê, não me disseram (ninguém sabia), sendo que a função da classe era de ser um objeto único mesmo. Nomeando corretamente sua classe, irá trazer mais clareza ao propósito da classe.

2 – Métodos

  • O nome dos métodos devem indicar um verbo. Após ler a ação no nome, já temos uma boa idéia do que ele irá realizar. Por exemplo:
    match.goal(value);

    O que esse código faz? O que ele retorna? Lá se vai um tempo para ter que entrar na classe, analisar o método… Imaginem se fosse escrito assim:

    match.getGoalsByPlayer(player);

    Ao ler o nome do método (com o verbo), já dá para ter uma noção do retorno, e inclusive, um provável comportamento do método.

  • É indicado que cada método mantenha um único objetivo. Imagine se você for chamar o método para buscar o total de pessoas presentes na partida:
    List presentAudience = match.getTotalPresentAudience();

    Mas ao executar o método, a seguinte mensagem é retornada:

    Exception in thread "main" main.DaoPublicException
      at main.DaoPublic.updateTotalProfitMatch(DaoPublic.java:6)
      at main.PresentAudience.getPresentAudience(PresentAudience.java:7)
      at main.match.getPresentAudience(match.java:7)
      at main.Principal.main(Principal.java:13)

    Espere, porque um método de atualizar renda da partida está sendo executado onde uma simples consulta deveria ser feita? Seu método tem que ser “Coeso”. Caso não haja outra opção, como última escolha, altere o nome do método para que o desenvolvedor que usar o método esteja ciente do que vai ocorrer. (Sei que o nome ficou feio, mas…).

    match.getPresentAudienceAndUpdateProfit();
  • Identação: “Deve ser a primeira regra do desenvolvedor”. O problema é que cada pessoa tem seu modo predileto, e às vezes não condiz com o padrão da empresa. Uma coisa é certa, não sei qual o padrão que você irá adotar, mas, por favor, sempre adote um. Abaixo dois códigos onde que, em sua leitura, fica clara a diferença de leitura:
            public int calculateScoredGoals()
        {int total = visitorTeam.getScoredTeam() +
    houseTeam.getScoredTeam();
                return total
            ;}
      public int calculateScoredGoals(){
        int total = visitorTeam.getScoredTeam() +
        houseTeam.getScoredTeam();
        return total;
      }

    Não importa qual a sua identação, apenas adote uma que facilite a leitura não só sua, mas de toda empresa.

  • Não devemos preservar referências retornadas por métodos que não terão utilizade depois. Vamos imaginar um método de atualização, que retorna a lista com os objetos que foram atualizados para caso queira utilizar:
      public void updateMatchDate() {
        //... Some code
        List expelledPlayers = DaoFactory.getDaoMatch().updatePlayers(expelledPlayers);
        //... More code, but none of them accessing expelledPlayers
      }

    Qual o motivo de ter criado a referência para a lista? Para que? Bastaria chamar o método e pronto. A lista será atualizada e você terá uma referência a um objeto alocado na memória que não será utilizado.

Esse foi o primeiro post sobre esse assunto, ainda falta muito pela frente!

Caso queria debater sobre essas idéias, podem postar que eu responderei. Gosto de aprender com a experiência de todos.