Saltar a contenido

Práctica 2.5: Documentación del código

P2.5 - Documentación del código

En esta práctica vas a convertir un módulo Python pequeño en un programa más fácil de entender, utilizar y mantener. Partirás de un archivo con comentarios redundantes y funciones sin docstrings. Después describirás su contrato, añadirás documentación con formato Google Style, prepararás un README.md y comprobarás la documentación desde Python.

La actividad sigue la teoría de documentación del código en Python. El resultado esperado es un módulo ejecutable y documentado, acompañado de evidencias que permitan a otra persona comprender cómo usarlo sin tener que deducirlo leyendo cada instrucción.

1. Objetivos

  • Distinguir entre comentarios, docstrings, anotaciones de tipo y documentación de proyecto.
  • Documentar un módulo, sus funciones y su script de demostración con una convención coherente.
  • Explicar el propósito, los parámetros, el retorno, las excepciones y las restricciones de una interfaz pública.
  • Sustituir comentarios redundantes por nombres claros y comentarios que expliquen decisiones no evidentes.
  • Crear un README.md con requisitos, uso, ejemplos y limitaciones.
  • Consultar la documentación mediante __doc__, help() y pydoc, y probar los casos normales y frontera.

2. Relación con RA y criterios de evaluación

Código Descripción literal de la normativa
RA 3 Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje.
CE 3.g Se ha comentado y documentado el código.

Las evidencias se concretan así:

  • CE 3.g: los ejercicios 2.5.1 a 2.5.3 demuestran la documentación del módulo, las funciones y las decisiones no evidentes mediante comentarios y docstrings.
  • El ejercicio 2.5.4 y el README.md entregado documentan el proyecto, su uso, sus pruebas, sus limitaciones y las decisiones tomadas.
  • El ejercicio 2.5.5 demuestra que la documentación se mantiene actualizada después de modificar el código y volver a ejecutar las comprobaciones.

3. Requisitos y recursos

La práctica adopta Google Style para las docstrings. No mezcles en el mismo módulo las secciones Args y Returns con otra convención. Las anotaciones de tipo ayudan a entender la interfaz, pero no sustituyen la explicación del contrato ni la validación del código.

4. Pasos a seguir

4.1. Preparar el módulo de trabajo

  1. Crea una carpeta llamada practica_u2_5_documentacion y, dentro de ella, crea los archivos temperaturas.py y README.md. El primero contendrá el código; el segundo recogerá el uso y las evidencias de la práctica.

  2. Copia el siguiente punto de partida en temperaturas.py. El programa es ejecutable, pero sus funciones todavía no explican bien su contrato y sus comentarios repiten parte del código.

    """Herramientas para analizar las temperaturas de una jornada."""
    
    
    def calcular_promedio(temperaturas: list[float]) -> float:
        # Comprobamos si la lista está vacía.
        if not temperaturas:
            raise ValueError("Debe haber al menos una temperatura.")
    
        # Sumamos las temperaturas y dividimos entre la cantidad.
        return sum(temperaturas) / len(temperaturas)
    
    
    def clasificar_temperatura(temperatura: float) -> str:
        # Comprobamos el rango de la temperatura.
        if temperatura < 0:
            return "helada"
        if temperatura <= 10:
            return "fría"
        if temperatura <= 20:
            return "templada"
        if temperatura <= 30:
            return "cálida"
        return "calurosa"
    
    
    def es_temperatura_extrema(temperatura: float) -> bool:
        # Comprobamos si la temperatura es extrema.
        return temperatura < -10 or temperatura > 40
    
    
    def main() -> None:
        # Guardamos unas lecturas de ejemplo.
        temperaturas = [8.0, 18.5, 36.0]
        promedio = calcular_promedio(temperaturas)
    
        print(f"Promedio: {promedio:.2f} °C")
        for temperatura in temperaturas:
            categoria = clasificar_temperatura(temperatura)
            extrema = es_temperatura_extrema(temperatura)
            print(f"{temperatura:.1f} °C: {categoria}; extrema: {extrema}")
    
    
    if __name__ == "__main__":
        main()
    
  3. Ejecuta el programa antes de modificarlo y anota en el README.md la salida obtenida. Así separarás los cambios de documentación de los cambios de comportamiento.

    python temperaturas.py
    

