10 princípios do código de auto-documentação

Oi Hoje, quero compartilhar dicas sobre como escrever códigos perfeitos e compreensíveis, extraídos do livro de Peter Goodlif, “O ofício de um programador // a prática de escrever um bom código”.

Claro, seria bom ler este livro divertido para todos que escrevem o código, mas para aqueles que são especialmente preguiçosos, mas que querem parar de torturá-los menos e enganar seus colegas ( tenham consciência ), apresento 10 princípios de código de auto-documentação em cat :

1. Escreva um código simples com boa formatação


O formato da apresentação tem um enorme impacto na facilidade de compreensão do código. Uma representação razoável transmite a estrutura do código: funções, loops e instruções condicionais se tornam mais claras.

int fibonacci(int position) { if (position < 2) { return 1; } int previousButOne = 1; int previous = 1; int answer = 2; for (int n = 2; n < position; ++n) { previousButOne = previous; previous = answer; answer = previous + previousButOne; } return answer; } 

  • Verifique se a execução normal do seu código é óbvia. O tratamento de erros não deve prejudicar a sequência de execução normal. As construções condicionais if-then-else devem ter uma ordem de ramificação uniforme (por exemplo, sempre coloque a ramificação de código "regular" antes da ramificação de "tratamento de erros" ou vice-versa).
  • Evite muitos níveis de instruções aninhadas. Caso contrário, o código se torna complicado e requer explicações extensas. É geralmente aceito que cada função deve ter apenas um ponto de saída; isso é conhecido como código de entrada única, saída única (SESE, uma entrada, uma saída) . Mas geralmente essa restrição dificulta a leitura do código e aumenta o número de níveis de aninhamento. Eu prefiro a opção de função fibonacci acima do que a seguinte opção de estilo SESE :

     int fibonacci(int position) { int answer = 1; if (position >= 2) { int previousButOne = 1; int previous = 1; for (int n = 2; n < position; ++n) { previousButOne = previous; previous = answer; answer = previous + previousButOne; } } return answer; } 

    Eu recusaria esse aninhamento excessivo em favor da declaração de retorno adicional - tornou-se muito mais difícil ler a função. A conveniência de ocultar o retorno em algum lugar profundo da função é altamente duvidosa, mas os simples cálculos resumidos no início tornam a leitura muito fácil.
  • Cuidado com as otimizações de código que causam clareza no algoritmo subjacente. Otimize seu código apenas quando ficar claro que ele interfere no desempenho aceitável do programa. Ao otimizar, faça comentários claros sobre o funcionamento desta seção do código.

2. Escolha nomes significativos


Os nomes de todas as variáveis, tipos, arquivos e funções devem ser significativos e não enganosos. O nome deve descrever corretamente o que é. Se você não conseguir encontrar um nome significativo, existe uma dúvida sobre se você entende a operação do seu código.

O sistema de nomes deve ser consistente e não causar surpresas desagradáveis. Certifique-se de que a variável seja sempre usada apenas para a finalidade que o nome sugere.

Uma boa escolha de nomes é provavelmente a melhor maneira de evitar comentários desnecessários. Os nomes tornam possível aproximar o código da expressividade das linguagens naturais.

3. Divida o código em funções independentes


Como você divide o código em funções e que nomes você pode tornar o código compreensível ou completamente incompreensível.

  • Uma função, uma ação

Minimize os efeitos colaterais inesperados, por mais úteis que possam parecer. Eles exigirão documentação adicional.
Escreva funções curtas. Eles são mais fáceis de entender. Você pode navegar em um algoritmo complexo se ele estiver dividido em pequenos fragmentos com nomes significativos, mas isso não pode ser feito na massa informe do código.

4. Escolha nomes de tipo significativos


Na medida do possível, descreva as limitações ou o comportamento usando os recursos de idioma disponíveis. Por exemplo:

  • Ao determinar um valor que não será alterado, atribua um tipo constante a ele (use const em C).
  • Se a variável não aceitar valores negativos, use um tipo não assinado (se existir no idioma).
  • Use enumerações para descrever o conjunto de dados associado.
  • Escolha o tipo de variáveis ​​corretamente. No C / C ++, escreva size para variáveis ​​do tipo size_t e os resultados de operações aritméticas com ponteiros para variáveis ​​do tipo ptrdiff_t .

5. Use constantes nomeadas


