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.