domingo, 17 de noviembre de 2013

Javadoc: Documentación


Se aconseja, como buena práctica de programación, incluir en la entrega de la aplicación la documentación de los ficheros fuente de todas las clases. Dicha documentación será generada por la herramienta "javadoc".

La herramienta "javadoc" construirá la documentación a partir de los comentarios (incluidos en las clases) encerrados entre los caracteres "/**" y "*/". Distinguimos tres tipos de comentarios javadoc, en función del elemento al que preceden: de clase, de variable y de método.

Dentro de los comentarios "javadoc" podremos incluir código html y etiquetas especiales de documentación. Estas etiquetas de documentación comienzan con el símbolo "@", se sitúan al inicio de línea del comentario y nos permiten incluir información específica de nuestra aplicación de una forma estándar.

Como norma general utilizaremos las siguientes etiquetas:


  • @author Nombre

    Añade información sobre el autor o autores del código.

  • @version InformacionVersion

    Permite incluir información sobre la versión y fecha del código.

  • @param NombreParametro Descripción

    Inserta el parámetro especificado y su descripción en la sección "Parameters:" de la documentación del método en el que se incluya. Estas etiquetas deben aparecer en el mismo orden en el que aparezcan los parámetros especificados del método. Este tag no puede utilizarse en comentarios de clase, interfaz o campo. Las descripciones deben ser breves.

  • @return Descripción

    Inserta la descripción indicada en la sección "Returns:" de la documentación del método. Este tag debe aparecer en los comentarios de documentación de todos los métodos, salvo en los constructores y en aquellos que no devuelvan ningún valor (void). 

  • @throws NombreClase Descripción

    Añade el bloque de comentario "Throws:" incluyendo el nombre y la descripción de la excepción especificada. Todo comentario de documentación de un método debe contener un tag "@throws" por cada una de las excepciones que pueda elevar. La descripción de la excepción puede ser tan corta o larga como sea necesario y debe explicar el motivo o motivos que la originan.

  • @see Referencia

    Permite incluir en la documentación la sección de comentario "See also:", conteniendo la referencia indicada. Puede aparecer en cualquier tipo de comentario "javadoc". Nos permite hacer referencias a la documentación de otras clases o métodos.

  • @deprecated Explicación

    Esta etiqueta indica que la clase, interfaz, método o campo está obsoleto y que no debe utilizarse, y que dicho elemento posiblemente desaparecerá en futuras versiones. "javadoc" añade el comentario "Deprecated" en la documentación e incluye el texto explicativo indicado tras la etiqueta. Dicho texto debería incluir una sugerencia o referencia sobre la clase o método sustituto del elemento "deprecado".

  • @since Version

    Se utiliza para especificar cuando se ha añadido a la API la clase, interfaz, método o campo. Debería incluirse el número de versión u otro tipo de información.


El siguiente ejemplo muestra los tres tipos de comentarios "javadoc",


/**
 * UnidadOrganizativa.java:
 * 
 *  Clase que muestra ejemplos de comentarios de documentación de código. 
 * 
 * @author jlflorido
 * @version 1.0, 05/08/2008
 * @see documento "Normas de programación v1.0"
 * @since jdk 5.0 
 */
public class UnidadOrganizativa extends PoolDAO {

    /** Trazas de la aplicación */
    private Logger log = Logger.getLogger(UnidadOrganizativa.class);

    /** Identificador de la unidad organizativa */
    private int id;
 
    /** Nombre de la unidad organizativa */
    private String nombre;

    /** Obtiene el identificador de esta unidad organizativa */
    public int getId() {
        return id;
    }

    /** Establece el identificador de esta unidad organizativa */
    public void setId(int id) {
        this.id = id;
    }
 
    /** Obtiene el nombre de esta unidad organizativa */
    public String getNombre() {
        return nombre;
    }

