Abaixo estão algumas das minhas preferências e suas razões.
1. Endentação e aspecto geral
- Endentar com 4 espaços;
- Limite de 80 caracteres por linha; e
- Tabulações proibidas.
Para mim 2 espaços é pouco e 8 espaços é muito na endentação. Quatro espaços parecem ser o meio termo adequado.
Linhas longas atrapalham a leitura do código: eu desejo um código tão legível quanto livros e jornais. Além disso, o limite de 80 caracteres permite abrir arquivos lado a lado sem necessitar de rolagem horizontal e ainda facilita revisão do código anterior e atual abertos lado a lado.
Com respeito a proibir tabulações, existe o argumento que tabulações são mais flexíveis, pois o programador pode escolher o tamanho de sua preferência. O argumento é válido, porém somente até se misturarem as tabulações e os espaços: nesse instante, a única pessoa que vê alinhado é o próprio autor do código; e todo o resto do mundo vê uma bagunça desalinhada. Usar apenas um tipo de espaço em branco elimina esse problema.
2. Alinhamento das chaves
Abertura de chaves na linha abaixo.
Isso ajuda a identificar onde acontece a abertura do bloco. Chave abrindo na própria linha permite determinar o início do bloco sem precisar procurar por ela no fim de alguma linha.
unsigned long int funcao_h( unsigned long int parametro1, unsigned long int parametro2, unsigned long int parametro3) { return parametro1 + parametro2 - parametro3; }
Compare abaixo a mesma função abrindo as chaves na linha. Não é tão óbvio como no caso acima.
unsigned long int funcao_h( unsigned long int parametro1, unsigned long int parametro2, unsigned long int parametro3) { return parametro1 + parametro2 - parametro3; }
Abrindo as chaves na linha abaixo, fica óbvio onde os parâmetros terminam e onde inicia o corpo da função. O mesmo acontece em blocos de controle como if, for, etc.
Mesmo se eliminarmos qualquer informação sobre os caracteres, como é mostrado abaixo, facilmente identificamos a lista de parâmetros e o início do corpo da função.
XXXXXXXX XXXX XXX XXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX X XXXXXX XXXXXXXXXX X XXXXXXXXXX X XXXXXXXXXXX X XXXXXXXX XXXX XXX XXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX XXXXXXXX XXXX XXX XXXXXXXXXXX X XXXXXX XXXXXXXXXX X XXXXXXXXXX X XXXXXXXXXXX X
A maior parte do tempo que passamos programando é utilizada, na verdade, lendo o código. Esta pequena escolha ajuda a encontrar a parte que importa no momento.
3. Parâmetros de funções
A lista de parâmetros de funções e a lista de argumentos de chamada de uma função devem estar todos em uma linha ou cada um em sua linha.
Dessa forma, a lista de parâmetros (ou argumentos) realmente se parece com uma lista. É fácil de contar os parâmetros e é fácil de encontrá-los.
Nesse ponto, há três possibilidades avaliadas na ordem seguinte:
- Protótipo todo na mesma linha;
- Lista de parâmetros toda na segunda linha; e
- Lista de parâmetros com um parâmetro por linha.
Exemplos abaixo:
/* Protótipo inteiro cabe em uma linha: */ int funcao_f(int parametro1, int parametro2) { return parametro1 + parametro2; } /* * Protótipo não cabe em uma única linha, porém * a lista de parâmetros cabe inteira na segunda linha: */ unsigned long int funcao_g( unsigned long int parametro1, unsigned long int parametro2) { return parametro1 + parametro2; } /* * Parâmetros não cabem todos na segunda linha, então * coloca-se um parâmetro por linha: */ unsigned long int funcao_h( unsigned long int parametro1, unsigned long int parametro2, unsigned long int parametro3) { return parametro1 + parametro2 - parametro3; }
4. Comentários
- Usar o mínimo de comentários possível; e
- Comentários multilinha devem ter um caractere inicial de alinhamento.
Comentários não são analisados pelo compilador e não precisam fazer sentido para o código funcionar. Por isso não são atualizados em conjunto com o código. Consequentemente, com o passar do tempo a semântica (o significado) do código se desvia dos comentários presentes.
Na maioria dos casos é possível fazer um código autoexplicativo através da refatoração e da melhoria de nomes de funções e nomes de variáveis.
/* executa_loop1 */ void executa_loop1(void) { // Lê o valor do sinal do sensor int16_t val = ADC0; // Calcula tensão do sensor em volts // a partir do offset e do ganho float valf = (val - 512) * (24.0 / 512.0); // Escreve na serial Serial_EscreveFloat(valf); } /* ---------------------------------------- */ /* executa_loop2 */ #define SENSOR_OFFSET 512 #define SENSOR_GANHO (24.0 / 512.0) float TensaoSensor_Volts(void); void executa_loop2(void) { Serial_EscreveFloat(TensaoSensor_Volts()); } int16_t SinalSensor_ADC(void) { return ADC0; } float TensaoSensor_Volts(void) { return (SinalSensor_ADC() - SENSOR_OFFSET) * SENSOR_GANHO; }
- O primeiro comentário é removido com uma chamada da função SinalSensor_ADC().
- O segundo comentário é removido com uma chamada da função TensaoSensor_Volts() e pelo uso das constantes SENSOR_OFFSET e SENSOR_GANHO.
- O terceiro comentário é redundante e desnecessário.
Qual versão da função executa_loopX() você prefere ler?
Alguns comentários, por sua vez, são impossíveis de serem transformados em código. Por exemplo, o comentário a seguir mostra um diagrama de um LCD 16×2 que mostra a tensão elétrica e a corrente medida.
/* * 0123456789012345 * 0 Tensão XX,XX V 0 * 1 Corrente Y,YYY A 1 * 0123456789012345 */
Sobre o caractere inicial dos comentários multilinha, alguns editores e formatadores eliminam espaços em branco iniciais, alinhando o primeiro caractere não branco de cada linha.
Dessa forma, todo o esforço de alinhamento abaixo é perdido em um piscar de olhos:
/* 0123456789012345 0 Display 16x2 0 1 Linha 2 1 0123456789012345 */
O comentário acima acaba por se transformar em alguma dessas atrocidades:
/* 0123456789012345 0 Display 16x2 0 1 Linha 2 1 0123456789012345 */ /* 0123456789012345 0 Display 16x2 0 1 Linha 2 1 0123456789012345 */
Colocando os asteriscos de alinhamento o problema deixa de existir.
/* * 0123456789012345 * 0 Display 16x2 0 * 1 Linha 2 1 * 0123456789012345 */
Considerações finais
Essas são as algumas das minhas preferências, ao menos as que eu acho mais importantes.
Todas essas já mudaram algumas vezes desde que comecei a programar e, com a experiência, são as que me parecem mais naturais e que facilitam a leitura do código.
Além disso, a maioria delas (exceto as sobre comentários), não me dão trabalho algum, pois utilizo um formatador automático. Assim posso focar no código em si e em como melhorá-lo para eliminar comentários.