Código Limpo
Uncle Bob nos trás princípios necessários para um código limpo e estimula a prática desses para desenvolver a habilidade de ser um artesão de códigos limpos.
Princípio dos 5S:
-
Seiri - Organização (pense em "Ordenar") - Saber onde estão as coisas;
-
Seiton - Arrumação (pense em "Sistematizar") - Um pedaço de código deve estar aonde você espera encontra-lo;
-
Seiso - Limpeza (pensem em "Polir") - Refatorar e eliminar comentários;
-
Seiketsu - Padronização (pensem em "Padrões") - Mander padrões entre o time de desenvolvimento;
-
Shutsuke - Disciplina (pensem em "Autodisciplina");
Precisamos sempre manter e melhorar nossos códigos, deixando-os mais limpos. Muitas vezes, fazemos o código funcionar e consideramos ele pronto.
Parte I - Princípios, Padrões e Práticas para criar um código limpo
1 - Código Limpo
- Os códigos representam os detalhes dos requisitos. E especificá-los detalhadamente de modo que a máquina possa executá-los é programar.
- Códigos ruins podem acabar com empresas. Custa muito manter um código ruim.
- A se deixe corromper pelos prazos de gerentes, eles defendem os prazos e você tem que defender um código limpo como entrega. Um código desorganizado só atrasará as entregas.
- Escrever um código limpo é como pintar um quadro. A maioria de nós sabe distinguir um bem pintado de um mal pintado. Mas nem todos sabem pintar bem.
- O código limpo faz bem apenas uma coisa, requer bastante atenção aos detalhes e é simples e direto. Ele é legível, inteligível e toda informação é expressa no código em si. Um código sem testes, não está limpo.
- Regra de escoteiro: "Deixe a área do acampamento mais limpa do que como você a encontrou". Refatorar sempre.
2 - Nomes Significativos
- Use nomes significativos que revelam o propósito do código.
- Use nomes passíveis de busca.
3 - Funções
- Não devem receber muitos parâmetros.
- Não devem receber parâmetros lógicos porque será necessário entrar na função e entender o uso.
4 - Comentários
- "Não insira comentários num código ruim, reescreva-o"
- Comentários antigos são prejudiciais pois disseminam mentiras.
__5 - Formatação __
- Devemos seguir alinhamentos e padrões de espaçamento.
- Não devemos criar muitas camadas de indentação.
- Devemos seguir uma ordem lógica das declarações e chamadas de funções.
6 - Objetos e estruturas de dados
- "Objetos devem esconder seus dados e expor suas operações" - Lei de Demeter
7 - Tratamento de Erro
- Use exceções em vez de retornar códigos de erros
- Crie mensagens de erro informativas e as passe juntamente com as exceções.
8 - Limites
- Quando usamos códigos que estão fora de controle, deve-se dar uma atenção especial ao nosso investimento e garantir que uma mudança futura não seja muito custosa. Usar um único ponto de contato com libs externas é uma boa saída para isso.
9 - Testes de Unidade Os testes são tão importantes para a saúde de um projeto quanto o código de produção.
TDD
- Primeira Lei - Não se deve escrever o código de produção até criar um teste de unidade de falhas;
- Segunda Lei - Não se deve escrever mais de um teste de unidade do que o necessário para falhar, e não compilar é falhar;
- Terceira Lei - Não se deve escrever mais códigos de produção do que o necessário para aplicar o teste de falha atual.
Testes precisam ser limpos e seguir as regras F.I.R.S.T:
- Fast - Devem ser rápidos;
- Independent - Não devem depender uns dos outros;
- Repeatable - Deve-se poder repetir os testes em qualquer ambiente;
- Self-Validating - Os testes devem ter uma saída booleana;
- Timely - Os testes precisam ser escritos em tempo hábil.
10 - Classes
Classes devem ser pequenas e seguir a seguinte ordem:
- Lista de variáveis (Públicas, Estáticas, Constantes, Privadas).
- Métodos. Devemos aplicar o Principio da Injeção de Dependencia para que nossas classes não dependam de detalhes concretos mas sim de abstrações.
11 - Sistemas
- "Complexidade mata. Ela suga a vida dos desenvolvedores, dificulta o planejamento, a construção e o teste dos produtos" - Ray Ozzie, CTO, Microsoft Corporation
- Sistemas são como cidades que precisam progredir em níveis apropriados de abstração e modularidade os quais possibilitaram que indivíduos e os "componentes" pudessem trabalhar de forma eficiente, mesmo sem ter noção da coisa como um todo.
- Os sistemas de software devem separar o processo de inicialização - a criação dos objetos do aplicativo e a "conexão" entre as dependências - da lógica em tempo de execução que vem após a inicialização.
- Uma arquitetura pode crescer gradualmente SE mantivermos uma separação devida de preocupações.
- Uma arquitetura invasiva afeta a agilidade e sobrepõe a lógica do domínio que, quando ofuscada, perde-se qualidade porque os bugs se escondem mais facilmente e dificulta a implementação.
12 - Emergência Quatro regras do Projeto Simples de Kent Beck:
- Efetuar todos os testes;
- Sem duplicação de código;
- Expressar o propósito do programador;
- Minimizar o número de classes e métodos;
A maioria dos custos de um projeto de software está na manutenção em longo prazo.
Quanto mais claro o autor tornar seu código, menos tempo outras pessoas terão de gastar para compreendê-lo.
13 - Concorrência
- O desacoplamento entre o que e quanto costuma ter grande impacto na estrutura do sistema.
- Mantenha seu código voltado para a concorrência separado do resto do código
- Leve a série o encapsulamento de dados; limite severamente o acesso a quaisquer dados que possam ser compartilhados.
- Tente dividir os dados em subsistemas independentes que possam ser manipulados por threads independentes, possivelmente em processadores diferentes.
Parte II - Estudos de casos de complexidade cadas vez maior
14 - Refinamento Sucessivo
- O autor mostra um estudo de caso aonde ele pegou uma aplicação e foi refatorando até chegar em um código mais limpo.
- Não é profissional apenas fazer com que o programa funcione. Precisamos refinar e limpar nosso código cada vez mais.
15 - Características Internas do JUnit
- O autor mostra partes do código do framework JUnit e propõe melhorias.
- Regra de Escoteiro: Devemos deixar o código um pouco mais limpo do que como o encontramos.
16 - Refatorando o SerialDate
- O autor mostra uma classe chamada SerialDate dentro da biblioteca JCommon e propõe melhorias.
Parte III - Lista de Heuristicas e "Odores"
17 - Odores e Heurísticas
- Colocar códigos em comentários é uma abominação. Talvez o código pudesse ser mais claro para não precisar do comentário;
- Nomes ruins (variável, método, classe);
- Construir um projeto deve ser uma operação simples e única (EX: yarn build);
- Código morto (código "desligado") ou desnecessário;
- Distância da margem (aumento da complexidade);
- As funções devem ter um número pequeno de parâmetros;
- Os parâmetros de saída são inesperados;
- Os parâmetros booleanos são confusos;
- Não tenha receio de excluir funções que não são utilizadas;
- DRY (Don't repeat yourself) - Não duplique código. Use padrão de Template Method e Strategy. A orientação ao objeto e a programação estruturada são táticas para organizar módulos e eliminar a duplicação;
- As classes base não deveriam enxergar nada em suas derivadas;
- Limite as informações para ajudar a manter um baixo acoplamento;
- Mantenha seus arquivos-fontes limpos, bem organizados e livres de entulhos;
- De maneira geral, é melhor ter muitas funções do que passar um código por parâmetro para selecionar o comportamento;
- Queremos que o código seja o mais expressivo possível;
- Use variáveis descritivas, se você não consegue entender o que uma função faz e precisa olhar a documentação é melhor refatorar;
- Há uma diferença entre entender como o código funciona e saber se o algoritmo fará o trabalho como deve. Não ter certeza se o algoritmo é apropriado é normal. Não ter certeza do que seu código faz é pura preguiça;
- A equipe não deve precisar de um documento que descreva suas convenções porque seus códigos fornecem os exemplos;
- Responsabilidades diferentes (quebra do SRP);
- Linha em branco (sem padrão);
- Números mágicos (que poderiam ser constantes);
- Tratamento de exceções inadequado (return -1, try/catch desnecessário);
- else desnecessário (inverter o if);
- Variável não tipada (em linguagens onde a tipagem é obrigatória);
- Variáveis declaradas juntas;
- Variáveis declaradas muito antes da sua utilização (eventualmente grupos de variáveis);
Não se cria um código limpo seguindo uma série de regras. Você não se tornará um especialista na arte de softwares através de uma lista de heurísticas. Profissionalismo e habilidade num ofício vêm com valores que requerem disciplina.
PS: Lembre-se que a performance pode ser afetada com o uso do clean code: