A necessidade de comentários é inversamente proporcional ao nível de abstração do código.
Por exemplo, a linguagem de montagem é, para fins mais práticos, ininteligível sem comentários. Aqui está um trecho de um pequeno programa que calcula e imprime os termos da série de Fibonacci :
main:
; initializes the two numbers and the counter. Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
mov ax,'00' ; initialize to all ASCII zeroes
mov di,counter ; including the counter
mov cx,digits+cntDigits/2 ; two bytes at a time
cld ; initialize from low to high memory
rep stosw ; write the data
inc ax ; make sure ASCII zero is in al
mov [num1 + digits - 1],al ; last digit is one
mov [num2 + digits - 1],al ;
mov [counter + cntDigits - 1],al
jmp .bottom ; done with initialization, so begin
.top
; add num1 to num2
mov di,num1+digits-1
mov si,num2+digits-1
mov cx,digits ;
call AddNumbers ; num2 += num1
mov bp,num2 ;
call PrintLine ;
dec dword [term] ; decrement loop counter
jz .done ;
; add num2 to num1
mov di,num2+digits-1
mov si,num1+digits-1
mov cx,digits ;
call AddNumbers ; num1 += num2
.bottom
mov bp,num1 ;
call PrintLine ;
dec dword [term] ; decrement loop counter
jnz .top ;
.done
call CRLF ; finish off with CRLF
mov ax,4c00h ; terminate
int 21h ;
Mesmo com comentários, pode ser bastante complicado para grok.
Exemplo moderno: Regexes são frequentemente construções de abstração muito baixas (letras minúsculas, número 0, 1, 2, novas linhas, etc). Eles provavelmente precisam de comentários na forma de amostras (Bob Martin, IIRC, reconhece isso). Aqui está uma regex que (eu acho) deve corresponder a URLs HTTP (S) e FTP:
^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|m
+il|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.
+\,\;\?\'\\+&%\$#\=~_\-]+))*$
À medida que as linguagens progridem na hierarquia de abstração, o programador pode usar abstrações evocativas (nome da variável, nomes de funções, nomes de classes, nomes de módulos, interfaces, retornos de chamada, etc) para fornecer documentação incorporada. Negligenciar tirar proveito disso, e usar comentários para escrever sobre isso é preguiçoso, um desserviço e desrespeito ao mantenedor.
Estou pensando em Receitas Numéricas em C traduzidas na maior parte das vezes em Receitas Numéricas em C ++ , as quais comecei como Receitas Numéricas FORTAN), com todas as variáveis a
, aa
, b
, c
, cc
, etc. mantidas em cada versão. Os algoritmos podem estar corretos, mas não aproveitaram as abstrações fornecidas pelas linguagens. E eles me dispensam. Exemplo de um artigo do Dr. Dobbs - Fast Fourier Transform :
void four1(double* data, unsigned long nn)
{
unsigned long n, mmax, m, j, istep, i;
double wtemp, wr, wpr, wpi, wi, theta;
double tempr, tempi;
// reverse-binary reindexing
n = nn<<1;
j=1;
for (i=1; i<n; i+=2) {
if (j>i) {
swap(data[j-1], data[i-1]);
swap(data[j], data[i]);
}
m = nn;
while (m>=2 && j>m) {
j -= m;
m >>= 1;
}
j += m;
};
// here begins the Danielson-Lanczos section
mmax=2;
while (n>mmax) {
istep = mmax<<1;
theta = -(2*M_PI/mmax);
wtemp = sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
for (m=1; m < mmax; m += 2) {
for (i=m; i <= n; i += istep) {
j=i+mmax;
tempr = wr*data[j-1] - wi*data[j];
tempi = wr * data[j] + wi*data[j-1];
data[j-1] = data[i-1] - tempr;
data[j] = data[i] - tempi;
data[i-1] += tempr;
data[i] += tempi;
}
wtemp=wr;
wr += wr*wpr - wi*wpi;
wi += wi*wpr + wtemp*wpi;
}
mmax=istep;
}
}
Como um caso especial sobre abstração, toda linguagem tem expressões idiomáticas / trechos de códigos canônicos para certas tarefas comuns (excluindo uma lista vinculada dinâmica em C), e independentemente de como elas se pareçam, elas não devem ser documentadas. Os programadores devem aprender esses idiomas, pois eles são extraoficialmente parte da linguagem.
Assim, o take away: Código não-idiomático construído a partir de blocos de construção de baixo nível que não podem ser evitados, precisa de comentários. E isso é necessário WAAAAY menos do que acontece.