4.2. Analizar el contrato y las personas destinatarias

  1. Lee el código y escribe en el README.md quién puede necesitar esta información: una persona que importa las funciones, alguien que mantiene el módulo y quien ejecuta el script de ejemplo.

  2. Antes de escribir las docstrings, anota el contrato de cada función: entradas, resultado, error previsto, unidades y límites. Por ejemplo, calcular_promedio no acepta una lista vacía y las temperaturas se expresan en grados Celsius.

  3. Decide qué información pertenece al módulo, a una función o al README: el propósito general va en la docstring del módulo, el contrato de una función va junto a su definición y la instalación o la forma de ejecutar el proyecto va en el README.

4.3. Añadir docstrings y anotaciones útiles

  1. Amplía la docstring del módulo para indicar su propósito, la unidad de las temperaturas, las funciones públicas que ofrece y el alcance de sus umbrales. No describas cada línea del archivo.

  2. Añade una docstring Google Style a calcular_promedio. Debe incluir un resumen en la primera línea, Args, Returns y Raises. Como orientación, la estructura mínima es la siguiente:

    def calcular_promedio(temperaturas: list[float]) -> float:
        """Calcula el promedio de una colección de temperaturas.
    
        Args:
            temperaturas: Valores expresados en grados Celsius.
    
        Returns:
            El promedio de las temperaturas recibidas.
    
        Raises:
            ValueError: Si la colección está vacía.
        """
    
  3. Documenta clasificar_temperatura indicando los intervalos exactos y los textos que devuelve. Documenta también es_temperatura_extrema, incluidos los límites estrictos -10 y 40, y main, que muestra una demostración por consola sin recibir argumentos.

  4. Comprueba que todas las funciones tienen anotaciones de tipo completas. Las anotaciones informan del tipo esperado, pero la docstring debe aclarar unidades, restricciones y posibles excepciones.

  5. Mantén una sola convención de docstrings y revisa que el resumen de cada una empiece con un verbo en tercera persona: «Calcula», «Clasifica», «Indica» o una forma equivalente.

4.4. Revisar comentarios y crear el README.md

  1. Elimina los comentarios que solo traducen una instrucción, como «sumamos las temperaturas» antes de sum(). Conserva o sustituye esos comentarios por una explicación del porqué cuando el código no exprese por sí mismo una decisión.

  2. Añade, como máximo, un comentario breve que explique una decisión de dominio no evidente: por ejemplo, que los umbrales de temperatura son un criterio didáctico del ejercicio y no una alerta médica. No comentes cada línea.

  3. Completa README.md con estos apartados: propósito, requisitos, ejecución, ejemplo de salida, funciones disponibles, decisión sobre los umbrales, casos de prueba y limitaciones. Incluye los comandos que has ejecutado y los resultados relevantes.

  4. En el ejemplo de uso del README, muestra al menos una importación de una función y explica qué devuelve. No incluyas contraseñas, rutas personales ni datos que no sean necesarios para reproducir la actividad.

4.5. Consultar la documentación y probar el comportamiento

  1. Ejecuta de nuevo el script y comprueba que la documentación no ha cambiado el comportamiento del programa.

  2. Desde la carpeta del proyecto, consulta la docstring y la ayuda de Python. Guarda en el README una breve observación sobre la información que aparece.

    python -c "import temperaturas; print(temperaturas.__doc__)"
    python -c "import temperaturas; help(temperaturas.calcular_promedio)"
    python -m pydoc temperaturas
    
  3. Prueba, como mínimo, los valores -11, -10, 0, 10, 20, 30, 40 y 41 en clasificar_temperatura y es_temperatura_extrema. Prueba también una lista normal y una lista vacía en calcular_promedio.

  4. Comprueba en el README que el resultado esperado y el resultado obtenido coinciden. Si aparece un ValueError previsto, explica su causa y verifica que la docstring lo documenta en Raises.

4.6. Simular una modificación mantenible

  1. Cambia las temperaturas de ejemplo de main para incluir -11.0 y 41.0. Ejecuta el programa y actualiza el ejemplo de salida del README para que siga siendo verdadero.

  2. Relee las docstrings, el comentario de los umbrales y la sección de pruebas. Si alguna explicación ya no coincide con el programa, corrígela.

  3. Ejecuta una última vez el módulo y pydoc. Esta revisión representa una tarea habitual de mantenimiento: cambiar código y documentación en el mismo trabajo.

