Minhas Preferências de Formatação

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.

Autor: Djones Boni

Engenheiro Eletricista.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *