|
Adolfo Di Mare |
Resumen |
Abstract |
|
|
La globalización ha unido a los programadores en una gran familia que produce todos los días millones de líneas de código. Como ha ocurrido ya tantas veces, si el programa en construcción será utilizado en pocas ocasiones existe una gran posiblidad de que su documentación no quede escrita. Aunque a primera vista esto parece un ahorro, pronto el programador descubre que especificar módulos le facilita su trabajo y acorta el tiempo necesario para construir programas. La razón de esta realidad es simple: quién no sabe adónde va, llega a otro lado [DiM-2007]. También conviene incorporar la definición de los datos de pruebas en la especificación de cada módulo, como se comenta en [DiM-2008]. | Globalization has brought programmers together into a large family that produces every day millions of lines of code. As it has happened many times over, if the program under construction will be used only in rare instances there is a strong possibility that its documentation will not be written. Although at first glance this looks like savings, the developer will soon discover that module specification facilitates his work and shortens the time needed to build programs. The reason for this reality is simple: whoever does not know where he goes, winds up elsewhere [DiM-2007]. It is also important to incorporate test data definition in each module specification, as discussed in [DiM-2008]. |
Cuando en este escrito se habla de "lenguajes" debe entenderse
"lengua hablada" pues se supone siempre que los programas
están escritos en C++, pero el método para
documentación en múltiples lenguajes aquí
descrito puede generalizarse a otros lenguajes de
computación en los que se usa la herramienta profesional de
documentación Doxygen
[VH-2005]. Doxygen usas etiquetas dentro
del código fuente del programa, muy similares a las de
JavaDoc:
/** Sorts the array */ .
Genera páginas HTML y documentos Latex o RTF. En la
documentación generada se destacan clases, métodos y
funciones e incluye opciones que permiten adaptarlos a diferentes
necesidades.
|
When in here we speak about "languages" it should be understood as
"spoken languages" as it is always assumed that programs are
written in C++, but the documentation method for multiple
languages described in here can be generalized to other computer
languages in which the profesional documentation tool Doxygen is
used
[VH-2005]. Doxygen uses embedded tags in
the program source, which are similar to JavaDoc's:
/** Sorts the array */ . It
generates HTML pages and Latex or RTF documents. The generated
documentation highlights clases, methods and functions, and its
options help tailoring it to different needs.
|
Bloques de documentación para cada lenguaje |
Documentation blocks for each language |
Es natural que al construir un programa el programador escriba sus especificaciones en su lengua materna o en inglés, que es el lenguaje estándar en proyectos internacionalizados. Aquí se usa inglés como lengua base y español como lengua adicional de trabajo. | When building programs it is natural for the programmer to write his specifications in his native language or English, which is the standard language for internationalized projects. Here English is used as the base language and Spanish as the other work language. |
Cuando en el archivo de configuración Doxygen se incluye la
opción
PREDEFINED
para definir una macro, Doxygen la usa luego para generar la
documentación. Usando esta habilidad de Doxygen es posible
definir un bloque de documentación para cada lenguaje,
poniendo el texto de la documentación encerrado dentro de
una pareja de
#ifdef - #endif
que corresponda a ese lenguaje.
|
When the Doxygen configuration file includes the
PREDEFINED
option to define a macro, Doxygen uses it to generate the
documentation. Using this Doxygen capability it is possible to
define a block of documentation for each language, putting the
documentation text surrounded by a
#ifdef - #endif
pair corresponding to that language.
|
#ifdef English_dox /// Defined by the C++ standard library. #endif #ifdef Spanish_dox /// Definido por la biblioteca estándar C++. #endif namespace std { } // trick to include it into the Doxygen documentation |
En la
Figura 1
está la documentación en inglés y en
español para el espacio de nombres "std ".
En este ejemplo, la macro
"English_dox " es la que marca el bloque de
documentación en inglés, mientras que la
macro "Spanish_dox " marca el bloque de
documentación en español. Aquí se nota que
este estilo de documentación puede tornarse muy pesado,
pues para documentar el simple renglón
"namespace std { } "
fue necesario utilizar 6 renglones de documentación. Por
eso, es natural tratar de evitar que tanta documentación
haga ilegible el código en los fuentes de los programas:
para la mayoría de los programadores es más sencillo
documentar en inglés los fuentes principales, y dejar en un
archivo aparte la documentación en español.
|
Figure 1
contains the documentation in English and Spanish for namespace
"std ". In this example, macro
"English_dox "
marks the English documentation block, while
macro "Spanish_dox " marks the Spanish
documentation block. Here we see that documenting style may become
very heavy, because to document the simple line
"namespace std { } "
6 lines of documentation were necessary. It is therefore natural
to try to prevent that so much documentation make program source
code unreadable: for most programmers is easier to document the
main sources in English, and leave in a separate file the Spanish
documentation.
|
// CSV.h (C) 2008 adolfo@di-mare.com // ... #ifdef English_dox /** Deletes \c ch when it is the trailing character in \c str. - The deleted character always is \c ch. \dontinclude test_CSV.cpp \skipline test::chop() \until }} \see test_CSV::test_chop() */ #endif void chop( std::string & str , char ch=0 ); // ... // EOF: CSV.h |
La Figura 2
es un trozo de código tomado del archivo
"CSV.h "
que contiene la
especificación para la función
"chop() ". Para evitar poner la documentación
en español dentro de este mismo archivo
"CSV.h " es necesario usar otro archivo en donde
incluirla.
|
Figure 2 is a piece of code taken from
file
"CSV.h "
that contains the
specification for function "chop() ". To avoid
putting the documentation in Spanish within the same file
"CSV.h " it is necessary to include it into another
file.
|
// CSV.es.h (C) 2008 adolfo@di-mare.com #ifdef Spanish_dox /// Documentación en español. #define Spanish_dox "Documentación en español" /// \def Spanish_dox ///< Marca bloques de documentación en español. #endif // ... /** \fn void chop( std::string & str , char ch=0 ); \brief Elimina \c ch si es el último caracter de \c str. - El caracter eliminado siempre es \c ch. \dontinclude test_CSV.cpp \skipline test::chop() \until }} \see test_CSV::test_chop() */ // ... // EOF: CSV.es.h |
El archivo
"CSV.es.h "
que se muestra en la
Figura 3 no contiene declaraciones C++ y
por eso nunca se usa para compilar el programa: sólo
contiene declaraciones de lo que Doxygen está documentando.
Debido a que todo lo documentado pertenece otros archivos, como
"CSV.h ", cada segmento de documentación debe
declarar qué es lo que documenta. En este caso, como lo que
se ha documentado es la función "chop() " es
necesario usar la declaración Doxygen "\fn "
con la firma exacta de la función documentada. La
descripción corta en español para esta
función es la que aparece en luego del comando Doxygen
"\brief ".
|
File "CSV.es.h "
shown in
Figure 3 does not contain C++ statements
and therefore it is never used to compile the program: it only
contains statements about whatever Doxygen is documenting. Because
everything being documented belongs to other files, as
"CSV.h ", each documentation segment must declare what
it documents. In this case, where what is being documented is
function "chop() ", it is necessary to use the
"\fn " Doxygen command with the exact signature of the
documented function. The short description in Spanish for this
function appears after the "\brief " Doxygen command.
|
Archivos de configuración Doxygen para cada lenguaje |
Configuration files for each language |
"CSV.cpp " es una biblioteca para leer y grabar
archivos en formato CSV (Comma Separated Value)
[RFC-4180]. Las especificaciones de las 2
funciones principales de esta biblioteca incluyen ejemplos que son
datos de prueba tomados del programa de prueba
"test_CSV.cpp ",
construido usando
"BUnit.h "
[DiM-2008]. Para compilar el programa de
prueba es necesario usar un proyecto que incluya estos 3 archivos:
"CSV.cpp " +
"CSV_line.cpp "
+ "test_CSV.cpp ". El compilador también
procesa los archivos de encabezado
".h "
correspondientes a estos fuentes: "CSV.h " +
"CSV_line.h ".
|
"CSV.cpp " is a library to read and write files in CSV
(Comma Separated Value) format
[RFC-4180]. The specifications for the 2
main functions in this library include examples that are test data
taken form test program
"test_CSV.cpp "
using
"BUnit.h "
[DiM-2008]. To compile the test program it
is necessary to use a project that includes these 3 files:
"CSV.cpp " +
"CSV_line.cpp "
+ "test_CSV.cpp ". The compiler also processes the
".h "
header files corresponding to those sources: "CSV.h "
+
"CSV_line.h ".
|
Sin embargo, al generar la documentación Doxygen en
inglés no es necesario usar los archivos en que está
la documentación en español. Por eso, en el archivo
de configuración Doxygen usado para generar la
documentación en inglés están mencionados los
mismos archivos que el compilador procesa:
|
However, to generate the Doxygen English documentation it is not
necessary to use the Spanish documentation files. Therefore, in
the Doxygen configuration file used to generate the English
documentation the files listed are the same files that the
compiler processes:
|
Además, en el archivo de configuración Doxygen debe
estar declarada la macro "English_dox " de manera que
Doxygen extraiga de los bloques marcados por esta macro la
documentación en inglés:
|
In addition, in the Doxygen configuration file macro
"English_dox " must be declared for Doxygen to extract
the English documentation form the blocks marked by this macro:
|
Para obtener la documentación en español es
necesario usar un archivo de configuración Doxygen
diferente. Una forma de lograrlo es crear un archivo con
extensión ".es.h " para cada uno de los
archivos fuentes en inglés: "CSV.h " →
"CSV.es.h " y "CSV_line.h " →
"CSV_line.es.h ". Es mejor usar la extensión
".es.h " en lugar de ".h.es " para que los
editores de texto procesen estos archivos destacando la
sintáxis. Desafortunadamente, si estos archivos de
documentación son mencionados, Doxygen los incluye como
parte de los archivos documentados. Por eso parece mejor
solución combinar todos estos archivos de
documentación en español en un sólo gran
archivo llamado "Spanish.txt ":
X:\SubDir\CSV> copy CSV_line.es.h+CSV.es.h Spanish.txt
|
To obtain the Spanish documentation it is necessary to use a
different Doxygen configuration file. One way to do this is to
create a file with extension ".es.h " for each English
source file: "CSV.h " → "CSV.es.h "
and
"CSV_line.h " → "CSV_line.es.h " It's
best to use the ".es.h " instead of
".h.es " so that text editors process these files with
syntax highlighting. It is unfortunate that if these documentation
files are mentioned, Doxygen will includes them as part of the
documented files. That is why it seems a better solution to
combine all these Spanish documentation files in one large file
called "Spanish.txt ":
X:\SubDir\CSV> copy CSV_line.es.h+CSV.es.h Spanish.txt
|
Usando este truco, toda las documentación en español
queda en el archivo "Spanish.txt " de donde luego
Doxygen la extraerá si en el archivo de
configuración "Spanish.dxg " contiene estas 2
sentencias:
|
Using this trick, all the Spanish documentation will be in file
"Spanish.txt " for Doxygen to extract if the
configuration file "Spanish.dxg " contains these 2
sentences:
|
En esta situación, para construir la documentación
en inglés se usa este comando:
X:\SubDir\CSV> doxygen test_CSV.dxg
|
In this situation, the English documentation gets built using this
command:
X:\SubDir\CSV> doxygen test_CSV.dxg
|
Para construir la documentación en español, el comando es el
siguiente:
X:\SubDir\CSV> doxygen Spanish.dxg
|
To build the Spanish documentation the command is the following:
X:\SubDir\CSV> doxygen Spanish.dxg
|
Comparación de configuraciones inglés vs. español |
Comparison of English vs. Spanish configurations |
Comparing files test_CSV.dxg and Spanish.dxg ***** test_CSV.dxg PROJECT_NAME = "CSV:" OUTPUT_LANGUAGE = English OUTPUT_DIRECTORY = . ***** Spanish.dxg PROJECT_NAME = "CSV:" OUTPUT_LANGUAGE = Spanish OUTPUT_DIRECTORY = . ***** ***** test_CSV.dxg INPUT = CSV.cpp CSV_line.cpp test_CSV.cpp \ CSV.h CSV_line.h RECURSIVE = NO ***** Spanish.dxg INPUT = CSV.cpp CSV_line.cpp test_CSV.cpp \ CSV.h CSV_line.h \ Spanish.txt # copy CSV_line.es.h+CSV.es.h Spanish.txt RECURSIVE = NO ***** ***** test_CSV.dxg PREDEFINED = "DOXYGEN_COMMENT" \ "English_dox" \ "__cplusplus" \ ***** Spanish.dxg PREDEFINED = "DOXYGEN_COMMENT" \ "Spanish_dox" \ "__cplusplus" \ ***** |
Las diferencias entre los 2 archivos de configuración
Doxygen que se muestran en la
Figura 4 se pueden obtener utilizando el
comando
"FC.exe ":
X:\SubDir\CSV> fc test_CSV.dxg Spanish.dxg
|
The differences between the 2 Doxygen configuration files shown in
Figure 4 can be obtained using the
"FC.exe " command :
X:\SubDir\CSV> fc test_CSV.dxg Spanish.dxg
|
Uso de un único archivo |
Using a single file |
En algunas ocasiones es más simple incluir al principio del archivo el código del programa C++ y al final toda la documentación Doxygen. Esta práctica tiene la ventaja de que es más sencillo producir la documentación, pues primero se crea un bloque de documentación vacío para todos los lenguajes para luego rellenarlo paulatinamente. | Sometimes it is easier to put the program code at the beginning of the C++ file and all Doxygen documentation at the end. This practice has the advantage that oftentimes it is easier to produce documentation creating first an empty documentation block for all languages to later fill them up gradually. |
// #1 #ifdef English_dox #endif #ifdef Spanish_dox #endif |
// #2 #ifdef English_dox /** \fn iterJava::hasNext() const; \brief Returns \c true if the iteration has more elements. (In other words, returns \c true if \c next() would return an element rather than breaking up.) \returns \c true if the iterator has more elements. */ #endif #ifdef Spanish_dox #endif /** \dontinclude test_iterJava.cpp \skipline test::next() \until }} \see test_iterJava::test_next() */ |
// #3 #ifdef English_dox /** \fn iterJava::hasNext() const; \brief Returns \c true if the iteration has more elements. (In other words, returns \c true if \c next() would return an element rather than breaking up.) \returns \c true if the iterator has more elements. */ #endif #ifdef Spanish_dox \fn iterJava::hasNext() const; \brief Retorna \c true si la iteración tiene más elementos. (En otras palabras, retorna \c true si \c next() retornaría un elemento en lugar de fallar.) \returns \c true si la iteración tiene más elementos. #endif /** \dontinclude test_iterJava.cpp \skipline test::next() \until }} \see test_iterJava::test_next() */ |
Detalles finales |
Final details |
// CSV.h (C) 2008 adolfo@di-mare.com #ifdef English_dox /// Doxygen English documentation. #define English_dox "Doxygen English documentation" /// \def English_dox ///< Macro used to have Doxygen generate English documentation. #endif #ifdef Spanish_dox /// Documentación en español. #define Spanish_dox "Documentación en español" /// \def Spanish_dox ///< Macro usado para que Doxygen genere documentación en español. #endif // ... // EOF: CSV.h |
Al principio del archivo de encabezado "CSV.h " se
usan tanto la macro "English_dox " como la macro
"Spanish_dox ". Aunque esto no es necesario para que
Doxygen documente correctamente, es bueno mencionar que la
documentación está disponible en estos 2 idiomas (aunque es
posible utilizar más idiomas).
|
At the beginning of header file "CSV.h " both macro
"English_dox " and macro "Spanish_dox "
are used. Even though this is not necessary for Doxygen to
document correctly, it is nice to mention that documentation is
available in these 2 languages (although it is possible to use
more languages).
|
En algunas ocasiones la documentación tiene sólo un renglón, como ocurre cuando se documentan los campos de una clase. En estos casos, es necesario poner la documentación fuera de la declaración de la clase, porque al dejarla dentro el código fuente queda difícil de leer. | Sometimes the documentation has only one line, as it happens when documenting the class fields. In these cases, it is necessary to put the documentation outside the class declaration, because leaving it inside makes source code harder to read. |
#ifdef English_dox /// Uses \c getNextCSV() to scan and store complete CSV lines. /// - Oftentimes it helps a lot to \c chop() out trailing CR+LF's. /// - This class is derived from std::vector<std::string> and has /// all vector operations and interfaces. #endif class CSV_line : public std::vector<std::string> { public: CSV_line(); CSV_line( const std::string & str ); CSV_line( const char *pz_str , size_t n=0 ); CSV_line( const CSV_line & ); void setData( const std::string & str ); void setData( const char *pz_str , size_t n=0 ); friend class test_CSV; }; #ifdef English_dox /// \class test_CSV; /// \brief Tests cases for \c CSV_line. #endif #ifdef English_dox /// Constructor. #endif inline CSV_line::CSV_line() { } |
En el ejemplo de la
Figura 6 la documentación de
"test_CSV " se pone afuera de la clase, lo mismo que
la del constructor, pues ponerla adentro mancharía mucho el
código.
|
In the example in
Figure 6 the documentation for
"test_CSV " is outside the class, just like the
constructor's, as leaving it inside stains the code a lot.
|
class CSV_line : public std::vector<std::string> { public: #ifdef English_dox /// Constructor. #endif CSV_line(); CSV_line( const std::string & str ); CSV_line( const char *pz_str , size_t n=0 ); CSV_line( const CSV_line & ); void setData( const std::string & str ); void setData( const char *pz_str , size_t n=0 ); #ifdef English_dox /// Tests cases for \c CSV_line. #endif friend class test_CSV; }; |
En la Figura 7 es fácil ver como queda de cargado el código fuente cuando se incluyen los bloques de documentación multi-lenguaje para Doxygen. Por eso, en general, es buena idea poner la documentación fuera de la clase. | In Figure 7 its easy to see how charged the source code becomes when multi-language Doxygen documentation blocks get included. Therefore, in general, it's a good idea to put the documentation outside the class. |
Conclusiones |
Conclusions |
Ya es bien sabido que Doxygen es una herramienta ideal para
documentar pues se usa en proyectos diversos y valiosos. Con un
pequeño esfuerzo es posible mantener la
documentación para varios lenguajes sin ensuciar demasiado
el código fuente. La forma de hacerlo incluye:
|
It is well known that Doxygen is an ideal tool for documenting
because it is used in several and valuable projects. With a little
effort it is possible to maintain documentation for several
languages without staining much the code. The way to do it
includes:
|
Agradecimientos |
Acknowledgements |
Alejandro Di Mare aportó varias observaciones y sugerencias importantes para mejorar este trabajo. | Alejandro Di Mare made several observations and important suggestions to improve this work. |
Código fuente |
Source code |
CSV.zip
:
[.zip]
http://www.di-mare.com/adolfo/p/CSV/CSV.zip
http://www.di-mare.com/adolfo/p/CSV/es/index.html
http://www.di-mare.com/adolfo/p/CSV/en/index.html
getNextCSV()
& setQuotedCSV()
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/CSV/es/CSV_8cpp.html
http://www.di-mare.com/adolfo/p/CSV/en/CSV_8cpp.html
CSV.h
:
[.spanish]
[.english]
[.h]
[.txt]
http://www.di-mare.com/adolfo/p/CSV/es/CSV_8h_source.html
http://www.di-mare.com/adolfo/p/CSV/en/CSV_8h_source.html
test_CSV.cpp
:
[.spanish]
[.english]
[.cpp]
[.txt]
http://www.di-mare.com/adolfo/p/CSV/es/classtest__CSV.html
http://www.di-mare.com/adolfo/p/CSV/en/classtest__CSV.html
test_CSV.dev
:
[.dev]
[.txt]
test_CSV.vcproj
:
[.vcproj]
[.txt]
CSV-Compilacion.txt
:
[.txt]
CSV-automata.jpg
:
[.jpg]
iterJava.zip
:
[.zip]
http://www.di-mare.com/adolfo/p/iterJava/iterJava.zip
http://www.di-mare.com/adolfo/p/iterJava/es/index.html
http://www.di-mare.com/adolfo/p/iterJava/en/index.html
.dxg
:
test_CSV.dxg
:
[.dxg]
[.txt]
Spanish.dxg
:
[.dxg]
[.txt]
Spanish.txt
: →
[[ copy
CSV_line.es.h+CSV.es.h Spanish.txt
]]
http://www.di-mare.com/adolfo/p/CSV/Spanish.txt
gcov
:
CSV.cpp.gcov
:
[.txt]
CSV_line.cpp.gcov
:
[.txt]
CSV_line.h.gcov
:
[.txt]
test_CSV.cpp.gcov
:
[.txt]
ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.5.6-setup.exe
Bibliografía |
Bibliography |
|
|
[DiM-2007] | Di Mare, Adolfo:
Uso de Doxygen para especificar módulos y programas,
Reporte Técnico ECCI-2007-02,
Escuela de Ciencias de la Computación e Informática,
Universidad de Costa Rica,
2007.
http://www.di-mare.com/adolfo/p/Doxygen.htm
|
[DiM-2008] | Di Mare, Adolfo:
BUnit.h : Un módulo simple para aprender prueba unitaria de programas en C++,
Reporte Técnico ECCI-2008-02,
Escuela de Ciencias de la Computación e Informática,
Universidad de Costa Rica,
2008.
http://www.di-mare.com/adolfo/p/BUnit.htm
|
[RFC-4180] | Shafranovich, Y.:
Common Format and MIME Type for Comma-Separated Values (CSV) Files,
Request for Comments: 4180,
IETF
The Internet Engineering Task Force,
Octubre 2005.
http://tools.ietf.org/html/rfc4180
|
[VH-2005] | van Heesch, Dimitri:
Doxygen,
2005.
http://www.doxygen.org/index.html
|
Indice |
Index |
|
|
Acerca del autor |
About the author |
Adolfo Di Mare: Investigador costarricense en la Escuela de Ciencias de la Computación e Informática [ECCI] de la Universidad de Costa Rica [UCR], en donde ostenta el rango de Profesor Catedrático. Trabaja en las tecnologías de Programación e Internet. Es Maestro Tutor del Stvdivm Generale de la Universidad Autónoma de Centro América [UACA], en donde ostenta el rango de Catedrático. Obtuvo la Licenciatura en la Universidad de Costa Rica, la Maestría en Ciencias en la Universidad de California, Los Angeles [UCLA], y el Doctorado (Ph.D.) en la Universidad Autónoma de Centro América. |
Adolfo Di Mare: Costarrican Researcher at the Escuela de Ciencias de la Computación e Informática [ECCI], Universidad de Costa Rica [UCR], where he is full professor. Works on Internet and programming technologies. He is Tutor at the Stvdivm Generale in the Universidad Autónoma de Centro América [UACA], where he is Cathedraticum. Obtained the Licenciatura at UCR, and the Master of Science in Computer Science from the University of California, Los Angeles [UCLA], and the Ph.D. at the Universidad Autónoma de Centro América. |
Acerca de este documento |
About this document |
Referencia: | Di Mare, Adolfo: Using Doxygen to generate Spanish and English documentation , Artículo #28 de la Sétima Conferencia del Latin American And Caribbean Consortium Of Engineering Institutions LACCEI-2009 (Consorcio de Escuelas de Ingeniería de Latinoamérica y del Caribe), realizado en la Universidad Nacional Experimental de Táchira (UNET) en San Cristóbal, Venezuela, junio 2009. |
Internet: |
http://www.di-mare.com/adolfo/p/DoxEsEn.htm
|
Autor: | Adolfo Di Mare
<adolfo@di-mare.com>
|
Contacto: | Apdo 4249-1000, San José Costa Rica Tel: (506) 2511-4020 Fax: (506) 2438-0139 |
Revisión: | ECCI-UCR, Junio 2009 |
Visitantes: |