Buenas prácticas de codificación en Java

Este post describe algunas recomendaciones básicas de codificación en Java para desarrollar un código más óptimo de cara al rendimiento, la homogeneidad y mantenibilidad del mismo.

Sustituir concatenación de Strings por StringBuffer

La concatenación de Strings mediante el operador “+” o el método concat es una operación costosa en tiempo de ejecución, pues se realiza la copia de los Strings en memoria, requiriendo el doble de tamaño del String original. En lugar de ello, es mejor utilizar la clase StringBuffer y su método “append”, que son más eficientes.

 Complementado por sysdent

Si bien es cierto que StringBuffer puede ser más eficiente que que el String como tal, hay que tener en cuenta que este objeto es Thread Safe lo que lo hace mucho más lento que el equivalente StringBuilder. Yo recomiendo usar StringBuffer solo en los casos estrictamente necesarios, es decir en ambientes multi-hilo.

Especialmente graves son los casos de concatenaciones de Strings dentro de bucles, pues estos son ejecutados tantas veces como pasa el flujo de ejecución del bucle, y pueden dar lugar a grandes consumos de memoria por los objetos temporales que se van creando para efectuar las concatenaciones. Por ejemplo, el código:

String resultado = ””;

for (int i=0;i<100;i++) {

resultado=resultado+”X”;

}

return resultado;

debería ser sustituido por:

StringBuffer resultado = new StringBuffer();

for (int i=0;i<100;i++){

resultado.append(“X”);

}

return resultado.toString();

Usar “new” sólo cuando sea necesario

Utilizar la palabra clave “new” cuando se instancia una clase reserva el espacio de memoria mínimo necesario para contener el objeto instanciado. Si ese objeto, debido a la ejecución del código posterior, no llega nunca a utilizarse, se ha consumido espacio de memoria sin ser realmente necesario:

String cadena=new String(“”);

Cuando exista la posibilidad de que un objeto instanciado no vaya a ser utilizado, es preferible inicializarlo a null, ya que esto no ocupa más memoria que la necesaria para almacenar un puntero:

String cadena=null;

Esto es especialmente útil en las clases que agrupan cierto número de objetos de distintos tipos, como por ejemplo los ValueObjects.

Sin embargo, se deberá tener cuidado con los objetos inicializados a null, ya que ese valor puede hacer cascar código posterior.

Evitar la creación de objetos temporales innecesarios

La creación de estos objetos consume recursos, y adicionalmente añaden más trabajo de limpieza para el Garbage Collector.

Un ejemplo muy habitual de la creación de este tipo de objetos es cuando se utilizan Wrappers para la conversión de tipos primitivos, como en:

new Boolean(valor);

que se puede sustituir por:

Boolean.valueOf(valor);

O también:

new Integer(aux3).toString();

por:

String.valueOf(aux3)

Relacionado con este tema está también la tendencia a crear objetos temporales que no son realmente necesarios. Por ejemplo, con frecuencia se utiliza el constructor de copia de la clase String (String temp=new String(parametro)) para realizar una copia de un String que se recibe como parámetro de un método, cuando en realidad se puede utilizar directamente el parámetro recibido.

Trazas de depuración

Toda traza realizada con Log4J a nivel debug e info deben ir precedidas de un if que pregunte si el nivel de traza correspondiente está habilitado ya que, aunque esta comprobación se hace dentro de los propios métodos de trazas, el hacerla lo primero evita tener que invocar al método, construyendo los parámetros (que suele requerir en la mayoría de los casos la creación de objetos String para representar la traza).

Este cambio puede llegar a ser muy significativo en ahorro de recursos (sobre todo de memoria), en función del número de trazas y la complejidad de las mismas a lo largo de la aplicación. Por ejemplo, se debería sustituir este código:

m_log.debug(“Esto es una traza”);

por:

if (m_log.isDebugEnabled()) {

m_log.debug(“Esto es una traza”);

}

Inicialización del sistema de trazas

