Ir al contenido principal

Comentarios y documentación en Java

Introducción

La documentación adecuada del código es una práctica esencial en el desarrollo de software profesional. En Java, los comentarios y la documentación no solo ayudan a explicar el funcionamiento del código, sino que también pueden utilizarse para generar documentación técnica automáticamente. Un código bien documentado es más fácil de mantener, depurar y compartir con otros desarrolladores.

En este artículo, exploraremos las diferentes formas de añadir comentarios en Java, cómo utilizar Javadoc para generar documentación automática y las mejores prácticas para documentar nuestro código de manera efectiva y profesional.

Tipos de comentarios en Java

Java ofrece tres tipos de comentarios, cada uno con un propósito específico:

1. Comentarios de una línea

Los comentarios de una línea comienzan con dos barras diagonales (//) y se extienden hasta el final de la línea. Son ideales para explicaciones breves:

// Este es un comentario de una línea
int contador = 0; // También se puede poner al final de una instrucción

2. Comentarios de múltiples líneas

Los comentarios de múltiples líneas (o comentarios de bloque) comienzan con /* y terminan con */. Todo el texto entre estos delimitadores se considera un comentario:

/* Este es un comentario
   que abarca múltiples líneas.
   Útil para explicaciones más extensas. */
   
int resultado = 100;

/* También se puede usar
 * con asteriscos al inicio de cada línea
 * para mejorar la legibilidad
 */

3. Comentarios de documentación (Javadoc)

Los comentarios de documentación comienzan con /** y terminan con */. Son especiales porque pueden procesarse por la herramienta Javadoc para generar documentación en formato HTML:

/**
 * Esta clase representa un cliente del banco.
 * Contiene información personal y métodos para gestionar su cuenta.
 *
 * @author Miguel Sánchez
 * @version 1.0
 */
public class Cliente {
    // Código de la clase...
}

Uso efectivo de comentarios regulares

Cuándo usar comentarios

Los comentarios regulares (// y /* */) son útiles para:

  1. Explicar decisiones de diseño no obvias
  2. Aclarar secciones complejas de código
  3. Marcar código temporal o que necesita revisión
  4. Deshabilitar temporalmente fragmentos de código durante la depuración
// IMPORTANTE: No modificar este valor, afecta al cálculo de impuestos
final double TIPO_IVA = 0.21;

/* 
 * Algoritmo de ordenación personalizado.
 * Se utiliza este enfoque en lugar de Collections.sort() 
 * porque necesitamos preservar el orden de elementos iguales.
 */
private void ordenarElementos() {
    // Implementación del algoritmo...
}

// TODO: Refactorizar este método para mejorar rendimiento
public void procesarDatos() {
    // Código pendiente de optimizar...
}

// Código comentado para pruebas
// if (condicion) {
//     hacerAlgo();
// }

Evitar comentarios innecesarios

Un buen código debe ser autoexplicativo en la medida de lo posible. Evita comentarios que simplemente repiten lo que el código ya dice:

// Mal ejemplo: comentario innecesario
// Incrementa contador en 1
contador++;

// Buen ejemplo: solo cuando añade contexto
// Incrementa contador para rastrear intentos fallidos de login
intentosFallidos++;

Documentación con Javadoc

Javadoc es una herramienta incluida en el JDK que genera documentación en formato HTML a partir de los comentarios de documentación en el código fuente.

Etiquetas Javadoc

Javadoc utiliza etiquetas especiales que comienzan con @ para estructurar la documentación:

Etiqueta Uso Descripción
@param @param nombreParametro descripción Documenta un parámetro del método
@return @return descripción Documenta el valor de retorno del método
@throws @throws NombreExcepcion descripción Documenta una excepción que puede lanzar el método
@author @author nombre Indica el autor del código
@version @version numero Indica la versión del código
@see @see referencia Añade un enlace a otra clase o método
@since @since version Indica desde qué versión está disponible
@deprecated @deprecated motivo Marca el código como obsoleto

Ejemplo de documentación de clase

/**
 * Representa una cuenta bancaria con operaciones básicas.
 * 
 * <p>Esta clase permite realizar operaciones como depósitos,
 * retiradas y consultas de saldo en una cuenta bancaria.</p>
 * 
 * @author Juan Pérez
 * @version 2.1
 * @since 1.0
 */
public class CuentaBancaria {
    // Atributos y métodos...
}

Ejemplo de documentación de método

/**
 * Realiza una transferencia de dinero entre dos cuentas.
 * 
 * <p>El método verifica que la cuenta origen tenga fondos suficientes
 * antes de realizar la transferencia.</p>
 * 
 * @param cuentaOrigen cuenta desde la que se transfiere el dinero
 * @param cuentaDestino cuenta que recibe el dinero
 * @param cantidad monto a transferir
 * @return true si la transferencia se realizó correctamente
 * @throws SaldoInsuficienteException si la cuenta origen no tiene saldo suficiente
 * @throws CuentaInactivaException si alguna de las cuentas está inactiva
 * @see CuentaBancaria#getSaldo()
 */
public boolean transferir(CuentaBancaria cuentaOrigen, 
                          CuentaBancaria cuentaDestino, 
                          double cantidad) throws SaldoInsuficienteException,
                                                CuentaInactivaException {
    // Implementación del método...
}

Ejemplo de documentación de campo

/**
 * Número único de identificación de la cuenta.
 * Este número se asigna automáticamente y no puede modificarse.
 */
private final String numeroCuenta;

Generación de documentación HTML

Para generar la documentación HTML utilizando Javadoc, ejecuta el siguiente comando desde la línea de comandos:

javadoc -d docs -author -version MiClase.java

Donde:

  • -d docs: especifica el directorio de salida para los archivos HTML
  • -author -version: incluye la información de autor y versión
  • MiClase.java: el archivo fuente a documentar

Mejores prácticas de documentación

1. Documenta el "por qué", no solo el "qué"

El código ya muestra qué hace, los comentarios deberían explicar por qué:

// Mal ejemplo: describe lo obvio
// Establece contador a cero
contador = 0;

// Buen ejemplo: explica el motivo
// Reiniciamos el contador cada día para cumplir con la normativa de auditoría
contador = 0;

2. Mantén sincronizados código y comentarios

Cuando modifiques el código, actualiza también los comentarios relacionados. Un comentario desactualizado es peor que la ausencia de comentario:

// Este método devuelve el saldo en euros
// COMENTARIO DESACTUALIZADO: ahora devuelve el saldo en dólares
public double getSaldo() {
    return saldoDolares;
}

3. Utiliza un estilo consistente

Mantén un estilo de comentarios uniforme en todo el proyecto:

/** 
 * Estilo consistente para comentarios Javadoc.
 * Siempre con asteriscos alineados y primera letra mayúscula.
 */

4. Documenta APIs públicas completamente

Todos los métodos y clases públicos deben tener documentación Javadoc completa:

/**
 * Método sin documentación adecuada.
 */
public void metodoMalDocumentado(String param) {
    // Código...
}

/**
 * Crea un nuevo usuario en el sistema.
 * 
 * @param nombre nombre completo del usuario
 * @return el ID generado para el nuevo usuario
 * @throws DuplicadoException si ya existe un usuario con ese nombre
 */
public int crearUsuario(String nombre) throws DuplicadoException {
    // Código...
}

Ejemplo práctico: Clase bien documentada

Veamos un ejemplo completo de una clase con documentación apropiada:

/**
 * Representa un producto en el inventario de una tienda.
 * 
 * <p>Esta clase contiene información sobre un producto como
 * su código, nombre, precio y cantidad en stock, así como
 * métodos para gestionar dicho inventario.</p>
 * 
 * @author Laura Gómez
 * @version 1.2
 * @since 1.0
 */
public class Producto {
    
    /**
     * Código único que identifica al producto.
     */
    private final String codigo;
    
    /**
     * Nombre descriptivo del producto.
     */
    private String nombre;
    
    /**
     * Precio actual del producto en euros.
     */
    private double precio;
    
    /**
     * Cantidad disponible en el inventario.
     */
    private int stock;
    
    /**
     * Categoría a la que pertenece el producto.
     * @since 1.1
     */
    private String categoria;
    
    /**
     * Crea un nuevo producto con los datos especificados.
     * 
     * @param codigo código único del producto
     * @param nombre nombre del producto
     * @param precio precio inicial en euros
     * @param stock cantidad inicial en inventario
     * @throws IllegalArgumentException si el precio o el stock son negativos
     */
    public Producto(String codigo, String nombre, double precio, int stock) {
        // Validaciones
        if (precio < 0) {
            throw new IllegalArgumentException("El precio no puede ser negativo");
        }
        if (stock < 0) {
            throw new IllegalArgumentException("El stock no puede ser negativo");
        }
        
        // Inicialización
        this.codigo = codigo;
        this.nombre = nombre;
        this.precio = precio;
        this.stock = stock;
        this.categoria = "General"; // Categoría por defecto
    }
    
    /**
     * Actualiza el precio del producto.
     * 
     * @param nuevoPrecio nuevo precio en euros
     * @return true si el precio se actualizó correctamente
     * @throws IllegalArgumentException si el nuevo precio es negativo
     */
    public boolean actualizarPrecio(double nuevoPrecio) {
        if (nuevoPrecio < 0) {
            throw new IllegalArgumentException("El precio no puede ser negativo");
        }
        
        // Solo registramos el cambio si es diferente al precio actual
        if (this.precio != nuevoPrecio) {
            // En un caso real, aquí podríamos registrar el cambio en un log
            this.precio = nuevoPrecio;
            return true;
        }
        return false;
    }
    
    /**
     * Añade unidades al inventario.
     * 
     * @param cantidad unidades a añadir
     * @throws IllegalArgumentException si la cantidad es negativa
     */
    public void aumentarStock(int cantidad) {
        if (cantidad < 0) {
            throw new IllegalArgumentException("La cantidad debe ser positiva");
        }
        this.stock += cantidad;
    }
    
    /**
     * Reduce unidades del inventario.
     * 
     * @param cantidad unidades a retirar
     * @return true si hay suficiente stock, false en caso contrario
     * @throws IllegalArgumentException si la cantidad es negativa
     */
    public boolean reducirStock(int cantidad) {
        if (cantidad < 0) {
            throw new IllegalArgumentException("La cantidad debe ser positiva");
        }
        
        if (cantidad > this.stock) {
            // No hay suficiente stock
            return false;
        }
        
        this.stock -= cantidad;
        return true;
    }
    
    /**
     * Devuelve el código del producto.
     * 
     * @return código único del producto
     */
    public String getCodigo() {
        return this.codigo;
    }
    
    /**
     * Devuelve el nombre del producto.
     * 
     * @return nombre descriptivo
     */
    public String getNombre() {
        return this.nombre;
    }
    
    /**
     * Establece un nuevo nombre para el producto.
     * 
     * @param nombre nuevo nombre
     */
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    
    /**
     * Devuelve el precio actual del producto.
     * 
     * @return precio en euros
     */
    public double getPrecio() {
        return this.precio;
    }
    
    /**
     * Devuelve la cantidad disponible en inventario.
     * 
     * @return unidades en stock
     */
    public int getStock() {
        return this.stock;
    }
    
    /**
     * Comprueba si el producto está disponible en inventario.
     * 
     * @return true si hay al menos una unidad en stock
     */
    public boolean estaDisponible() {
        return this.stock > 0;
    }
    
    /**
     * Establece la categoría del producto.
     * 
     * @param categoria nueva categoría
     * @since 1.1
     */
    public void setCategoria(String categoria) {
        this.categoria = categoria;
    }
    
    /**
     * Devuelve la categoría del producto.
     * 
     * @return categoría actual
     * @since 1.1
     */
    public String getCategoria() {
        return this.categoria;
    }
    
    /**
     * Devuelve una representación textual del producto.
     * 
     * @return cadena con la información básica del producto
     */
    @Override
    public String toString() {
        return "Producto{" +
               "codigo='" + codigo + '\'' +
               ", nombre='" + nombre + '\'' +
               ", precio=" + precio +
               ", stock=" + stock +
               ", categoria='" + categoria + '\'' +
               '}';
    }
}

Resumen

Los comentarios y la documentación son herramientas fundamentales para crear código Java mantenible y profesional. Los comentarios regulares (// y /* */) son útiles para explicar decisiones de diseño y aclarar secciones complejas, mientras que los comentarios de documentación Javadoc (/** y */) permiten generar documentación técnica automáticamente.

Una buena práctica de documentación consiste en explicar el "por qué" detrás del código, mantener los comentarios actualizados, utilizar un estilo consistente y documentar completamente las APIs públicas. Siguiendo estas recomendaciones, crearemos código más comprensible y facilitaremos la colaboración con otros desarrolladores en nuestros proyectos Java.