    /** Establece el nombre de esta unidad organizativa */
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    /**
     * Inserta la unidad organizativa en el sistema.
     * 
     * @param unidad Unidad organizativa a insertar
     * @throws Exception Excepción elevada durante el proceso de inserción
     */
    public void insertarUnidad(UnidadOrganizativa unidad) throws Exception{
  
        log.debug("-> insertarUnidad(UnidadOrganizativa unidad)");
  
        Connection conn = null;
        PreparedStatement pstmt = null;
        StringBuffer sqlSb = null;
  
        try {
            conn = this.dameConexion();
      
            sqlSb = new StringBuffer("")
            .append("INSERT INTO ORG.UNIDAD_ORGANIZATIVA ")
            .append("(ID, NOMBRE) VALUES (?, ?)");
      
            pstmt = conn.prepareStatement(sqlSb.toString());
            pstmt.setInt(1, unidad.getId());
            pstmt.setString(2, unidad.getNombre());
            pstmt.executeUpdate();
   
        } catch (Exception e) {

            log.error("Error: error al insertar la unidad. " +
            "Descripción:" + e.getMessage(), e);

            throw e;

        } finally {

            log.debug("<- insertarUnidad(UnidadOrganizativa unidad)");

        }
    }
}


La documentación generada por "javadoc" será la siguiente:

a) Página índice de toda la documentación generada:



b) Documentación de la clase "UnidadOrganizativa.java":







Estandares de Programación JAVA


1. Introducción

El objetivo es el establecimiento de los diferentes estándares que pueden ser empleador durante el desarrollo de software sobre el lenguaje JAVA. 



Las ventajas que podemos tener para el uso de estos estándares son:

  • Facilidad en Mantenimiento de la aplicación.
  • Permite el fácil entendimiento para cualquier persona.
  • Mejora de la legibilidad del código.

2. Ficheros o Archivos

2.1 Organización

En el desarrollo de la aplicación, las diferentes clases en Java se las debe agrupar por paquetes, por lo que se les debe organizar de una manera jerárquica seguidos por un punto como separador.

Así dentro del paquete principal se deben organizar los diferentes subpaquetes dependiendo de las diferentes funciones que vaya a cumplir dicha aplicación. Por ejemplo, desarrollamos un web Service de acceso a datos debería tener la siguiente estructura: imfe.webservice.data, donde imfe es el nombre de la aplicación, webservice el paquete principal y data subpaquete.


Cada clase de java debe contar de lineas separadas y comentarios que identifiquen cada sección de la misma.

Deben evitarse archivos de gran tamaño que no contengan mas de 1000 lineas, ya que puede ocasionar un mal entendimiento albergando gran cantidad de métodos. 

2.2 Archivo o Fichero fuente Java (.java)

Cada archivo java debe contener una única clase o interfaz. El nombre del archivo tiene que ser el mismo que el nombre de la clase. En el caso que existan varias clases privadas que estén vinculadas a la clase publica, se debería colocar en el mismo archivo que la clase publica por lo que esta clase publica debe estar ubicada en primer lugar antes que las clases privadas.


Todo archivo Java debe tener las siguientes secciones:

  • Comentarios de Inicio
  • Sentencia de paquete
  • Sentencia de importación
  • Declaraciones de clases e interfaces

2.2.1 Comentarios de Inicio

Todo archivo fuente debe comenzar con un comentario que incluya:
  • Nombre de la clase
  • Información de la version
  • Fecha
  • Copyright
En el caso del copyright, esta debe indicar: 
  • Propiedad legal del código
  • Ambito de distribución, 
  • Uso para el que fue desarrollado
  • Modificación 


Adicionalmente podrían incluirse opcionalmente: 

  • Comentarios sobre los cambios efectuados en dicho archivo
  • Historial de cambios realizados en el archivo
Ejemplo de Comentario Inicial


/*
 * @(#)JceSecurity.java 1.50 04/04/14
 * 
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/**
 * This class instantiates implementations of JCE engine classes from
 * providers registered with the java.security.Security object.
 *
 * @author Jan Luehe
 * @author Sharon Liu
 * @version 1.50, 04/14/04
 * @since 1.4
 */

2.2.2 Sentencia de paquetes

La primera linea que debe contener un archivo fuera del comentario inicial, son los paquetes al que pertenece, clases incluidas en el archivo. 

