¿Es mejor documentar funciones en el archivo de encabezado o en el archivo fuente?

86

En los lenguajes que distinguen entre un archivo "fuente" y "encabezado" (principalmente C y C ++), es mejor documentar las funciones en el archivo encabezado:

(robado de CCAN )

/**
 * time_now - return the current time
 *
 * Example:
 *  printf("Now is %lu seconds since epoch\n", (long)time_now().tv_sec);
 */
struct timeval time_now(void);

o en el archivo fuente?

(robado de PostgreSQL)

/*
 * Convert a UTF-8 character to a Unicode code point.
 * This is a one-character version of pg_utf2wchar_with_len.
 *
 * No error checks here, c must point to a long-enough string.
 */
pg_wchar
utf8_to_unicode(const unsigned char *c)
{
...

Tenga en cuenta que algunas cosas se definen solo en el encabezado, como estructuras, macros y static inlinefunciones. Solo estoy hablando de cosas que se declaran en un archivo de encabezado y se definen en un archivo fuente.

Aquí hay algunos argumentos en los que puedo pensar. Me estoy inclinando hacia la documentación en el archivo fuente, por lo que mis argumentos "Pro-header" pueden ser algo débiles.

Pro-encabezado:

  • El usuario no necesita el código fuente para ver la documentación.
    • La fuente puede ser inconveniente, o incluso imposible de adquirir.
    • Esto mantiene la interfaz y la implementación más separadas.

Pro-fuente:

  • Hace que el encabezado sea mucho más corto, lo que le da al lector una vista panorámica del módulo en su conjunto.
  • Empareja la documentación de una función con su implementación, lo que facilita ver que una función hace lo que dice que hace.

Al responder, tenga cuidado con los argumentos basados ​​en lo que pueden hacer las herramientas y los "IDE modernos". Ejemplos:

  • Pro-header: el plegado de código puede ayudar a hacer que los encabezados comentados sean más navegables al ocultar los comentarios.
  • Pro-fuente: cscope 's Find this global definitionfunción le lleva al archivo de origen (donde la definición es) más que el archivo de cabecera (donde la declaración es).

No digo que no haga tales argumentos, pero tenga en cuenta que no todos están tan cómodos con las herramientas que usa como usted.

Joey Adams
fuente
La misma pregunta puede aplicarse a Pascal / Delphi, donde no tenemos archivos fuente y de encabezado, sino secciones de interfaz e implementación.
Jan Doggen
1
Consulte también stackoverflow.com/questions/355619/…
cp.engr el

Respuestas:

96

Mi vista...

  • Documente cómo usar la función en el archivo de encabezado, o más exactamente cerca de la declaración.

  • Documente cómo funciona la función (si no es obvio por el código) en el archivo fuente, o más exactamente, cerca de la definición.

Para el aspecto de ojo de pájaro en el encabezado, no necesariamente necesita la documentación que se cierra; puede documentar grupos de declaraciones a la vez.

En términos generales, la persona que llama debe estar interesada en los errores y excepciones (aunque solo sea para poder traducirlos a medida que se propagan a través de las capas de abstracción), por lo que estos deben documentarse cerca de las declaraciones relevantes.

Steve314
fuente
13
+1: es decir, documentar la interfaz en el encabezado. Los detalles sangrientos del cómo y por qué en la fuente.
rapid_now
2
Para los encabezados de la biblioteca donde no hay una fuente disponible, puede agregar condiciones previas y posteriores, etc. para ayudar con las pruebas. Además, agregue el rendimiento O (n) si tiene sentido, para que los usuarios de la biblioteca puedan elegir sabiamente.
Patrick Hughes el
Naturalmente, a veces la declaración y la definición son lo mismo.
Deduplicador
@Dupuplicator: cuando las mismas reglas aún conducen a lo correcto, incluso en el caso especial, ¿por qué hacer eco de esas reglas para cada caso especial? ¿Seguramente un deduplicador no debería querer eso?
Steve314
1
@Dupuplicator: por supuesto, es un razonamiento masivo para no seguir su consejo, pero me quedo con él.
Steve314
34

Si va a utilizar una herramienta como Doxygen (tenga en cuenta en el primer ejemplo que realmente parece un comentario de Doxygen porque comienza con /**), entonces realmente no importa: Doxygen mirará a través de su encabezado y archivos fuente y encontrará Todos los comentarios para generar la documentación.

Sin embargo, estaría más inclinado a poner los comentarios de la documentación en los encabezados, donde están las declaraciones. Sus clientes se ocuparán de los encabezados para interactuar con su software, los encabezados son lo que incluirán en sus propios archivos fuente y allí es donde buscarán primero para ver cómo se ve su API.

Si observa la mayoría de las bibliotecas de Linux, por ejemplo, su sistema de administración de paquetes de Linux a menudo tiene un paquete que contiene solo los binarios de la biblioteca (para usuarios "normales" que tienen programas que necesitan la biblioteca) y usted tiene un paquete "dev" que contiene los encabezados para la biblioteca. El código fuente normalmente no se suministra directamente en un paquete. Sería realmente engorroso si tuviera que obtener el código fuente de una biblioteca en algún lugar para obtener la documentación de la API.

Jesper
fuente
2
+1 - con la condición de que incluso si usa Doxygen, eso no significa que nunca va a leer directamente de la fuente. Las anotaciones de Doxygen son incluso a veces útiles como patrones estándar a seguir, y es útil si la anotación que encuentra está cerca del código que describe.
Steve314
1
@ Steve314, por supuesto, no dije que nunca querría mirar el código fuente de alguna biblioteca, pero ese no sería el primer lugar donde buscaría cómo se ve la API y cómo usarla.
Jesper
También recomendaría mantener todo lo relacionado con la API en el encabezado (o al menos en el encabezado o la fuente), ya que evitaría una posible incoherencia al actualizar la documentación en un lugar y no en el otro.
jopasserat
12

Resolvimos este problema (hace aproximadamente 25 años) creando un grupo de #defines (p. Ej., Públicos, privados, etc., que se resolvieron en <nada>) que podrían usarse en el archivo fuente y fueron escaneados por un script awk (horrores !) para generar automáticamente los archivos .h. Esto significa que todos los comentarios vivieron en la fuente y se copiaron (cuando corresponde) en el archivo .h generado. Sé que es bastante Old School, pero simplificó enormemente este tipo de documentación en línea.

Peter Rowell
fuente
1
hmm sé que este estilo de cosas puede ser útil, pero desde mi punto de vista siempre he encontrado ese tipo de documentación para ser francamente molesto ...
osirisgothra
1
Parafraseando a Donald Rumsfeld (un hombre que no me gusta), "Usted programa con las herramientas que tiene, no con las herramientas que desearía tener". Cada idioma con el que he trabajado en los últimos 40 años ha tenido al menos una verruga importante (si no más). Nuestra solución a) funcionó, b) usó herramientas que existían en ese momento, c) nos permitió dedicar nuestro tiempo a obtener el código generador de ingresos.
Peter Rowell
Aunque probablemente no optaría por esto, es una forma interesante de manejar los comentarios en los encabezados. ¿Los encabezados generados estarían en control de versiones? ¿o es este un proceso de lanzamiento para hacer una fuente redistribuible? (pero no utilizado por los desarrolladores)
ideasman42
Oh, he visto el mismo patrón recientemente en un proyecto iniciado en ≥ 2000 y estaban muy orgullosos de su ingenioso invento ...
5gon12eder
3
En nuestro caso, no mantuvimos ninguno de los archivos generados bajo control de versión, ya que se derivaron (re) fácilmente y directamente de los archivos rastreados.
Peter Rowell
9

Asumiendo que esto es código dentro de un proyecto más grande (donde los desarrolladores se moverán entre la fuente y los encabezados a menudo) , y siempre que esto no sea una biblioteca / middleware, donde otros pueden no tener acceso a la fuente, he encontrado que esto funciona mejor...

  • Encabezados:
    comentarios breves de 1-2 líneas, solo si son necesarios.
    A veces, los comentarios sobre un grupo de funciones relacionadas también son útiles.
  • Fuente:
    documentación en API directamente sobre la función (texto plano o doxygen si lo prefiere) .
  • Mantenga los detalles de implementación, solo relevantes para un desarrollador que modifique el código en el cuerpo de la función.

La razón principal de esto es para mantener los comentarios cerca del código, he notado que los documentos en los encabezados tienden a desincronizarse con los cambios en el código con más frecuencia. (por supuesto que no deberían, pero lo hicieron en nuestro proyecto en menos) . También los desarrolladores pueden agregar documentación en la parte superior de las funciones cuando realizan algún cambio, incluso si hay documentos de encabezado ... en otro lugar. Causar duplicaciones o información útil solo para estar en una de las cadenas de documentos.

Por supuesto, puede elegir una convención y asegurarse de que todos los desarrolladores la sigan, acabo de encontrar la convención por encima del ajuste más natural y causa menos problemas para mantener.


Por último, para proyectos grandes, existe la inclinación de no hacer pequeñas correcciones en un encabezado cuando se sabe que puede causar que se vuelvan a compilar potencialmente 100 o 1000 de archivos cuando otros actualizan el control de versión, lo que también ralentiza los errores de bisección.

ideasman42
fuente
5

En mi opinión (bastante limitada y sesgada), soy una forma de pensar de código fuente. Cuando hago partes en C ++, generalmente edito el archivo de encabezado una vez y luego nunca vuelvo a mirarlo.

Cuando coloco documentación en el archivo fuente, siempre la veo cuando estoy editando o leyendo códigos. Supongo que es una costumbre.

Pero solo soy yo ...

MattyD
fuente
1
No funciona muy bien si todo lo que tiene es una biblioteca compilada y el archivo de encabezado. En ese caso, más información en el encabezado es algo bueno porque es la única documentación de interfaz que tiene.
rapid_now
podría generar documentación con doxygen; también la toma de los archivos .c. Por lo tanto, podría distribuir documentación fácilmente con bibliotecas compiladas. Pero el problema sería con IDE que puede analizar archivos de encabezado y darle documentación mientras usa la función ... Pero tal vez podría resolver algún script de implementación que copiaría los comentarios de la función frm .c en .h ...
Vit Bernatik
5

Los comentarios no son documentación. La documentación para una función normalmente puede ser de 2K de texto, posiblemente con diagramas; consulte, por ejemplo, la documentación para funciones en el SDK de Windows. Incluso si su comentario a documento permite tal cosa, hará que el código que contiene el comentario sea ilegible. Si desea producir documentación, use un procesador de textos.

Neil Butterworth
fuente
actualización, es mucho más fácil documentar estos días (con cosas como Qt Creator) documentar la forma doxygen (o clonar), por ejemplo, en qtc solo presionas la tecla / algunas veces antes del comentario y la mitad del el trabajo está hecho para ti. Debido a cosas como esta, dudo que la gente quiera saltar a un procesador de texto solo para documentar su código. Solía ​​hacer esto, concedido, en 2005, pero nunca lo haría ahora. Incluso usar un editor html parece ser bastante arcaico ahora.
osirisgothra
@osirisgothra Doxygen- "documentación" puede ser fácil de hacer, y ciertamente produce una gran cantidad de LOC rápidamente escritos, pero el valor de la "documentación" producida sigue siendo discutible en la gran mayoría de los casos. Los comentarios de Doxygen no son una buena documentación (casi todos los detalles cruciales faltan generalmente), ni son buenos comentarios (tienden a repetir lo que ya es obvio de la firma). Creo que nbt tiene razón al decir que la documentación real no se mezcla con el código porque es perjudicial para la legibilidad del código. De todos modos, se perderá la sincronización, no hay una bala de plata para eso.
cmaster
4

Si las partes interesadas de su código fuente (por ejemplo, una pequeña biblioteca) se componen de "usuarios" (otros desarrolladores que utilizarán la funcionalidad de su biblioteca sin involucrarse en su implementación) y "desarrolladores" (usted y otros desarrolladores que implementarán la biblioteca) , luego coloque la "información de los usuarios" en el encabezado y la "nota de implementación" en la fuente.

Con respecto al deseo de no cambiar los archivos de encabezado más de lo absolutamente necesario, supongo que si su biblioteca no está "en un flujo loco de cambios", que la "interfaz" y la "funcionalidad" no cambiarán mucho, y tampoco Si los comentarios del encabezado cambian con demasiada frecuencia. Por otro lado, los comentarios del código fuente deberán mantenerse sincronizados ("nuevos") con el código fuente.

rwong
fuente
0

El objetivo de usar doxygen es que genera documentación y la hace accesible en otro lugar. Ahora toda esa documentación en los encabezados es solo basura, lo que hace que sea más difícil detectar rápidamente la declaración de función requerida, y tal vez sus sobrecargas. Un comentario de línea es el máximo que debería ir allí, pero incluso eso es una mala práctica. Porque si cambia la documentación en la fuente, recompila esa fuente y vuelve a vincularla. Pero si coloca documentos en el encabezado, realmente no desea cambiar nada, porque provocará una parte importante de la reconstrucción del proyecto.

Slava
fuente
1
Esto no parece ofrecer nada sustancial sobre los puntos hechos y explicados en las respuestas anteriores 7
mosquito
1
@gnat de las 7 respuestas anteriores, solo una está a favor del código contra los encabezados. Y esa está dando una argumentación totalmente diferente.
Slava