5. Comprobaciones de finalización

  • temperaturas.py se ejecuta con python temperaturas.py sin errores.
  • La docstring del módulo explica propósito, unidad de medida, funciones públicas y alcance del ejemplo.
  • Las cuatro funciones tienen anotaciones de tipo y docstrings coherentes; las funciones que pueden fallar describen ValueError en Raises.
  • Las docstrings mantienen Google Style y explican parámetros, retorno y restricciones sin copiar literalmente la implementación.
  • Los comentarios redundantes se han eliminado y queda, como máximo, una explicación breve de una decisión no evidente.
  • Se han probado los límites -11, -10, 0, 10, 20, 30, 40 y 41, además de una lista vacía para el promedio.
  • __doc__, help() y pydoc muestran información útil y legible.
  • README.md contiene propósito, requisitos, ejecución, ejemplo, API, pruebas, limitaciones y la observación sobre la modificación final.
  • El ejemplo de salida del README coincide con el programa después de añadir las lecturas -11.0 y 41.0.

6. Ejercicios y entregables

  1. Ejercicio 2.5.1 — Documentar el módulo. Amplía la docstring de temperaturas.py para que una persona recién incorporada al proyecto entienda su finalidad y alcance sin leer la implementación.

  2. Ejercicio 2.5.2 — Documentar la API. Escribe las docstrings de calcular_promedio, clasificar_temperatura, es_temperatura_extrema y main con Google Style. Describe los límites exactos y el ValueError previsto.

  3. Ejercicio 2.5.3 — Comentar decisiones. Elimina comentarios redundantes y conserva una explicación del criterio de los umbrales solo si aporta una información que no se deduce del código.

  4. Ejercicio 2.5.4 — Documentar el proyecto. Completa el README.md con propósito, requisitos, uso, ejemplo, API, pruebas, decisiones y limitaciones. Incluye las observaciones de __doc__, help() y pydoc.

  5. Ejercicio 2.5.5 — Mantener la documentación. Añade las temperaturas -11.0 y 41.0 al ejemplo, actualiza la salida del README y corrige toda explicación que haya quedado desactualizada.

  6. Entregables. Entrega temperaturas.py y README.md. El README debe incluir tu nombre o identificador, los comandos ejecutados, los casos probados, los resultados esperados y obtenidos, y las decisiones tomadas. No es necesario entregar el HTML generado temporalmente por pydoc.

7. Solución orientativa

Una solución correcta no se mide por la cantidad de comentarios, sino por la información que aporta cada explicación. El código debe seguir funcionando igual después de documentarlo y una persona lectora debe poder usar las funciones sin inspeccionar su implementación.

Elemento Información que debería aparecer
Módulo Propósito, unidad Celsius, funciones disponibles y alcance didáctico de los umbrales.
calcular_promedio Lista de temperaturas, promedio devuelto, ValueError para lista vacía y ausencia de efectos secundarios.
clasificar_temperatura Intervalos ordenados y etiquetas helada, fría, templada, cálida y calurosa.
es_temperatura_extrema Es extrema si es menor que -10 o mayor que 40; los valores -10 y 40 no son extremos.
main Ejecuta una demostración con las lecturas del ejemplo y muestra el resultado por consola.
README.md Propósito, requisitos, ejecución, ejemplo, API, pruebas, límites, decisiones y limitaciones.

Una docstring de función puede seguir este patrón, adaptándolo al contrato real:

def es_temperatura_extrema(temperatura: float) -> bool:
    """Indica si una temperatura queda fuera del intervalo normal.

    Args:
        temperatura: Valor expresado en grados Celsius.

    Returns:
        `True` si la temperatura es menor que -10 o mayor que 40;
        en otro caso, `False`.
    """
    return temperatura < -10 or temperatura > 40

Para contrastar el resultado, revisa especialmente que -10 y 40 no se marquen como extremos, que la lista vacía produzca el error documentado y que el README se haya actualizado después de cambiar las lecturas de ejemplo. No se exige copiar esta implementación ni este texto literalmente: se evalúan la precisión del contrato, la coherencia de la convención y la calidad de las evidencias.

8. Fuentes y referencias