Por ejemplo:
package javax.crypto;

2.2.3 Sentencia de importación

Después de la declaración del paquete, se debe incluir las sentencias de importación de los paquetes necesarios para el desarrollo del programa, el cual debería seguir el siguiente lineamiento:
  • Paquetes de utilidades que no pertenezcan al JDK como frameworks o proyectos opensource.
  • Paquetes desarrollados para la aplicación.

Lo que se recomienda es minimizar el uso de importacion completa de paquete, es decir del tipo "package.*", ya que dificulta la comprension de las dependencias del cual estan siendo usadas en la aplicación.

Ejemplo:


import java.io.*; // BufferedReader, PrintWriter, FileInputStream, File
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import provincia.organismo.corporativas.atlas.vo.AgendaVO;

2.2.4 Declaraciones de clases e interfaces

La siguiente tabla nos mostrara los elementos que componen la declaración de una clases asi como el orden al que deben ser usados:

Elementos de declaración de una clase / interfazDescripción
Comentario de documentación de la clase/interfaz /** ... */Permite describir la clase/interfaz desarrollada. Necesario para generar la documentación de la api mediante javadoc.
Sentencia class / interface
Comentario de implementación de la clase/interfaz, si es necesario /* ... */Este comentario incluye cualquier información que no pueda incluirse en el comentario de documentación de la clase/interfaz.
Variables de clase (estáticas)En primer lugar las variables de clase públicas (public), después las protegidas (protected), posteriormente las de nivel de paquete (sin modificador), y por último las privadas (private).
Variables de instanciaPrimero las públicas (public), después las protegidas (protected), luego las de nivel de paquete (sin modificador), y finalmente las privadas (private).
Constructores
MétodosDeben agruparse por funcionalidad en lugar de agruparse por ámbito o accesibilidad. Por ejemplo, un método privado puede estar situado entre dos métodos públicos. El objetivo es desarrollar código fácil de leer y comprender.


3. Sangria

La norma general es establecer cuatro caracteres como unidad de sangria. En los diferentes IDE(Entorno de Desarrollo Integrado) mas conocidos como Eclipse o NetBeans, estos incluyen la facilidad de darle formato al código Java.


3.1 Longitud de línea

No debe superar mas de 80 caracteres por motivos de visualización e impresión.

3.2 División de líneas

En ocasiones una expresión puede ocupar mas de una línea, por lo que se deberá romper dicha expresión de acuerdo a los siguientes criterios:
  • Tras una coma
  • Antes de un operador
  • Rupturas de nivel superior a las de nivel inferior
  • Alinear la nueva línea con el inicio de la expresión al mismo nivel que la línea anterior
Ejemplo:

unMetodo(expresionLarga1, expresionLarga 2, expresionLarga 3, 
        expresionLarga 4, expresionLarga 5);

if ((condicion1 && condicion2)
        || (condicion3 && condicion4)
        ||!(condicion5 && condicion6)) {
    unMetodo();
}

4. Comentarios

4.1 Comentarios de Implementación

Se usan para describir el código, el como, en donde se incluye información relacionada con la implementación, como la descripción de la funciones de las variables locales, fases lógicas de ejecución del método, captura de excepciones, etc.

4.1.1 Comentarios de bloque

Descripción de archivos, clases, bloques, estructuras de datos y algoritmos.

Ejemplo


/*
 * Esto es un comentario
 * de bloque
 */

4.1.1 Comentarios de línea

Son comentarios cortos, que están localizados en una sola línea y tabulados al mismo nivel que el código que lo describe.

Ejemplo:


/* Esto es un comentario de línea */

// Esto es otro comentario de línea

4.1.1 Comentarios fuera de línea

Es el comentario ubicado al final de la sentencia del mismo código o línea de código

Ejemplo:


int contador = 4 + 10;  // Inicialización del contador
contador++;   /* Incrementamos el contador */

4.2 Comentarios de Documentación

También denominados comentarios Javadoc, en el que utilizan para describir la especificación del código, desde un punto de vista independiente a la implementación. Para ser consultada por desarrolladores que no tengan acceso al código fuente.

