You are currently browsing the tag archive for the ‘comentarios’ tag.

Chiste de informáticos: viene el recién titulado de la universidad y pregunta por la documentación.

Si no has entendido el chiste, entonces ¡enhorabuena! Parece que nunca tuviste que entender un código kilométrico sin comentarios ni explicaciones ni documentación. Pues, aquí quiero proponer algunos trucos antes de ponerte a llorar.

Un escenario típico de analizar código puede empezar en una línea de código – si las trazas del programa eran tan amables de indicarla. En esta línea de código aparecen variables, que se definen con un valor de retorno de unas funciones que a su vez llaman más funciones y estas aún más. Sólo averiguar qué valor obtiene una variable y por qué puede llevarte a estudiar 20 subfunciones de cien líneas cada una. Al fin de tu estudio sabes que la variable tiene el valor 3.0, 5 o «mpf», pero todavía no sabes, qué esto significa y si es correcto. ¿Son tres litros de cerveza, cinco mesas libres o el comentario sobre el resultado del partido de fútbol? Lógicamente, esto se podría evitar documentando bien el código, pero en este artículo asumimos que ya no estamos en la universidad.

Entonces, ¿dónde vas a empezar a entender todo este código sin significado? Pues, básicamente escribes comentarios de documentación como si fuera un wiki: siempre cuando sabes algo, lo escribes en el sitio más adecuado. Cuando entiendes más, refinas los comentarios o los mueves a un sitio mejor. Así sigues hasta que hayas entendido el código lo suficiente para resolver tu problema concreto. Por supuesto, puedes seguir hasta tenerlo todo documentado, pero hasta ahora no he tenido ningún jefe que te dejaría el tiempo. En cambio, nadie se queja de comentarios incompletos. Más bien invitan a corregirlos. Esto es justamente el poder de un wiki: uno empieza, otro lo mejora. Pero sin el uno, el otro no haría nada. Así, ¡atrévete! ¡Pon comentarios de documentación aunque no estés de todo seguro!

Donde empiezas depende un poco de la parte que ya entiendes, pero típicamente son líneas simples o bloques pequeños. A continuación vamos a dar ejemplos.

El significado de una variable es más que saber su valor, sino también su tipo y su semántica. A veces una variables contiene un valor inequívoco. Por ejemplo t = time() en en el lenguaje C asigna a t el segundo actual desde el inicio de 1970 en segundos. Es decir, tú añadirías este comentario.

// Tiempo de sistema en segundos desde el 1 de enero de 1970
t = time();

Puede ser que el tiempo absoluto es siempre el tiempo «desde época» para ti. Entonces puedes omitirlo. Pero debe quedar claro para ti (y los demás) e – importante – debes escribir lo que sabes. Recuerda que queremos documentar el código como un wiki. Y esto empezamos con algo fácil. Aunque la línea por si misma será obvia, cada comentario te indica donde ya has entendido algo. Y nadie te prohibe borrarlo si has elaborado un comentario mejor.

Por cierto, corregir los niveles de indentación o los nombres de los identificadores también es documentar el código. En el ejemplo anterior, podrías escribir la documentación en el nombre de la variable y omitir el comentario.

tiempo_de_sistema_en_segundos_desde_1970 = time();

Esto resulta en una refactoración que a veces ni es fácil ni está permitida por modificar el código ejecutable. Pero ¡atrévete si puedes!

Conociendo el significado de una variable nos ayuda a entender más variables. Si t es el tiempo absoluto, entonces la variable x debe ser una duración en la expresión t + x. Quizá todavía no sabemos la duración de qué, pero ya podemos documentar la variable x con «duración en segundos». Y esto nos permite entender al menos parcialmente expresiones con x.

Si entendemos que el valor de una constante enumerativa signífica «verde», entonces podemos asumir que las demás constantes del mismo tipo todas serán colores – más unas con el significado de «ningún color» o «todos los colores». Sabiendo esto, ponemos comentarios a las definiciones de estas constantes y el tipo enumerativo. Una variable a que asignamos una de estas constantes tendrá lógicamente el significado de color también. Quizá no sabemos el color de qué, pero ya sabemos mucho más que nada.

Por cierto, si ya sabes que debes revisar un comentario por no tenerlo completo, entonces márcalo con una cadena de texto única. Probablemente tu nombre ya vale. Identificadores en el código no suelen llamarse María o José.

Cuando más identificadores simples entendemos, más probablemente entenderemos expresiones. Una expresión general como a < b se convierte, sabiendo que a y b son tiempos absolutos en

// Si a es antes que b
if (a &lt; b)

Conseguir reemplazar una expresión (matemática) por una frase en lengua natural ayuda treméndamente a entenderla. Recuerda que anteriormente tenías que haber entendido los significados de a y b – que se pueden haber inicializadas en funciones muy distintas. Por esto es importante documentar también las variables simples: son los componentes que debes haber entendido antes de poder entender sus agrupaciones.

Como con las expresiones ayuda resumir bloques de código en una sola frase. ¿Qué entiendes viendo este código?

p.db.set(a);
p.update();
p.notify();

Ahora imagina que alguien le habría puesto el título «Repinta el dashboard con el color a«. Para llegar a esto debes haber entendido el significa de p, db y a – y al contrario de la intuición, db no era database. Una vez entendido puedes reunir un bloque completo en una sóla frase. Con varios sub-bloques bien comentados puedes comprender el significado de un super-bloque complejo. Finalmente entenderás el significado de una función entera.

Entender una función aumenta drásticamente tu comprensión del código porque ahora ya no necesitas consultar la implementación de la función y todas sus subfunciones. Basta con leerse la documentación de la función con sus parámetros, su valor de retorno y sus excepciones. Esta documentación ya te permite documentar al menos parcialmente funciones que llaman a la función documentada, por ejemplo, si simplemente pasan el valor de retorno o no captan excepciones ya que estas tendrán probablemente el mismo significado para el usuario de la función llamante.

Finalmente con un par de funciones entendidas puedes documentar la clase que contiene todas estas funciones. Esto, a su vez, te ayuda a entender el significado de instancias de esta clase. Con lo que acabamos al inicio: documentar el significado de una variable simple.

Durante todo este transcurso no olvides tu meta: el error que buscas o la funcionalidad concreta que quieres entender. Tus comentarios serán como un wiki: incompletos y con cambios frecuentes. Lógicamente pararse ahí no es obligatorio. Puede ser la meta de escribir un documento de diseño del código a alto nivel. Esto requiere documentar muchas clases, tipos y demás. No serías el primero en ingenería inversa del propio software por no tener un código bien documentado. Pero puedes ser el primero en tu empresa en usar tus nuevos conocimientos para hacer la documentación.

Recuerda: el primero en agradecer estos comentarios de documentación, aunque sean incompletos, serás probablemente . Porque ya te imaginarás a quién el jefe asignará la tarea de analizar el próximo error en el mismo código.

Nota también, que bloques y funciones bien descritas son la base para refactoraciones éxitosas. Puedes sustituir un bloque de varias líneas con una función cuyo nombre lleva el título que pusiste al bloque. Esto hace el código más legible y reduce el tamaño de una función. Además, te darás cuenta cuando puedes sustir varios bloques por la misma función.

Lectura adicional

Una tarea típica de un programador (o «arquitecto» como se llaman los especialistas en esta tarea) es crear las tablas en una base de datos relacional. En este artículo no quiero hablar de los comandos SQL necesarios para crearlas, sino de las características de las tablas que aparecen a la hora de crear el modelo de datos en la base de datos. En este artículo asumo que el lector ya sabe relacionar objetos del programa con tablas en una base de datos.

En una base de datos nos encontramos típicamente con tablas de las funcionalidades siguientes:

  • Tablas de estado actual. Estas guardan datos parecidos a las variables en un lenguaje de programación.
  • Tablas de entrada y salida. Son tablas que guardan mensajes o trazas y se parecen a ficheros o flujos de datos en un lenguaje de programación.
  • Tablas de historial. En estas tablas guardamos los datos viejos de las tablas de estado o de entrada y salida.
  • Tablas de configuración. Son tablas en que guardamos constantes de enumeración, parámetros de configuración y otros datos, que se suelen cambiar poco o nunca.

Casi todas las tablas en un esquema se dejan clasificar por una de estas categorías y vamos a verlas ahora una en una.

Las tablas de estado actual y las tablas de entrada y salida suelen ser las tablas de «trabajo» ya que contienen la información del procesamiento.

Las tablas del estado actual

Lo que se guarda en una tabla de estado es lo que se guardaría en un objeto variable en un programa. Por eso representan un estado. (Como se puede hacer una correspondencia entre variables y tablas es el tema del artículo «Relación entre objetos y tablas en una base de datos«.)

Igual como las variables en un programa, estas tablas reciben muchas peticiones de lectura y escritura. Por lo tanto importa un acceso rápido. Esto se consigue utilizando una clave primaria numérica y eliminando datos obsoletos que se pueden transferir a tablas de historial.

Las tablas de entrada/salida

Las tablas de entrada y salida son aquellas que de alguna forma guardan mensajes. Se puede utilizar una tabla en la base de datos para enviar mensajes entre varios procesos. Un proceso escribe sus notificaciones y otro los lee y procesa.

A menudo el método que el proceso que lee emplea es un «polling»: comprueba regularmente si ha llegado algún mensaje nuevo con un estado de «no tratado». Típicamente hay una columna de estado de mensaje en este tipo de tablas. El proceso que escribe pone este estado a «mensaje nuevo» y el que lee les asigna un estado de «tratado». Por supuesto, se puede evitar este campo de estado si el proceso que lee elimina los mensajes tras tratarlos.

Sin embargo, muchas veces es preferible no borrar datos de una base de datos para facilitar la depuración de errores. Si los mensajes procesados se quedan, todavía se puede averiguar qué información enviaron los procesos entre sí. Si guardo un número de secuencia con cada mensaje, puedo saber en qué orden se han introducido los mensajes. Este número de secuencia puede ser la clave primaria de esta tabla. Se puede omitir el número de secuencia si se guarda la fecha (mejor el timestamp) de creación del mensaje en su lugar. De hecho puede ser recomendable, ya que el timestamp es más informativo e internamente se guarda también como un número. Se puede guardar también la fecha de procesado del mensaje en otra columna para tener la información completa.

Para simplificar el uso de la base de datos, no debería más que un proceso que lee los mensajes de una tabla. Puede haber varios que escriben, pero es recomendable que haya sólo un proceso que escribe y uno que lee. No es costoso crear muchas tablas en un esquema, pero puede ser costoso sacar los mensajes y depurar un fallo cuando sólo hay una tabla de mensajería que actúa como la central nacional de correos.

Es recomendable que los mensaje no estén sobrecargados de información. Si un proceso cambia una tabla de estado basta con notificar con algo como «he hecho algo en la tabla tal» y añadir como mucho la clave primaria en esta tabla. No envíes más datos. El proceso que lee puede hacer su propia consulta a las tablas de estado y obtener toda la información que necesita.

Las trazas de un programa también se pueden guardar en una tabla. En este caso sólo hay un proceso que escribe pero ninguno que lee.

Igual como las tablas de estado, las tablas de entrada y salida suelen tener muchas peticiones de lectura y escritura. Por lo tanto, vale todo lo que ya he mencionado más arriba sobre asuntos de velocidad.

Las tablas de historial

Conviene mantener las tablas de estado y de entrada/salida, es decir, las tablas de «trabajo» con un número de registros reducido, ya que el acceso a sus datos es más rápido cuando menos datos contengan. De otro lado muchas veces se desea guardar los datos antiguos. La solución traen las tablas de historial.

Todos los datos que ya no se necesitan en una tablas de trabajo se pasan a una tabla de historial. Esta tabla suele tener las mismas columnas con los mismos tipos ya que acoge a los mismos datos. Cuando se pasa un registro al historial, se puede borrar en la tabla de trabajo. Hay muchas aplicaciones que todavía permiten visualizar los datos históricos. Por ejemplo, si una tabla de estado contiene las ordenes de compra en curso, la tabla de historial correspondiente contiene las ordenes de compra ya cerradas y permite visualizar estadísticas sobre las ventas en los meses pasados.

No es necesarios pasar los datos de una tabla de trabajo a una tabla de historial justamente después de terminar el trabajo con un registro. Es una tarea que se puede programar una vez al día o una vez al mes en que se pasan todos los registros antiguos de golpe. Por eso las tablas de historial pueden tener pocas pero grandes modificaciones. Por no necesitar un acceso constante, la velocidad no es importante. Algunas bases de datos como Oracle, permiten guardar estas tablas un tablespace diferente.

Las tablas de configuración

Las tablas de configuración contienen parámetros de sólo lectura – aunque una aplicación puede permitir actualizarlos de forma esporádica. Puede ser factible cachear estos datos de configuración en un programa – sobre todo si son muchos y se cambian poco.

