A la hora de escribir código que vaya a ser usado por otros resulta crítico documentarlo adecuadamente. Este proceso de documentación es algo realmente útil por varias razones, obliga a revisar qué hace cada función exactamente, sienta bases para que futuros desarrolladores (o uno mismo en años siguientes) pueda averiguar qué hacía el código y ayudará a los usuarios de nuestro código a sacarle el máximo provecho y a comprender las opciones de diseño adoptadas.

Sin embargo, documentar código puede ser una tarea tediosa. Ya es difícil que los programadores comenten adecuadamente el código fuente como para encima exigirles que mantengan actualizado un documento aparte con las explicaciones de uso de funciones y objetos. Por eso, hay muchas herramientas que permiten generar el código a partir de los comentarios plasmados en el mismo código fuente. De esta manera los programadores sólo tienen que plasmar la información en un sitio (el código fuente) lo que facilita el mantenerla actualizada.

 

doxygen_logo

 

¿Qué es Doxygen?

Doxygen es una herramienta de generación de documentación a partir del código fuente, compatible con C, C++, C#, Objective-C, IDL, Java, VHDL, PHP, Python, Tcl, Fortran, y D. Genera diagramas de herencia de manera automática. Exporta a HTML, CHM, RTF, LaTeX, PDF (Vía LaTeX), XML, o incluso páginas de man.

 

Instalacion y uso

Existen varias maneras de usar la herramienta, siendo la más cómoda el asistente visual que incorpora. Usando un simple sistema de menús se pueden configurar las opciones básicas que son:

  • Project: En este apartado se selecciona el nombre del proyecto, una breve descripción, la versión, el logo, la carpeta donde debe buscar el código y la carpeta donde debe guardar la documentación.

  • Mode: En este apartado se selecciona el lenguaje de programación en el que está el código, y se selecciona si se quieren mostrar todas las entidades o solo aquellas documentadas, de tal manera que podemos evitar tener valores vacíos solo con el nombre, como pasa en Javadoc. Además se puede referenciar directamente al código fuente, para que conecte cada función con la línea de código correspondiente.

  • Output: En este apartado se puede seleccionar el formato de salida, y las diferentes opciones de generación, siendo los dos apartados mayores HTML y LaTeX, y además pudiendo generar el resto de los formatos vistos anteriormente.

  • Diagrams: En este apartado se permite personalizar la manera de generar los gráficos y diagramas.

doxygen_gui

Una vez configuradas dichas opciones, en la pestaña Run se hace click en “Run Doxygen” donde, en función de las opciones configuradas se generarán una o varias salidas.

 

Documentando el código

La transición a partir de código comentado para herramientas como Javadoc es automática ya que reconoce los comandos habituales. Si es la primera vez que usa un sistema de generación de documentación puede usar otras notaciones.

 