5. Declaraciones

5.1 Declaración por línea

Es aconsejable ya que se promueve el uso de comentarios

Ejemplo:

int idUnidad;   // Identificador de la unidad organizativa
String[] funciones; // Funciones de la unidad

5.2 Inicialización

Toda variable local debe ser inicializada en el momento de su declaración, excepto que el valor que contenga inicialmente dependa de algún otro valor ya calculado previamente.

Ejemplo:

int idUnidad = 1;
String[] funciones = { "Administración", "Intervención", "Gestión" };

5.3 Localización

5.3.1 Variables Locales

Las declaraciones deben estar situadas al principio de cada bloque principal y nunca en el momento de su uso.

Ejemplo:

public void unMetodo() {
 int contador = 0;  // inicio del método

 ...
}


5.3.2 Variables Globales

Estas variables deben estar ubicadas al inicio de la clase principal

Ejemplo:


public class unaClase{

 int contador = 0;  // Inicio de la variable Global

 public void unMetodo() {
 
  if (condicion) {
   int contador = 2;  // ¡¡ EVITAR !!
   ...
  }
  ...
 }
}

5.3.3 Excepciones

Cuando se usan los indices de bucle for ya que en Java se las puede incluir dentro de la misma sentencia

Ejemplo:


for (int i=0; contador<10; i++) {
 ...
}


5.4 Declaración de clases o interfaces

Deben seguir el siguiente formato:
  • No incluir espacios entre el nombre del método y los parentesis
  • El carácter de inicio del bloque es { y debe aparecer al final de la sentencia de declaración } debidamente tabulada al mismo nivel correspondiente
  • Cada método se separa de otro por medio de una linea en blanco 
Ejemplo:

public classe ClaseEjemplo extends Object {

 int variable1;
 int variable2;
 
 public ClaseEjemplo() {
  variable1 = 0;
  variable2 = 1;
 }
 ...
}


6. Sentencias

Cada línea debe tener como máximo una sentencia

Ejemplo:


int contador++;
int variable--;


Toda sentencia de un bloque debe estar contendida entre llaves {...}, aunque sea de una única sentencia.

Ejemplo:


if (condicion) {
 variable++;
}

La sentencia try/catch tiene que tener este formato:


try {
    sentencias;
} catch (ClaseException e) {
    sentencias;
}

Para liberar los recursos de este bloque se usa "finally"


try {
    sentencias;
} catch (ClaseException e) {
    sentencias;
} finally {
    sentencias;
}


7. Espacios en Blanco

Permiten una mejor legibilidad del código para poder identificar las secciones de código relacionadas. Y se utilizara los espacios en blanco en los siguientes casos:
  • Entre una palabra claver y un parentesis, para poder distinguir las llamadas a métodos de las palabras claves.

while (true) {
    ...
}
  • Tras cada coma en un listado de argumentos
objeto.unMetodo(a, b, c);
  • Separar un operador binario de sus operandos
a += b + c;

a = (a + b) / (c + d);

contador++;
  • Separa expresiones incluidas en la sentencia for
for (expresion1; expresion2; expresion3)
  • Al realizar casting de clases
Unidad unidad = (Unidad) objeto;

8. Nomenglatura de identificadores

Permite que los programas sean mas fáciles de leer y mas comprensibles. Ademas proporcionan información sobre la función que desempeña el identificador dentro del código.

8.1 Paquetes

Se escribirán siempre con letra minúscula para evitar cualquier conflicto con los nombres de clases o interfaces. El prefijo del paquete siempre corresponderá a un nombre de dominio de primer nivel como: es, eu, org, com, net, etc.

El resto de componentes del paquete se escribira con minusculas, si en el caso se identifican con dos nombres debe estar presedido por el caracter "_" el segundo nombre.

Ejemplo

adm.practica_1.logica
java.util.ArrayList

javax.servlet.http.HttpServletRequest

8.2 Clases e Interfaces

Los nombres de las clases deben ser sustantivos, en la que deben contener la primera letra en Mayúscula. 
Los nombre serán simples y descriptivos. Debe evitarse el uso de acrónimos o abreviaturas, salvo en aquellos casos como URL, HTTP, etc.
Así mismo las interfaces serán nombradas como lo indicado para las clases.

