Escrito por Lino Urdaneta para qu4nt
Documentar un código no es un asunto trivial. Hace siglos, algunos filósofos del estoicismo llegaron a la conclusión de que todo lo que tiene un comienzo, tiene también un final, y que después de este final inevitablemente había un nuevo comienzo. Siglos después, Nietzsche sugirió que ese nuevo comienzo tenía por fuerza que idéntico al anterior, y que la historia no hacía sino repetirse de forma aburrida e incesante. Jorge Luis Borges fantaseaba con un universo que ser repite a sí mismo de vez en cuando por culpa de su finitud:
El número de todos los átomos que componen el mundo es, aunque desmesurado, finito, y sólo capaz como tal de un número finito (aunque desmesurado también) de permutaciones. En un tiempo infinito, el número de las permutaciones posibles debe ser alcanzado, y el universo tiene que repetirse. De nuevo nacerás de un vientre, de nuevo crecerá tu esqueleto, de nuevo arribará esta misma página a tus manos iguales, de nuevo cursaras todas las horas hasta la de tu muerte increíble. (Jorge Luis Borges, La doctrina de los ciclos)
Sean o no válidos estos razonamientos, lo cierto es que muchas veces (demasiadas) tendemos a hacer borrón y cuenta nueva, y lo hacemos por las razones más diversas. Una muy común (por lo menos para mí) se da cuando reviso algún código que escribí hace mucho tiempo: ¿Qué es lo que se supone que hace esta función? Ya no me acuerdo… Otras veces comenzamos de cero (de nuevo) porque no entendemos el código de otro: Le doy vueltas y vueltas a esto y mientras más lo leo, menos lo entiendo. Mejor me olvido de esto y empiezo mi propio script. Estas son dos situaciones que se pueden evitar con facilidad si el código es legible y cuenta con una adecuada documentación.
El maratón versus el sprint
Si tenemos un proyecto muy pequeño entre manos, y muy muy poco tiempo para llevarlo a término, es muy posible que documentar adecuadamente esté fuera de la ecuación. Pero si lo que tenemos por delante es un proyecto medio o grande, documentarlo es la mejor — la única — opción. De otra manera, llegar a la meta no serán sino una serie de sprints desordenados direcciones muchas veces opuestas. Y lo peor de todo es que pasaremos horas tratando de descifrar qué quisimos resolver con una función, o volviendo a diseñar una clase que hizo el desarrollador que renunció el mes pasado. Mordiéndonos la cola, como el Uróboros.
Código limpio
El código bien documentado comienza con un código limpio. Para ello un experto como Robert C. Martin (el célebre tío Bob) recomienda:
- Usar el nombre adecuado: este nombre debe ser descriptivo, por sí mismo, de qué hacen, y por qué, las variables, clases, métodos, funciones, etc.
- Las funciones deben hacer una única cosa, y deben hacerla bien.
- Los comentarios deben mantenerse al mínimo. Si se necesita comentar frecuentemente un código, entonces algo se está haciendo mal.
- Debe ponerse atención al formato, tanto horizontal como vertical, del código.
Estos consejos pueden hacer toda la diferencia entre un flujo de trabajo eficiente y un desastre total. Contribuyen, además, a la posibilidad de crear una documentación coherente.
La guía de estilo (PEP8)
Una guía de estilo trata sobre consistencia. La consistencia con esta guía de estilo es importante. La consistencia con un proyecto es más importante. La consistencia con un módulo o función es lo más importante (PEP 8 — Style Guide for Python Code)
Python viene con su propia guía de estilo, llamada PEP-8 (https://www.python.org/dev/peps/pep-0008/). PEP-8 es un recurso muy útil ya que impone cierto acuerdo entre los programadores de Python, facilitando la legibilidad del código en general. PEP-8 incluye sugerencias relacionadas con:
- La indentación correcta: 4 espacios (nada de tabulaciones).
- La extensión de una línea de código (no más de 79 caracteres).
- La separación de fragmentos de código por medio de líneas en blanco.
- Formato de la importación de librerías y módulos.
- Uso apropiado de los comentarios.
- Convenciones en los nombres utilizados.
- Sugerencias varias sobre funciones, clases y variables.
Adherirse a una guía de estilo es muy importante. Sea a PEP-8 o a la que te sugiera tu organización. Esto permite programar más rápido porque muchas decisiones de formato se hacen de forma automática. También hace más sencilla la corrección del código.
Documentación dentro y fuera del código
Mantener un código ordenado y seguir una guía de estilo son los pilares sobre los que se puede sustentar una buena documentación. En este punto vamos a hacer una distinción entre la documentación en el código y la documentación técnica. La primera describe el código desde dentro y está compuesta por los comentarios (hechos por desarrolladores para desarrolladores) y los docstrings (texto ligado a funciones, métodos, clases, módulos, paquetes, entre otros).
Documentación en el código
En Python, los comentarios empiezan con # y sirven para planificar la estructura del código, indicar de forma permanente o temporal algún fragmento de código en el que se esté trabajando, explicar el algoritmo utilizado, dar información legal, indicar el autor del script y otras muchas funciones.
Los docstrings, por otra parte, se emplean para darle información al usuario o desarrollador sobre el uso de algún objeto en Python. Si quisiéramos ver la “ayuda” sobre el objeto dict en Python, podríamos escribir lo siguiente en el intérprete:
>>> help(dict)
Lo que nos devolvería un docstring relacionado con dicho objeto. Ya Python trae incluidos los docstrings básicos, pero podemos — y debemos — crear nuestras propias cadenas de documentación para cada objeto que diseñemos.
Documentación técnica
La documentación técnica va un paso más allá y relaciona el código con el lenguaje ordinario, para crear un tipo de texto híbrido en el que nos apoyamos cuando queremos comprender qué hace una determinada función, o qué podemos esperar de un atributo particular. Para la documentación técnica asumimos más el rol de un escritor que el de un programador.
Nos acercamos a la documentación técnica cuando queremos aprender a utilizar un nuevo framework, o cuando estamos aprendiendo los rudimentos de un lenguaje de programación. Este tipo de documentación nos cuenta el porqué de algunas decisiones, nos da consejos, y nos indica vías seguras o rápidas de resolver problemas. Incluye además, normalmente, lo documentado dentro del código.
Podemos encontrar este tipo de documentación en la mayoría de los proyectos de GitHub, GitLab, frameworks, librerías. Esto podemos constatarlo visitando uno de los sitios de documentación más importantes en la actualidad: Read the Docs. Básicamente, cada proyecto importante tiene su propia documentación:
Y ese será el lugar al que vamos cuando tenemos dudas, o queremos comprender mejor alguna funcionalidad. Se puede desarrollar la mejor librería del planeta, pero sin la documentación adecuada serán muy pocos los usuarios o desarrolladores lo suficientemente pacientes para utilizarla.
Primeros pasos con Sphinx
Para documentar nuestro código apropiadamente, vamos a usar la herramienta adecuada. Sphinx es un paquete que se encargará del trabajo pesado de organizar la información, extraerla de los lugares adecuados, y presentarla en un bonito HTML o PDF (o en algún otro formato). Esto te permitirá concentrarte más en el contenido que en el formato. Sphinx es, además, el estándar para elaborar la documentación técnica en Python. Vamos a por ello.
Instalación de Sphinx
La instalación de Sphinx dependerá del sistema operativo que estés utilizando. Si ya tienes instalado Python, puedes descargar e instalar Sphinx utilizando pip:
$ pip install -U sphinx
Puedes comprobar que Sphinx funciona correctamente con
$ python -c 'import sphinx'
Si no hay errores, no verás nada como respuesta.
Creación del directorio de trabajo
Debes crear un nuevo directorio para poner la estructura de archivos que necesita Sphinx para organizar un proyecto. Por lo general existe la convención de llamarlo, simplemente, doc. Entra en ese directorio.
Una vez allí, se creará la estructura utilizando el comando
$ sphinx-quickstart
Este comando te preguntará algunas cosas para configurar apropiadamente el proyecto. Vamos a escoger, para empezar, las opciones que nos da por defecto. Lo que sí es imprescindible es indicar el nombre del autor y el nombre del proyecto, ya que ambos aparecerán en varias partes de la documentación.
Sphinx se encargará de crear varios archivos de configuración y de directorios vacíos que serán utilizados más adelante. Deberías ver algo como esto:
$ ls -R
Makefile
_static
conf.py
make.bat
_build
_templates
index.rst
¡Ya está listo todo para empezar a documentar!
Los directorios que comienzan con underscore son aquellos que tendrán archivos generados por Sphinx (como los documentos en HTML para tu página web de documentación). El archivo Makefile se utilizará, como veremos, para automatizar el proceso de generación de la documentación. Otro archivo clave es index.rst (llamado master document) el cual servirá como página de bienvenida a la documentación, así como también de índice de tus archivos de documentación.
Introducir los archivos de documentación
¿Dónde ponemos nuestros archivos de documentación? Podemos hacerlo en cualquier sitio, pero lo más conveniente es crear sub-directorios dentro del directorio que tiene el conf.py. Puedes crear, por ejemplo, un directorio tutorials/ para los tutoriales, y otro distinto para la documentación de los docstrings. Una vez tengas una estructura de directorios lista, puedes copiar tus archivos en ellos.
Pero, ¿qué formato deben tener esos archivos?
Sphinx utiliza como source archivos tipo .rst creados con un lenguaje de marcas denominado reStructuredText (o simplemente reST). Se trata de un tipo de formato similar a markdown, pero con una serie de marcas ampliadas especialmente diseñadas para facilitar el trabajo de documentación automática de código. Puedes encontrar más información en la documentación de Sphinx. Aquí va un ejemplo del formato:
Otra opción que te puede resultar de utilidad si ya tienes documentos en markdown es utilizar pandoc para convertirlos automáticamente. Puedes utilizar el siguiente comando (siempre y cuando hayas instalado pandoc):
$ pandoc archivo_origen.md -f markdown -t rst -s -o archivo_destino.rst
(Recuerda poner las rutas de los archivos si están en distintas locaciones.)
reST es extensible gracias a las directivas. No vamos a tocar este tema en este artículo, pero podrás encontrar más información en la documentación de Sphinx (¿ves lo importante que es documentar?).
Preparar el índice de los documentos
Cuando tengamos nuestro contenido organizado y escrito en archivos .rst, debemos indicarle a Sphinx dónde debe buscar los documentos. Para ello, edita el archivo index.rst (está en la raíz de tu proyecto de documentación) e introduce los archivos de documentación con su ruta relativa. Los archivos debe ir dentro de la directiva .. toctree::, debajo de :caption: Contents: (recuerda respetar la indentación). Aquí va un ejemplo:
Con ello, ya Sphinx sabrá dónde debe buscar nuestro contenido. Y no solo eso, sino que lo organizará en una tabla de contenidos donde podremos navegar por toda nuestra documentación. El siguiente paso será crear una página web para ver todo bonito y sin marcas.
Convertir la documentación a HTML
Crear una versión HTML de la documentación es muy sencillo. Solo tienes que correr el siguiente comando desde la ruta donde está el Makefile:
$ make html
¡Eso es todo! Podrás ver el resultado en la ruta _build/html/index.html. Si quieres ver el resultado en tu navegador, usa tu explorador de archivos para encontrar el index.html y haz doble clic. O escribe la ruta absoluta al archivo en tu navegador. Verás algo más o menos como esto:
Si no te gusta el aspecto de la página, puedes probar con cualquiera de los temas que puedes encontrar en https://sphinx-themes.org. Te recomendamos especialmente los que aparecen aquí. También puedes personalizar los colores, tipos de letra, etc.
Con eso terminamos. Sphinx, además de facilitar la organización y exportación a otros formatos de tu documentación, también puede aprovechar los docstrings para construir un listado de todas las funciones, métodos, clases, etc. de nuestro código. Se trata de funciones más avanzadas de documentación, pero que Sphinx realiza para nosotros de forma muy cómoda.
Con una buena documentación, y un código limpio, no habrá que empezar de nuevo desde cero. Y los desarrolladores y usuarios de tu código te lo agradecerán: no más eterno retorno.