Bloques de comentarios para lenguajes de programación similares a C (C/ C++/ C#/ Objective-C/ PHP/ Java)

Para cada entidad en el código hay dos (o en algunos casos tres) tipos de descripciones, que juntas forman la documentación para esa entidad; una breve descripción y la descripción detallada, ambos son opcionales. Para los métodos y funciones también hay un tercer tipo de descripción, la llamada descripción en el cuerpo, que consiste en la concatenación de todos los bloques de comentarios que se encuentran dentro del cuerpo del método o función.

Se permite tener más de una breve o detallada descripción (pero no es recomendable, ya que el orden en el que aparecerán las descripciones no se especifica).

Como el nombre sugiere, una breve descripción es un resumen de una sola línea, mientras que la descripción detallada proporciona una documentación más larga y detallada. Una descripción “en el cuerpo” también puede actuar como una descripción detallada o puede describir una colección de detalles de implementación. Para la salida HTML también se utilizan breves descripciones para proporcionar información sobre herramientas en los lugares donde se hace referencia a un elemento.

Hay varias formas de marcar un bloque de comentario como una descripción detallada:

  • Utilizando el estilo Javadoc, que consiste en un bloque de comentarios de estilo C a partir de dos asteriscos (*).
/**
 * ... text ...
 */

  • Utilizando el estilo Qt y adicionando el signo de exclamación (!) después de abrir un bloque de comentario al estilo C.
/*!
 * ... text ...
 */

En ambos casos, los * intermedios son opcionales, por lo que también es válido:

/*!
 ... text ...
*/

  • Una tercera alternativa es el uso de un bloque de al menos dos líneas de comentarios C++, donde cada línea comienza con una barra diagonal adicional o un signo de exclamación. Estos son ejemplos de los dos casos.
///
/// ... text ...
///

//!
//!... text ...
//!

Tenga en cuenta que una línea en blanco finaliza un bloque de documentación en este caso.

  • A algunas personas les gusta hacer sus bloques de comentarios más visibles en la documentación. Para este propósito se puede utilizar lo siguiente:
/********************************************//**
 *  ... text
 ***********************************************/

Tenga en cuenta las 2 barras para terminar el bloque de comentario normal y comenzar un bloque de comentario especial.

/////////////////////////////////////////////////
/// ... text ...
/////////////////////////////////////////////////

Para la descripción breve también hay varias posibilidades:

  • Se podría utilizar el comando \brief de uno de los bloques de comentarios anteriores. Este mandato finaliza al final de un párrafo, por lo que la descripción detallada siguiente después de una línea en blanco.
/*! \brief Brief description.
 *         Brief description continued.
 *
 *  Detailed description starts here.
 */

  • Si la opción de configuración JAVADOC_AUTOBRIEF tiene como valor “YES” en el archivo de configuración, entonces, utilizando el estilo Javadoc módulos de comentario, se iniciará automáticamente una breve descripción que termina en el primer punto seguido por un espacio o una nueva línea.
/** Brief description which ends at this dot. Details follow
 *  here.
 */

La opción tiene el mismo efecto para comentarios especiales multilínea al estilo C++.

/// Brief description which ends at this dot. Details follow
/// here.

  • Una tercera opción es el uso de un comentario especial estilo C++ que no incluya más de una línea.
/// Brief description.
/** Detailed description. */

//! Brief description.

//! Detailed description 
//! starts here.

Observe la línea en blanco en el último ejemplo, que se requiere para separar la breve descripción del bloque que contiene la descripción detallada. El valor de la opción JAVADOC_AUTOBRIEF debe ser igual a “NO” para este caso.

Como se puede ver Doxygen es bastante flexible. Si tiene varias descripciones detalladas, como en el siguiente ejemplo:

//! Brief description, which is
//! really a detailed description since it spans multiple lines.
/*! Another detailed description!
 */

Ellos serán unidos. Tenga en cuenta que también es el caso si las descripciones se encuentran en diferentes lugares del código. En este caso el orden dependerá del orden en que Doxygen analiza el código.

A diferencia de otros sistemas de documentación, Doxygen también le permite poner la documentación de los miembros (incluyendo las funciones globales) delante de la definición. De esta forma la documentación se puede colocar en el archivo de origen en lugar del archivo de encabezado. Esto mantiene el archivo de cabecera compacto, y permite que el ejecutor de los miembros tenga un acceso más directo a la documentación. Como solución de compromiso la breve descripción podría ser colocada antes de la declaración y la descripción detallada antes de la definición de miembro.

 

Poner la documentación después de que miembros

Si desea documentar los miembros de un archivo, estructura, unión, clase o enumerativo, a veces se desea colocar el bloque de documentación después de que el miembro en vez de antes. Para este propósito hay que poner un signo de < adicional en el bloque de comentarios. Tenga en cuenta que esto también funciona para los parámetros de una función.

Estos son algunos ejemplos:

int var; /*!< Detailed description after the member */

Este bloque se puede utilizar para poner un bloque de documentación detallada estilo Qt después de un miembro. Otras maneras de hacer lo mismo son:

int var; /**< Detailed description after the member */

int var; //!< Detailed description after the member
         //!< 

int var; ///< Detailed description after the member
         ///<

La mayoría de las veces sólo se quiere poner una breve descripción después de un miembro. Esto se hace de la siguiente manera:

int var; //!< Brief description after the member

int var; ///< Brief description after the member

Para las funciones uno puede usar el comando @param para documentar los parámetros y luego utilice [in], [out], [in,out] para documentar la dirección. Para la documentación en línea esto también es posible comenzando con el atributo de dirección, por ejemplo.

void foo(int v /**< [in] docs for input parameter v. */);

Tenga en cuenta que estos bloques tienen la misma estructura y significado que el bloque de comentarios especiales en la sección anterior sólo el < indica que el miembro se encuentra a principios del bloque en lugar de después del bloque.

He aquí un ejemplo de la utilización de estos bloques de comentarios:

/*! A test class */
class Test
{
  public:
    /** An enum type.
    * The documentation block cannot be put after the enum!
    */
    enum EnumType
    {
      int EVal1, /**< enum value 1 */
      int EVal2 /**< enum value 2 */
    };
    void member(); //!< a member function.
  protected:
    int value; /*!< an integer value */
};

Estos bloques sólo se pueden utilizar para los miembros de documentos y parámetros. No pueden ser utilizados para documentar archivos, clases, uniones, estructuras, grupos, espacios de nombres y los propios enumerativos. Además, los comandos estructurales mencionados en la sección siguiente (\class) no se permiten dentro de estos bloques de comentarios.

He aquí un ejemplo de un fragmento de código C++ documentado utilizando el estilo de Qt.

//! A test class.
/*!
A more elaborate class description.
*/
class Test
{
  public:
    //! An enum.
    /*! More detailed enum description. */
    enum TEnum {
      TVal1, /*!< Enum value TVal1. */
      TVal2, /*!< Enum value TVal2. */
      TVal3 /*!< Enum value TVal3. */
    }
    //! Enum pointer.
    /*! Details. */
    *enumPtr,
    //! Enum variable.
    /*! Details. */
    enumVar;
    //! A constructor.
    /*!
    A more elaborate description of the constructor.
    */
    Test();
    //! A destructor.
    /*!
    A more elaborate description of the destructor.
    */
    ~Test();
    //! A normal member taking two arguments and returning an integer value.
    /*!
    \param a an integer argument.
    \param s a constant character pointer.
    \return The test results
    \sa Test(), ~Test(), testMeToo() and publicVar()
    */
    int testMe(int a,const char *s);
    //! A pure virtual member.
    /*!
    \sa testMe()
    \param c1 the first argument.
    \param c2 the second argument.
    */
    virtual void testMeToo(char c1,char c2) = 0;
    //! A public variable.
    /*!
    Details.
    */
    int publicVar;
    //! A function variable.
    /*!
    Details.
    */
    int (*handler)(int a,int b);
};

Las breves descripciones se incluyen en el resumen de miembro de una clase, espacio de nombres o un archivo y se imprimen con una pequeña fuente en cursiva (esta descripción se puede ocultar si el valor de BRIEF_MEMBER_DESC es “NO” en el archivo de configuración). Por defecto las breves descripciones se convierten en la primera frase de la descripción detallada (pero esto se puede cambiar si el valor de REPEAT_BRIEF es “NO”). Tanto el resumen y las descripciones detalladas son opcionales para el estilo de Qt.

Este es el mismo fragmento de código, que se muestra más arriba, esta vez documentado utilizando el estilo Javadoc y JAVADOC_AUTOBRIEF en “YES”:

/**
* A test class. A more elaborate class description.
*/
class Test
{
  public:
    /**
    * An enum.
    * More detailed enum description.
    */
    enum TEnum {
      TVal1, /**< enum value TVal1. */
      TVal2, /**< enum value TVal2. */
      TVal3 /**< enum value TVal3. */
    }
    *enumPtr, /**< enum pointer. Details. */
    enumVar; /**< enum variable. Details. */
    /**
    * A constructor.
    * A more elaborate description of the constructor.
    */
    Test();
    /**
    * A destructor.
    * A more elaborate description of the destructor.
    */
    ~Test();
    /**
    * a normal member taking two arguments and returning an integer value.
    * @param a an integer argument.
    * @param s a constant character pointer.
    * @see Test()
    * @see ~Test()
    * @see testMeToo()
    * @see publicVar()
    * @return The test results
    */
    int testMe(int a,const char *s);
    /**
    * A pure virtual member.
    * @see testMe()
    * @param c1 the first argument.
    * @param c2 the second argument.
    */
    virtual void testMeToo(char c1,char c2) = 0;

    /**
    * a public variable.
    * Details.
    */
    int publicVar;

    /**
    * a function variable.
    * Details.
    */
    int (*handler)(int a,int b);
};

Del mismo modo, si se quiere, la primera frase de un bloque de documentación estilo Qt para automáticamente ser tratada como una breve descripción, se puede establecer QT_AUTOBRIEF a “YES” en el archivo de configuración.

 

Documentación en otros lugares

En los ejemplos anteriores los bloques de comentarios siempre se encuentran delante de la declaración o definición de un archivo, de clase o espacio de nombres o delante o después de uno de sus miembros. Aunque esto es a menudo cómodo, puede ser a veces que existan razones para incluir la documentación en otro lugar. Para documentar un archivo que esto es aún requerido ya que no hay tal cosa como “delante de un archivo”.

Doxygen le permite poner sus bloques de documentación prácticamente en cualquier lugar (la excepción es en el interior del cuerpo de un función o el interior de un bloque de comentario estilo C normal).

El precio que se paga por no poner el bloque de documentación directamente antes (o después) de un elemento es la necesidad de poner un comando estructural en el interior del bloque de documentación, que conduce a una duplicación de la información. Así que en la práctica se debe evitar el uso de comandos estructurales a menos que existan otros requisitos que obliguen a hacerlo.

Los comandos estructurales (como todos los otros comandos) comienzan con un backslash (\), con el signo de arroba (@) si se prefiere el estilo Javadoc, seguido del nombre del comando y de uno o más parámetros. Por ejemplo si desea documentar la clase Test de los ejemplos anteriores podría también haber puesto el siguiente bloque de documentación en alguna parte de la entrada que es leída por Doxygen.

/*! \class Test
    \brief A test class.

    A more detailed class description.
*/

En el ejemplo anterior el comando especial \class se usa para indicar que el bloque de documentación contiene documentación para la clase Test. Otros comandos estructurales son:

  • \struct para documentar una estructura de C.

  • \union para documentar una unión.

  • \enum para documentar un enumerativo.

  • \fn para documentar una función.

  • \var para documentar una variable o una definición de tipo o un valor de un enumerativo.

  • \def para documentar una sentencia #define.

  • \typedef para documentar una definición de tipo.

  • \file para documentar un fichero.

  • \namespace para documentar un espacio de nombres.

  • \package para documentar un paquete de Java.

  • \interface para documentar una interfaz de IDL.

 

Bloques de comentarios en Python

Para Python hay una manera estándar de documentar el código usando las denominadas cadenas de documentación. Estas cadenas se almacenan en el documento y se pueden recuperar en tiempo de ejecución. Doxygen extraerá dichos comentarios y asumen que tienen que estar representados en una forma con formato previo.

"""@package docstring
Documentation for this module.

More details.
"""

def func():
    """Documentation for a function.

    More details.
    """
    pass

class PyClass:
    """Documentation for a class.

    More details.

    """
    def __init__(self):
        """The constructor."""
        self._memVar = 0;

    def PyMethod(self):
        """Documentation for a method."""
        pass

Note que en este caso ninguno de los comandos especiales de Doxygen es soportado.

También hay otra manera de documentar el código Python usando los comentarios que comienzan con “##”. Este tipo de bloques de comentarios están más en consonancia con la forma en módulos de documentación de trabajo para los demás lenguajes soportados por Doxygen y también permite el uso de comandos especiales.

## @package pyexample
# Documentation for this module.
#
# More details.

## Documentation for a function.
#
# More details.
def func():
    pass

## Documentation for a class.
#
# More details.
class PyClass:
    ## The constructor.
    def __init__(self):
        self._memVar = 0;

    ## Documentation for a method.
    # @param self The object pointer.
    def PyMethod(self):
        pass

    ## A class variable.
    classVar = 0;

    ## @var _memVar
    # a member variable

Python se parece más a Java que a C o C ++, por lo que se recomienda que el valor de OPTIMIZE_OUTPUT_JAVA sea igual ar “YES” en la configuración.

 

Conclusiones

Bueno eso es todo por hoy. Discúlpenme si les parece muy extenso el artículo. Es que quería darles la mayor cantidad de elementos posibles. Espero que les sea útil en algun momento de sus vidas y que comenten sus impresiones acerca de esta fabulosa herramienta.

Fuente: Sitio oficial.