Tablas de configuración sustituyen lo que se podría guardar en un fichero «ini». La ventaja de las tablas es que se guardan todos los datos en un mismo sitio: la base de datos.

A menudo se usan para enlazar identificadores numéricos con un texto descriptivo. Por ejemplo, la tabla de ordenes de trabajo tiene una columna con el estado de la orden. Por ser una tabla de trabajo, la tabla de ordenes sólo guarda un número en el campo de estado, ya que es más rápido que un texto.  En una tabla de configuración se relaciona el número de estado con su significado. Por ejemplo, estado 10 equivale a «en preparación», estado 20 a «listo para enviar». Esta construcción permite mantener la velocidad de datos numéricos en las tablas de trabajo pero poder mostrar textos descriptivos al usuario.

Conclusión

Hemos visto diferentes conceptos de uso de tablas de base de datos. Aunque técnicamente la base de datos no distingue estos uso, un programador, sí, puede hacerlo. Puede diferenciarlo por asignar espacio de almacenamiento distinto, por optimizar consultas o por encapsular o cachear la información de forma distinta. Se pueden usar prefijos diferentes como «HIS_» para tablas de históricos para dejar claro de qué tipo de tabla se trata.

A base de las diferentes categorías, se pueden crear clases (abstractas) que se relacionan con uno u otro tipo de tabla. Por ejemplo, una estructura jerárquica como «orden de compra», «envíos de la orden», «contenido de los envíos» se parece a una estructura de «paleta», «caja», «contenido de caja»: un contenedor que contiene otro contenedor. Cada anidamiento necesita una columna adicional para la clave primaria. Una clase abstracta de «contenedor triple» que usa el nombre de las tablas como parámetro podría cargar la estructura de diferentes datos con el mismo código. Las clases derivadas se ocuparían de extraer los datos particulares de la tabla – dependiendo si es una orden de compra o una paleta de transporte con cajas. Una secuencia SQL modificable podría crear estas estructuras de datos. De esta forma se puede crear código reciclable para varios proyectos.

Y una última nota: Las bases de datos (al menos las de importancia) permiten guardar comentarios descriptivos junto con la definición de las tablas y columnas. Esto es una funcionalidad muy útil ya que permite explicar la utilidad de un campo donde se necesita. Y hay pocos campos que no necesitan una descripción explicativa. Desgraciadamente no se usa esta posibilidad en todos los sitios. Aunque puede ser una alternativa describir los campos en un documento tipo Word, no es tan práctico como guardar el significado directamente en la base de datos. Porque los documentos se pueden perder. Si, en cambio, uno consigue perder la base de datos, las descripciones de los campos van a ser lo de menos.

Referencias

Honestamente, el título confunde: Este artículo comenta mucho los comentarios.

Programadores están obligados a hacer su código funcionar. Una restricción que les quita mucha creatividad. Sólo una minoría privilegiada, que escribe comentarios en el código, tiene la posibilidad de expresarse con libertad.

Por qué comentarios

Miles de programadores (bueno, quizá más bien unos veinte) no tienen mayor preocupación que su aparición como coautor en este artículo. Por este motivo evitan el uso de comentarios en su código. Mientas tanto disfrutan el resultado simple y exacto de cada función, que devuelve 3 cuando el parámetro var1 es “OK” y var2 guarda 15. Tres significa que la máquina va a arrancar, el robot gira a la izquierda, el programa va a terminar o el contrario de esto – o todo a la vez o una combinación arbitraria de esto. Depende del contexto, el cual puedes encontrar 150 líneas más arriba o en otro fichero del programa. Mala suerte, si la función está mal y debería devolver 4, que es algo diferente que 3 o lo mismo. Depende del contexto. Hay muchas maneras de escribir código inmantenible.

No te entiendo

Usando comentarios trae la cuestión de lo que es un buen comentario. En general, yo consideraría un bueno comentario alto que explica la semántica y no la sintaxis. Alguien que sabe programar no necesita un comentario como

// Incrementa x en uno
x = x + 1

Sin embargo, es un comentario obligatorio cuando sería el único en una función de 1500 líneas.

Explicar la semántica puede ser difícil a veces. A continuación sigue una lista con ejemplos de la vida real, que muestran lo que no es probablemente un buen comentario.

bool ProcesaTeclaUsuario(void)
// de momento es global por problemas con los punteros

En este programa no hubo ninguna función no-global. Pero, por supuesto, puede haber una razón de no ser global diferente para cada función.

num_mens_control++;  //TODO tiene sentido???

¿Tiene sentido lo que haces ahí? Mientras funciona, todo tiene sentido. En este contexto me es grato presentar la definición

Un científico sabe por qué no funciona. Un ingeniero no sabe, por qué funciona.

Mientras cambias código y no estás seguro si el cambio fue bueno, puedes dejar las líneas originales comentadas y marcar la modificación con una palabra especial. Si tienes mucho que cambiar, entonces un poco de variación puede resultar más gratificante. Estos ejemplos son de un fichero con unos 2000 líneas:

//TODO
//XXX TODO
//WORKAROUND
//WORKAROUND TO DO IT BETTER
//XXX BAUSTELLE
//XXX BAU 28.06

Baustelle es alemán para “obras”. El aviso “constantemente en obras” en una página web es igualmente significativo. Quién esperaría que una página web cambiase.

!! rules necesarias para el correcto funcionamiento:
rule void Nr_Set_Visible_Displayed(object Ob_Strip input)

A diferenciar de las rules no necesarias y las rules para el funcionamiento incorrecto.

!!  start of Md_GbMDW_FPL needed rules

¿Escribes código que no es needed?

!! END OF RULE EXPERIMENTAL

Vale. Lo haces.

Cuando la comunicación falla, todavía te queda decir a otros lo que deben hacer por código fuente.

!! Note: move this(Ob_GbManCoord) to strip model.
export variable object Ob_GbManCoord;

Por supuesto, lo podrías hacer tú mismo, pero ¿por qué?

!! New model for waypoints line
model MdGb Md_Gb_Waypoints

O este comentario es actualizado frecuentemente o este modelo será nuevo para siempre.

!! Study assigment of colours
if Ob_Fp_Strip.In_Flag_Un_Flag_Field then

A veces, un ordenador toma un respiro se pregunta: ¿En qué color debería pintarlo?

!! Rule to solve the STR-1207: Panning in Playback mode

Resuelto. Una vez y por todas. Ni piensas en que este código podría ser útil para otro propósito.

//declarar el objeto, es importante inicializarlo a NULL
TStringList *Valores = NULL;
Valores = new TStringList; //crear instancia del objeto

Esto es un comentario importante. De otra forma el lector podría llegar a pensar que no vale la pena asignar NULL a un puntero que será sobrescrito inmediatamente después.

Como comentar mejor

En general podrías tener en cuenta las siguientes ideas para escribir un código.

  • Como un programador ya sabe el lenguaje de programación, no necesitas explicárselo de nuevo. Una excepción sería si usaste el lenguaje de una forma rara y sorprendente como, por ejemplo, sobrecargar el operador + sin la connotación de “más”. No obstante, en este caso deberías considerar cambiar el código y no el comentario.
  • No repitas código en tus comentarios. “Añadir cinco a x” no aporta ninguna información nueva a “x + 5”. Céntrate en el significado de x, por ejemplo “añade 5 metros a la posición x.
  • No olvides que identificadores (variables, tipos y nombres de funciones) ya deberían contener su semántica en si mismos. Un comentario puede todavía ser necesario para explicar el contexto en que una operación tiene lugar, por ejemplo un comentario a send_to_printer(document) podría ser «Aquí el documento debe estar en un formato adecuado para la impresora».
  • ¿Tiene importancia cuando el código o el comentario fue escrito y cuantas veces fue cambiado? Ten esto en cuenta antes de escribir una fecha en el código. “Nuevo” y “viejo” dan una idea de que algo fue cambiado, pero no cuando. No obstante, no tengas miedo en que comentarios podrían caducar en el próximo cambio de código. Todavía pueden dar una pista importante y un programador sabe que lo que hace un programa funcionar es el código y no el comentario.
  • No olvides limpiar el código. Muchos de los ejemplos anteriores se “olvidaron”. Eran marcadores durante el desarrollo que perdían su sentido cuando el trabajo concluyó.
  • Si tus ficheros usan una cabecera, sólo escribe cosas ahí para que habrá suficiente disciplina para actualizarlas. Un fichero guarda una fecha de última modificación, el último “autor” es probablemente uno de tu grupo de trabajo, y la versión del fichero fuente inútil. Un fichero ejecutable tiene un número de versión y todos los ficheros fuente para crearlo tienen este mismo número de versión automáticamente. A menos si vendes ficheros fuentes y no programas que funcionan.
  • No es mala idea de usar comentarios para separar código visualmente en secciones (con barras o incluso con títulos). Es sabio usar el mismo estilo para el mismo tipo de sección.

Referencias

Doxygen es una herramienta de documentación automatizada muy potente. Como muchos programas viene con la configuración para el inglés americano por defecto. Por eso puede haber problemas a la hora de procesar bien comentarios que usan letras con acentos como suele haber en español y muchos otros idiomas.

Una solución al problema es guardar los ficheros con la codificación UTF-8, que es la que viene por defecto también en phpDocumentor. Sin embargo, doxygen permite especificar explícitamente qué codificación a usar.

Si usas el interfaz gráfico Docwizard, entonces puedes pinchar en la pestaña «Expert», y luego en el menú de los «Topics» seleccionas «Input». A la derecha hay un campo que se llama INPUT_ENCODING. Cambia el valor («UTF-8» por defecto) a la codificación de tus ficheros fuente. Para el español suele ser la codificación ISO-8859-1. Obviamente sólo puedes usar una codificación de caracteres para un proyecto.

Si no usas el interfaz gráfico puedes buscar por la cadena de texto INPUT_ENCODING en el fichero de configuración.

Si no estás seguro qué codificación a elegir, entonces puedes visualizar la documentación generada y jugar con la codificación de los caracteres del navegador hasta tu documentación  salga bien. La codificación puedes cambiar (en Mozilla Firefox) con el menú View (Ver) -> Character Encoding. Cuando haces estas pruebas fíjate en los textos que has escrito tú en la documentación; y no en los títulos que añade doxygen. Cuando pones la codificación correcta en el campo INPUT_ENCODING, tanto los textos generados a partir de los comentarios como los que añade doxygen saldrán con los acentos bien. Recuerda volver poner tu navegador a autodetectar la codificación.

Por cierto, también se puede modificar la codificación del fichero de configuración de doxygen. En la pestaña «Expert» seleccionas en el menú «Topics» el punto «Project». A la derecha hay un campo que se llama DOXYFILE_ENCODING. Cambia el valor («UTF-8» por defecto) a la codificación desdeada.

Referencias

En muchas ocasiones se pide un manual de referencia del código. Esto es especialmente importante a la hora de crear una librería que esté ideada para que otro programador la use en una aplicación final. Este manual engloba de alguna forma un trabajo doble: hay que explicar bien el funcionamiento de cada función en el código mismo y luego repetir la misma información en un documento de texto.

De este trabajo pueden encargarse sistemas de documentación automáticos. Leen el código y extraen la información necesaria para generar la documentación. Muchas veces permiten varios tipos de documentos de salida: en formato HTML, en formato PDF, como fichero de HTML comprimida (CHM) o en formato «Rich Text».

Probablemente el más influyente de estos sistemas es javadoc. Fue incluido en el entorno Java de Sun como una parte integral del sistema y ha marcado desde entonces el formato de los comentarios de documentación. El programa de más uso es probablemente doxygen, ya que puede entender la sintaxis de muchos lenguajes, muy especialmente de C++. Para PHP es recomendable usar phpDocumentor.

A todos estos sistemas es común que requieren un marcador especial para los comentarios que se exportan del código a la documentación final. El más extendido es el de javadoc que marca los comentarios entre /** y */. Nota que es nada más que un comentario al estilo /**/ donde la primera letra es un asterisco. Sin embargo, para el sistema de documentación, el segundo asterisco en /** lo marca como un comentario de documentación cuyo contenido será procesado por el sistema de documentación automatizado.

Dentro de este bloque están permitido una multitud de etiquetas (tags en inglés) que dependen del objeto documentado, por ejemplo si es un fichero una clase o una función. La declaración de una función podría parecerse a algo como esto:

/**
 * La primera frase es un título/resumen de la función. Después del
 * punto que delimita la primera frase comienza la documentación
 * detallada. Características especiales están marcadas con una
 * etiqueta.
 * @param parametro El parámetro de la función.
 * @return La función devuelve un resultado.
 */
int mi_funcion(int parametro);

Guarda tus ficheros fuentes en Unicode si quieres tener acentos correctos en la documentación. Esto vale al menos para phpDocumentor.