Código como se (contador == 76) for desconcertante. Qual é o significado mágico de 76? Qual é o significado dessa verificação? A prática de números mágicos é cruel. Eles obscurecem o significado do código. É muito melhor escrever assim:

 const size_t bananas_per_cake = 76; ... if (count == bananas_per_cake) { //    } 

Se o código constante 76 é frequentemente encontrado no código (desculpe-me, bananas_per_cake ), uma vantagem adicional é alcançada: quando é necessário alterar o conteúdo de bananas na torta, basta modificar o código em um local, em vez de executar uma pesquisa / alteração global do número 76, que está repleto de erros.

Isso se aplica não apenas a números, mas também a seqüências constantes. Dê uma olhada em quaisquer literais no seu código, especialmente se elas ocorrerem repetidamente. Não seria melhor usar constantes nomeadas?

6. Destaque partes importantes do código


Tente destacar um código importante no contexto de material comum. No lugar certo, você deve chamar a atenção do leitor. Existem vários truques para isso. Por exemplo:

  • Coloque anúncios na sala de aula com sabedoria. Primeiro, as informações sobre objetos abertos devem ir, porque é o usuário da classe que precisa delas. Detalhes de implementação fechados devem ser colocados no final, pois são menos interessantes para a maioria dos leitores.
  • Se possível, oculte todas as informações não essenciais. Não deixe lixo desnecessário no espaço para nome global. O C ++ possui o idioma pimpl, que permite ocultar os detalhes da implementação da classe. (Meyers 97).
  • Não oculte código importante. Não escreva mais de uma declaração em uma linha e simplifique-a. A linguagem permite escrever operadores muito inventivos do loop for, nos quais toda a lógica se encaixa em uma linha com muitas vírgulas, mas esses operadores são difíceis de ler. Evite-os.
  • Limite a profundidade de aninhamento de instruções condicionais. Caso contrário, é difícil perceber o tratamento de casos realmente importantes por trás de um monte de ifs e parênteses.

7. Combine dados relacionados


Todas as informações relacionadas devem estar em um só lugar. Caso contrário, você fará o leitor não apenas pular pelos aros, mas também procurá-los com o ESP. A API para cada componente deve ser representada por um único arquivo. Se houver muitas informações interconectadas para serem apresentadas em um só lugar, vale a pena revisar a arquitetura do código.

Se possível, combine objetos usando construções de linguagem. Em C ++ e C #, você pode combinar elementos no mesmo espaço para nome . Em Java, o mecanismo de empacotamento é o mecanismo de pacotes. Constantes relacionadas podem ser definidas em uma enumeração.

8. Arquivos de etiqueta


Coloque um bloco de comentários no início do arquivo com uma descrição do conteúdo do arquivo e do projeto ao qual ele se relaciona. Isso não requer muito trabalho, mas é de grande benefício. Qualquer pessoa que precise acompanhar esse arquivo terá uma boa idéia do que está lidando. Esse título pode ter um significado especial: a maioria das empresas de software, por razões legais, exige que cada arquivo de origem tenha uma declaração de direitos autorais. Normalmente, os cabeçalhos dos arquivos são mais ou menos assim:

 /********************************************************* * File: Foo.java * Purpose: Foo class implementation * Notice: (c) 1066 Foo industries. All rights reserved. ********************************************************/ 

9. Manipule os erros corretamente


Coloque a manipulação de todos os erros no contexto mais adequado. Se houver um problema de leitura / gravação no disco, ele deverá ser processado no código que trata do acesso ao disco. Para lidar com esse erro, pode ser necessário gerar outro erro (como uma exceção "Não consigo carregar o arquivo"), passando-o para um nível superior. Isso significa que, em cada nível do programa, o erro deve ser uma descrição precisa do problema em seu contexto . Não faz sentido manipular o erro associado a uma falha de disco no código da interface do usuário.

O código de auto-documentação ajuda o leitor a entender onde ocorreu o erro, o que significa e quais são as consequências para o programa no momento.

10. Escreva comentários significativos


Portanto, tentamos evitar escrever comentários usando outros métodos indiretos de documentação de código. Mas depois que você fez todo o esforço para escrever um código compreensível, todo o resto precisa ser fornecido com comentários. Para facilitar a compreensão do código, ele precisa ser complementado com uma quantidade adequada de comentários. Qual?

Tente outros truques primeiro. Por exemplo, verifique se você pode tornar o código mais claro, alterando o nome ou criando uma função auxiliar e, assim, evite comentar.



Tenho certeza de que, após a introdução de vários desses princípios no hábito, você deixará um programador mais feliz. E você será esse programador feliz. Quando? Na hora de retornar ao trabalho em seu código, seis meses atrás.

Source: https://habr.com/ru/post/pt458264/


All Articles