Ejemplo:
class Ciudadano
class OrganigramaDAO
class AgendaService

8.3 Métodos

Los métodos deben ser verbos escritos en minúsculas. Cuando estos estén compuestos por varias palabras se tendrá la primero palabra en mayúscula.

Ejemplo:

public void insertaUnidad(Unidad unidad);
public void eliminaAgenda(Agenda agenda);
public void actualizaTramite(Tramite tramite)

8.4 Variables

Se escribirán siempre en minúsculas, si en el caso que estén compuestas por varias palabras la primera palabra sera en mayúscula.
Las variables nunca podrán comenzar con los siguientes caracteres "_" o "$".
Los nombres deben ser cortos y su significado debe ser lo suficientemente claro para que demuestre la función que desempeña en el código. Por lo que se debe evitar el uso de nombre de variables de un solo carácter.

Ejemplo:


Unidad unidad;
Agenda agenda;
Tramite tramite;

8.5 Constantes

Todos los nombres de las contantes deben ir en mayusculas, en el caso de componer con mas nombres se debe usar un caracter de intermedio "_"

Ejemplo:


int LONGITUD_MAXIMA;
int LONGITUD_MINIMA;

9. Prácticas de programación

9.1 Visibilidad de atributos de instancias y clases

Los atributos de instancia y clases siempre deben ser declarados privados (private), excepto cuando tengan que ser visibles en subclases heredadas, en tal caso serán como protegidos(protected).
El acceso a los atributos de una clase debe darse por medio de los métodos "get" y "set".

Ejemplo:

public class Unidad {

 private int id;
 private String nombre;
 ...

 public void actualizaUnidad(Unidad unidad) {
  this.setId(unidad.getId());
  this.setNombre(unidad.getNombre());
 }

 ...
}

9.3 Constantes

Nunca aparecerán directamente en el código, para lo cual se escribirá con mayúsculas y se declararán su ámbito de uso.

Ejemplo:

// Uso incorrecto
codigoErrorUsuarioNoEncontrado = 1;
...
switch (error) {
  case codigoErrorUsuarioNoEncontrado:
   ...
}

// Uso correcto
public final int CODIGOERROR_USUARIONOENCONTRADO = 1;
...
switch (error) {
  case CODIDOGERROR_USUARIONOENCONTRADO:
   ...
}


9.4 Asignación sobre variables

Se debe evitar asignaciones sobre el mismo valor multiples variables en una misma sentencia.

Ejemplo:

int a = b = c = 2;  // Evitar

// INCORRECTO
if ((c = d++) == 0) { }

// CORRECTO
c = d++;
if (c == 0) { }

//INCORRECTO
c = (c = 3) + 4 + d;  


//CORRECTO
c = 3;
c = c + 4 + d; 


9.5 Otras prácticas

9.5.1 Paréntesis

Se debe incluir distintos tipos de operadores para evitar problemas de precedencia de operadores. Por lo que otros programadores puedan que no tengan clara las reglas de precedencia.

Ejemplo:

if (w == x && y == z)     // INCORRECTO
if ((w == x) && (y == z)) // CORRECTO

9.5.2 Variables de retorno

Tendrán que ser simples y comprensibles de acuerdo al propósito y comportamiento que se utilicen.

Ejemplo:

// INCORRECTO
public boolean esProgramador(Empleado emp) {

 if (emp.getRol().equals(ROL_PROGRAMADOR)) {
  return true;
 } else {
  return false;
 }

}

// CORRECTO
public boolean esProgramador(Empleado emp) {

 boolean esUnProgramador = false;

 if (emp.getRol().equals(ROL_PROGRAMADOR)) {
  esUnProgramador = true;
 }

 return esUnProgramador;
}

9.5.3 Expresiones en el operador condicional ternario

Toda expresión compuesta, por uno o más operadores binarios, situada en la parte condicional del operador ternario deberá ir entre paréntesis

Ejemplo:


(x >= y) ? x : y;