Con mucha frecuencia se hacen multitud de llamadas al método init() del sistema de trazas, lo cual provoca que se vuelvan a leer y establecer las propiedades de inicialización del Log4J. Esta operación sólo es necesario que se realice una única vez en el inicio de la aplicación. En una clase cualquiera, el uso que se debe hacer del servicio de trazas debería ser como en el siguiente ejemplo:

public class MiClase {

// Servicio de LOG

static LogService aux = new LogService(“log”, “< properties>”);

static Log m_Log = aux.getLog(MiClase.class.getName());

/**

* Método constructor de la clase MiClase

* */

public MiClase(<parametros>) {

<código del constructor>

aux.init();

}

<resto del código de la clase>

}

Esta codificación hace que el servicio de log se inicialice cada vez que se instancia la clase.

Otra aproximación, que permite aún mejor rendimiento, es desarrollar un servlet que se ejecute al iniciarse la aplicación, en el que se inicializaría todo aquello que sólo es necesario inicializar una vez por aplicación en su método “init()”, como por ejemplo el servicio de log. Esto se especifica en el descriptor de despliegue de la aplicación, que permite indicar uno o más servlets y su orden de ejecución al iniciarse la aplicación.

Evitar el uso de System.out y System.err en código de producción

En vez de lanzar trazas en la salida estándar, se recomienda utilizar el sistema de trazas de la aplicación, para que las mismas queden en el log de la aplicación.

Siempre que sea posible, inicializar las colecciones con el tamaño adecuado

Siempre que se conozca su tamaño, es conveniente inicializar las colecciones (Vector, ArrayList, HashMap, HashTable, etc) con el tamaño adecuado que van a requerir, para evitar en la medida de lo posible las operaciones de ampliación de tamaño, que crean un nuevo objeto (en muchos casos duplicando el tamaño del original) para copiar el contenido del objeto anterior y tener espacio para lo nuevo. Un ejemplo de esto sería un Vector que llevara información relativa a cada día de la semana. En este caso, sabemos que el Vector contendrá 7 elementos (lunes a domingo). En el ejemplo, habría que sustituir el código:

Vector diasDeLaSemana = new Vector();

por:

Vector diasDeLaSemana = new Vector(7);

Téngase en cuenta que, independientemente de que la colección se inicialice con un número concreto de elementos, ésta se ampliará automáticamente si es necesario, lo que no afectaría al funcionamiento del código.

Evitar las llamadas a métodos dentro de las condiciones de bucles

Esas llamadas se realizarán por cada iteración del bucle, por lo que es recomendable evitarlas cuando sea posible. Por ejemplo, habría que sustituir este código:

for (int i=0;i < miVector.size();i++) {

<código para tratar cada elemento de miVector>

}

por este otro:

int tam=miVector.size();

for (int i=0;i<tam ;i++) {

<código para tratar cada elemento de miVector>

}

Así se evita que el método size() de la clase Vector se invoque en cada iteración del bucle, consumiéndose menos recursos.

Publicado en Java, Tutoriales. 3 Comments »

Java EOL

La fecha de EOL (End of Life) de Java SE 6 es en noviembre de 2012. Para detalles leer Updated Java 6 EOL Date.

Me sorprende mucho más esta:

El 10 de diciembre de 2012 JavaFX 1.2 and JavaFX 1.3 no estarán más disponibles, Más detalles en The JavaFX Blog.

Esta frase se las trae, sobre todo teniendo en cuenta las grandes diferencias entre JavaFX 1.X y JavaFX 2: “All developers currently creating JavaFX 1.x applications available are strongly encouraged to migrate their applications to JavaFX 2”

https://blogs.oracle.com/java/entry/eoling_java_se_6_javafx?msgid=3-6077692575

Publicado en Java, Noticias. 1 Comment »

Firefox 11

Ayer mismo salió la versión 11 de Firefox.

Lo más destacable es el número de versión: la 11!!! (Lo de las versiones de Firefox es aún más incomprensible que lo de las versiones del Chrome, que al menos siempre han seguido la misma política).

Se ha mejorado las herramientas para los desarrolladores, consumo de memoria, mejora del rendimiento.

También incluye el inspector DOM 3D basado en Tilt

Podéis descargarla aquí para Windows.

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 445 seguidores

%d personas les gusta esto: