quarta-feira, 8 de dezembro de 2010

Clean Code

O primeiro objetivo dos desenvolvedores quando criam uma funcionalidade é fazê-la funcionar. Tudo bem, está funcionando, mas e o código, como esta? Será que o código que faz tudo funcionar está legível, fácil de ser entendido, ou seja, será que está limpo?  É preciso preocupar-se com o código, garantir que  está legível e bem escrito, pois somente o próprio código pode dizer de forma confiável o que o software realmente faz.

Mas afinal, o que é código limpo?
Em suma um código limpo deve ser:
·         Elegante (distinto)
·         Eficiente
·         Legível
·         Simples
·         Direto
·         Único, sem duplicidades
·         Bem escrito
·         Deve ser escrito cuidadosamente
·         E deve sempre possuir UMA responsabilidade

O código é importante e deve agregar valor ao negócio. Somente um código limpo pode oferecer a qualidade e entendimento que esperamos quando abrimos uma classe. Portanto é necessário que seu código seja limpo e legível para que qualquer um que encontrá-lo possa facilmente entendê-lo evitando perda de tempo e facilitando o trabalho de todos.

Nomes significativos
Vamos começar pelos nomes. Escolhemos nomes para tudo, desde variáveis até métodos e classes, por causa disso devemos escolhê-los bem.
Os nomes devem nos dizer três coisas: Porque existem, o que fazem e como são usados. Devem revelar sua intenção e ser significativos, devem dizer o que estão fazendo e o que significam.
Faça distinções significativas, use nomes diferentes dentro de um mesmo escopo. Nomes como a1, a2, a3 são o oposto de nomes que demonstram intenção. São confusos e não informam nada. Evite também usar abreviações ou trocadilhos, escreva exatamente o que você quer dizer, o nome deve ser auto-explicativo. É comprovado que um desenvolvedor passa muito mais tempo lendo código do que escrevendo, por isso não se preocupe em economizar caracteres ao escolher um nome, o fato de um ser claro e objetivo poupará muito mais tempo do futuro do que os caracteres a menos que você digitar ao escolher um nome curto e ruim.
Métodos e funções
O que os tornam métodos e funções fáceis de se ler e entender? A primeira regra dos métodos é que eles devem ser pequenos, a segunda é que eles devem ser menores ainda.
Métodos devem conter no máximo 20 linhas e seu nível de identação não pode ser maior que dois. Quanto ao conteúdo, um método deve ter somente UMA responsabilidade. É difícil dizer o que é “uma responsabilidade”, mas uma maneira de descobrir se um método está fazendo mais de uma coisa, é tentar extrair uma parte dele em outro método. Se for possível, realmente o primeiro método tinha mais de uma responsabilidade.
Evite passar muitos parâmetros para um método, porque isso pode causar confusão além de dificultar a escrita de testes unitários, pois assegurar que todas as combinações de parâmetros diferentes funcionarão é bem mais trabalhoso. Passar parâmetros booleanos (verdadeiro ou falso) também não é uma boa prática, além complicar a assinatura do método, claramente a função tem mais de uma responsabilidade. Outro detalhe importante  que devemos nos preocupar são os efeitos colaterais, esses efeitos são mentiras. Seu método diz que fará uma coisa, mas faz outras “escondidas”.

Observe o método abaixo:
public boolean checkPassword(String username, String password) {
String passwordStatus = cryptographer.decrypt(password);
if(passwordStatus.equals(“OK”)) {
     Session.initialize();
     return true;
}
return false;
}
O método checkPassword tem o objetivo de verificar a validade da senha, mas além disso está abrindo um sessão, o que não está coerente com a finalidade do método. Não se esqueça, seu método deve sempre ter somente um objetivo.
Comentário
Comentários podem ser úteis se colocados nos lugares certos, mas também podem ser mentirosos e trazer desinformação. Na verdade, o melhor comentário é aquele que não precisa ser escrito. Podemos usá-los de forma benéfica para informar o leitor de alguma conseqüência ou fornecer a intenção de uma decisão tomada, mas um dos principais motivos para você escrever um comentário é porque o código está difícil de ser entendido. Você acha que o código ficou meio confuso e acha melhor adicionar um comentário? Não, você acha melhor refatorar
Quando você pensa em adicionar um comentário em seu código, é um forte indício que ele não está muito bom, não está claro
Não use comentários quando você pode usar métodos ou variáveis,explique-se no código, lembre-se que apenas o código pode dizer o que ele realmente faz
Formatação
A formatação do código é importante, pois se trata da forma de comunicação do desenvolvedor, um código todo bagunçado e sem formatação dificulta o entendimento de quem o está lendo
A legibilidade do código terá profundo efeito sobre todas as mudanças que serão feitas, seu estilo e disciplina sobrevive sobre estas mudanças.
Procure escrever  classes com no máximo 500 linhas, classes menores são mais fáceis de se entender. Já para as linhas de código, tente estabelecer um limite de caracteres por linha. Uma boa identação ajuda a visualizar melhor todo o escopo e facilita a identificação de situações e regras relevantes. Tente manter conceitos relacionados mais próximos verticalmente, para criar um fluxo na leitura do código. Use espaços entre operadores, parâmetros e vírgulas. Evite deixar o código todo grudado.
Tratamento de erro
Quando estamos programando devemos tratar os possíveis erros que nossa aplicação poderá lançar, as coisas podem dar errado e temos que estar certos que nosso código fará o que deve fazer
Prefira lançar uma exception ao invés de retornar um código de erro, estes retornos desorganizam a chamada do método e pode-se facilmente esquecer de verificá-los
Defina o fluxo do método separando as regras de negócio de erros ou outras situações. Para seus erros crie mensagens informativas, mencionando a operação que falhou e o tipo de falha.

Testes unitários
Há alguns anos atrás, pouco se ouvia falar de TDD (Test Driven Development). Para muitos TDD erá apenas trechos de código que garantia que o programa “funcionasse”. Mas essa idéia amadureceu bastante entre todos nós, hoje em dia programar com TDD é um conceito de alto nível, por isso, todos os testes que criamos devem ser escritos com código limpo.
Queremos dizer muito em nossos testes, por isso que eles devem ser legíveis, claros e simples de entender. Um teste com código ruim e difícil de entender é muito mais trabalhoso para se dar manutenção. Cada teste deve possuir apenas um conceito para facilitar seu entendimento, também deve sofrer alterações da mesma maneira que o código que está testando, tudo isso para manter a flexibilidade e a manutenabilidade do código.

Lembre-se que o código do teste é tão importante quanto o código da produção.
Todos sabem que o TDD nos manda escrever o teste antes do código de produção em si, considere essas três regras do TDD:
1.     Você não pode escrever o código até que você tenha criado um teste que falhe.
2.     Você não pode escrever mais testes do que seja suficiente para falhar.
3.     Você não pode escrever mais código do que o suficiente para passar o teste que está falhando.
Se você conseguir seguir essas regras ao desenvolver, você estará praticando TDD corretamente.

Classes
Para começarmos a falar de classes limpas podemos partir da organização das classes. De acordo com os padrões Java, uma classe deve começar com uma lista de variáveis de preferência nesta ordem:
1.     variáveis publicas e estáticas
2.     variáveis privadas e estáticas
3.     variáveis privadas
Depois das variáveis vêm os métodos públicos. Os métodos privados aparecem depois de suas chamadas. Assim como os métodos, as classes também devem ser pequenas. Ninguém gosta de encontrar classes gigantes onde é difícil até mesmo de se encontrar dentro delas. Mas a pergunta é: O quão pequenas elas devem ser?
O nome da classe deve representar a sua responsabilidade. Tentar fazer uma breve descrição da classe, explicando o que ela faz pode ajudar a escolher o nome certo. Esta descrição deve ter no máximo 25 palavras e não  conter palavras como “mas”, “e”, ”ou”, “se”, pois expressam mais de uma coisa mostrando que há mais de uma responsabilidade.
Outra maneira de descobrir o tamanho ideal da classe é analisarmos suas responsabilidades. O Princípio da Única Responsabilidade (Single Responsibility Principle) diz que uma classe deve ter uma, e apenas uma razão para mudar. Quando uma classe possui mais que um motivo para ser alterada é porque provavelmente ela esta fazendo mais coisas do que devia, ou seja, ela têm mais de um objetivo. O princípio nos dá definições de responsabilidade e uma diretriz para o tamanho de uma classe. Tentar identificar responsabilidades nos ajuda a melhorar nosso código e criar melhores abstrações.
Para concluir, queremos nosso sistema com pequenas classes, cada uma com uma única responsabilidade, tendo uma razão para mudar e colaborando com outras para alcançar o comportamento desejado do sistema.

Design emergente

Design emergente é um design que nunca é o final, sempre está em evolução. Para conseguirmos criar boas estruturas de código tornando mais fácil de aplicar princípios como SRP e DIP, e assim facilitar a criação de um de bom design de software, Kent Beck estipulou 4 regras para um design simples (Simple Design):

1. Rode todos os testes

Fazer um sistema testável nos obriga e usar boas práticas como classes e métodos pequenos de apenas uma responsabilidade.
Quanto mais testes fazemos mais e melhores maneiras e princípios seguiremos para evitar o acoplamento de nosso código. Lembre-se, um sistema testável possui sempre todos os seus testes passando. Um sistema que não é testável, não é verificável e assim não pode ser entregue para produção.

2. Remova duplicação

Duplicação é o primeiro inimigo de um bom design, ela representa trabalho e riscos adicionais além de uma maior e desnecessária complexidade. Ela se manifesta em linhas de códigos iguais ou parecidas além de aparecerem nas implementações. Usar padrões como Template Method é uma saída para remover duplicações mais complexas.

3. Expresse sua intenção

Escrever código que nós entendemos é fácil pois estamos concentrados e ligados no problema que estamos tentando resolver. Mas o próximo que pegar o código para fazer manutenção, não estará tão ligado ao problema como você estava quando implementou a solução.
Expressar-se bem no código pode trazer grandes benefícios para o desenvolvimento de um sistema. Além de poupar tempo de quem o mantém. Você pode expressar-se bem em seu código escolhendo bons nomes, deixando métodos e classes pequenas, separando responsabilidades. Lembre-se que você pode sem o próximo a ler este código.

4. Diminua o número de classes e métodos

Sempre que possível, nosso objetivo é manter sistemas pequenos enquanto ao mesmo tempo se mantém  métodos e classes pequenas.
Princípios e boas práticas não substituem a experiência, mas a partir delas pode se dar o primeiro passo para desenvolver um bom design.

Conclusão

Ao longo do tempo, comecei a perceber a diferença que estas técnicas fazem no meu dia-a-dia como desenvolvedor, pois, elas ajudam a pensar de uma forma mais  clara e objetiva sobre o código que escrevo. Pequenas coisas podem fazem grandes diferenças.
Tendo em mente estas observações, passei a escrever códigos mais legíveis, de fácil manutenção e mais eficientes. Sempre que vejo um trecho de código que não está muito legível, sinto-me na obrigação de refazê-lo, tornando-o legível limpo e eficiente.


Nenhum comentário:

Postar um comentário