Regla 0x2003h: Todas las funciones deben incluir documentación completa y estructurada
Funciones, contratos y modularizacion (0x20XX)
0x2003h: Todas las funciones deben incluir documentación completa y estructurada¶
Enunciado normativo¶
DEBE documentarse cada función con un bloque estructurado que declare su propósito, la precondición que exige, la postcondición que garantiza y el significado de cada parámetro y del valor de retorno. Las etiquetas mínimas son
@brief,@param,@pre,@posty@returns.
¿Por qué existe esta regla?¶
El problema¶
El nombre describe la intención, pero no el contrato. “¿Acepta NULL?”, “¿qué
devuelve si la lista está vacía?” son preguntas que el código no contesta. Un
contrato escrito es verificable: @pre lista lo que el llamador debe cumplir y
@post lo que la función garantiza, así la falla tiene un culpable.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Bug silencioso | El llamador pasa NULL porque nunca supo que estaba prohibido. |
| Fugas de memoria | Sin documentar la propiedad, nadie sabe quién debe liberar. |
| Revisión | El docente no puede evaluar si la función cumple lo que promete. |
Fundamento en el estándar y en la cátedra¶
La documentación estructurada viene de Doxygen, formato único que adopta la
cátedra con /** ... */. El estándar define los elementos del contrato: vida
útil (§6.2.4), parámetros (§6.9.1) y NULL (§7.19). Se documenta cuándo una
función puede retornar NULL, en línea con 0x3009h: Documentá explícitamente los casos en que una función puede retornar NULL.
Alcance y excepciones¶
Aplica a funciones públicas (declaradas en .h) y a las static con lógica no
trivial. La documentación del contrato vive preferentemente en el encabezado
.h, que es lo que consume el cliente.
Excepciones: no hace falta documentar con etiquetas las funciones
triviales de una línea (get/set) si su nombre y firma no dejan dudas, pero
sí se documenta todo parámetro que sea puntero, todo valor de retorno con
códigos de error y todo caso que retorne NULL.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Firma muda¶
int dividir(int a, int b);Por qué falla: no se sabe qué ocurre si b == 0, ni si el resultado se expresa
en unidades, ni si int alcanza. El llamador no tiene forma de cumplir un
contrato que no fue escrito.
❌ Contraejemplo 2 — Comentario que repite el nombre¶
/* Esta funcion suma. */
int suma(int a, int b)
{
return a + b;
}Por qué falla: decir que “suma” en una función llamada suma no aporta nada
(viola 0x0203h: Prescindí de comentarios obvios, redundantes o vacíos). El comentario no aclara desbordamiento, rango válido ni
el tipo de los operandos; es ruido, no documentación.
✅ Ejemplo conforme 1 — Contrato completo¶
/**
* @brief Calcula el cociente entero de dos números.
* @param a Dividendo. Debe ser distinto de INT_MIN si b == -1.
* @param b Divisor. Precondición: b != 0.
* @return El cociente truncado hacia cero.
* @pre b != 0.
* @post El retorno multiplicado por b no excede a a.
*/
int dividir(int a, int b)
{
return a / b;
}El bloque fija el dominio, la condición de error y la garantía. Cualquier llamador puede decidir si su uso es válido leyendo solo el encabezado.
✅ Ejemplo conforme 2 — Propiedad del recurso documentada¶
/**
* @brief Crea una copia dinámica de una cadena.
* @param origen Cadena terminada en '\0' o NULL.
* @return Nueva cadena en el heap, o NULL si origen es NULL o falla malloc.
* @post Si el retorno no es NULL, el llamador es dueño del bloque
* y debe liberarlo con free().
*/
char *duplicar_cadena(const char *origen)
{
if (origen == NULL) {
return NULL;
}
size_t n = strlen(origen) + 1;
char *copia = malloc(n);
if (copia != NULL) {
memcpy(copia, origen, n);
}
return copia;
}La etiqueta @post responde la pregunta que el código no puede responder solo:
quién libera. Complementa a 0x3006h: Documentá la propiedad de los recursos al utilizar punteros (documentar propiedad) y
0x3009h: Documentá explícitamente los casos en que una función puede retornar NULL (documentar retorno NULL).
⚠️ Casos límite¶
Cadenas vacías: documentar si
""es una entrada válida o un error.Parámetros
const: el contrato debe decir que la función no modifica la memoria apuntada (0x3007h: Los argumentos de tipo puntero deben ser const siempre que la función no los modifique).Funciones que nunca fallan: decirlo explícitamente en
@returnsen vez de omitir la etiqueta.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Función sin bloque /** ... */ precedente. |
gaff | gaff fix archivo.c | Inserta la plantilla de documentación faltante. |
| Doxygen | doxygen -g && doxygen | Advertencia de parámetro sin documentar. |
Checklist de autocontrol¶
¿Escribí el
@briefantes de la firma?¿Documenté cada
@paramy el@returns?¿Declaré la
@prey la@postde forma verificable?
Reglas relacionadas¶
0x2005h: Cada función debe tener una única responsabilidad (Principio de Responsabilidad Única) — el contrato hace explícita la única responsabilidad.
0x3006h: Documentá la propiedad de los recursos al utilizar punteros — la propiedad del recurso se declara en el contrato.
0x3009h: Documentá explícitamente los casos en que una función puede retornar NULL — el retorno
NULLse documenta como caso explícito.0x0201h: Escribí comentarios que expliquen el ‘porqué’, no el ‘qué’ — el comentario explica el porqué, no el qué evidente.