Los sistemas de documentación sólo documentan declaraciones, objetos y tipos globales, ficheros y inclusiones. No documentan el cuerpo de una función ya que se supone que no es algo importante en un manual de referencia. Sin embargo ofrecen una etiqueta @internal con información interna, que sólo se compila con un cierto flag activado. De la misma forma se puede documentar o no variables y métodos privados.

Es cierto que los sistemas de documentación requieren algún esfuerzo al principio para instalar y entenderlos. Sin embargo, una vez superado esta fase ofrecen tener una documentación actualizada prácticamente en tiempo real que con sus enlaces y agrupaciones son una ayuda incluso para el autor durante el desarrollo. El entorno Eclipse ya incluye un enlace para mostrar la documentación de doxygen para código de C++.

Probablemente has aprendido en algún sitio que se ponen comentarios para documentar el código y explicar los pasos que está haciendo tu programa a otros. Esto no está de todo erróneo, aunque la vida real te puede enseñar otra cosa.

Comentarios no son productivos. No añaden funcionalidad que se podría vender, cuestan tiempo en escribirlos, se quedan obsoleto si cambias el programa y poner comentarios sobra si usas identificadores autoexplicativos. Si quieres saber qué pasa en cada línea del programa, usa un depurador y observa como se cambian las variables. Una de mis frases favoritas es: «Los comentarios ponemos cuando tenemos tiempo.» Desde luego nunca tenemos tiempo. Si no dímelo y te asigno otra tarea.

En conclusión: Olvídate poner comentarios para satisfacer a otros a menos que sea explícitamente requerido. Al final nadie se leerá más que dos líneas de comentario.

La verdadera razón de poner un comentario eres tú. Porque tú eres la primera persona en leer, entender y depurar todo este código que has hecho. Así elige: ¿Poner orden te da pereza y no te importa pasar horas sólo para hacerte entender otra vez lo que ya entendiste hace medio año o, al contrario, es el caos que te da pereza y prefieres que alguien explica para qué todo este código es útil?

No extraña que los programadores que más tendencia tienen a usar identificadores autoexplicativos son también aquellos que más comentarios ponen. Simplemente prefieren pensarse algo una vez y no cada vez que leen algo.

Un trozo de programa escribes una vez, lo modificas diez veces y lo lees cien veces. Si tardas 99 segundos en escribir un comentario que te ahorra un segundo de pensar a la hora de leerlo, entonces todavía sales rentable. Como es probable que nadie más se leerá tu comentario, tampoco cuesta mucho pensar cuántos detalles pones en el comentario: los que a ti te gustaría tener la próxima vez que debes entender esto.

Mis criterios son los siguientes:

  • Si escribo una nueva función, lo primero que hago es apuntarme lo que esta función debería hacer. Esto será el comentario de la cabecera.
  • Lo mismo vale dentro de una función. Primero escribo lo que quiero hacer ahí.
  • Aunque no estoy seguro si borraré una líneas al final, siempre pongo comentarios. Así tengo código bonito desde el primer momento y me ahorro la frustración que debo repasar todo si una vez funciona. (Al final borrar algo no cuesta tanto.)
  • Si hace falta cambiar código de forma temporal, pongo marcadores como «start debug maddin» y «end debug maddin». Está claro que son cambios temporales y como no nombre variables «maddin», es fácil encontrar todos los marcadores temporales. Si cada uno usa una palabra distinta en lugar de «maddin» es incluso posible saber quién ha dejado el marcador ahí.
  • Si una línea de código funciona con misterio pongo un largo comentario no sólo sobre lo que hace esta línea sino porque es mejor que otra forma.
  • A veces pongo incluso un comentario al estilo «me he pasado dos horas para descubrir que el programa se cuelga si llamo la variable a. Ahora se llama b por eso.» Relaja tus sentimientos agresivos cuando lo escribes y te hace sonreír cuando lo vuelves a encontrar. No te cortes incluir alguna palabrota si te relaja. Como mucho tu jefe sale del armario admitiendo que lee tu comentarios.

En fin, la próxima vez que te preguntas si pones un comentario o no, ponlo.

Escribe tu dirección de correo electrónico para suscribirte a este blog, y recibir notificaciones de nuevos mensajes por correo.

Únete a otros 61 suscriptores

Archivos

May 2024
L M X J V S D
 12345
6789101112
13141516171819
20212223242526
2728293031