«Patrón singleton» revisited

Estoy leyendo un delicioso libro, «Effective Java», de Joshua Bloch, sobre buenas prácticas Java para programadores Java (el segundo capítulo, por ejemplo, empieza explicando cómo usar métodos de factoría estáticos y sus ventajas sobre los constructores típicos, para que os hagáis una idea…). El libro es una joya, de los que merece la pena leer junto a un buen café, tomando notas en los laterales, porque está cargadito de apuntes que reutilizarás en el futuro, seguro, al menos si programas en Java (sí, ya sé, «Java is evil», etc.. etc…. ) Enumera distintos ítems, (vamos a llamarles recetas), en las que indica cómo se hace tal cosa en Java y cómo se debería de hacer. En muchas ocasiones, las recetas están directamente relacionadas con patrones de diseño, soluciones a problemas comunes. En otras, con anti-patrones : soluciones que NO se deberían de adoptar ante problemas comunes.

Sólo un comentario más de presentación, extraído del prefacio, en palabras de James Gosling, el padre de Java: «I sure wish I had had this book ten years ago. Some might think that I don’t need any Java books, but I need this one.»

Bien, una vez hechas las introducciones, pasamos a la chicha. Uno de los puntos sobre el que ya hablamos en otro post de DiarioLinux trata sobre el patrón singleton. El caso es que Bloch recomienda seguir una plantilla para aplicar el patrón singleton diferente a la que recomienda el libro de Liskov (Program Development in Java). La recomendación (de Bloch) es la siguiente:


// Singleton with public final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
// como todo el mundo sabe "There's only one Elvis" :-)

Yo mismo recomendaba la plantilla de Liskov frente a la de Bloch… pero visto lo visto, y sabiendo que la recomendación de Liskov podría tener condiciones de carrera… ya no hay duda. Sin embargo, el propio Bloch indica que «un consumidor de ese código con suficientes privilegios podría invocar al constructor privado usando las capacidades de introspección de Java, con el método AccessibleObject.setAccessible», así que para evitar ese problema (hay que ser rebuscado de narices), recomienda esta otra forma:


// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() { ... }
}

que se parece muchísimo a la recomendación de Liskov, pero sin el problema de las condiciones de carrera.

Finalmente, llega la guinda. Bloch dice que todo lo anterior está muy bien y tal, pero que teniendo disponible Java 1.5 desde hace ya unos cuantos añitos, que nos podríamos simplificar todos un poco la vida mediante el uso de tipos enumerados (disponibles en Java desde la versión 1.5, o 5.0 para aquellos lectores más comercial-friendly):


// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}

«While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.» Amén 🙂

PD: buscando documentación sobre esto, me he encontrado casualmente con la receta que comento en un artículo de InformIT.

Visual Paradigm, Linux y Compiz

No sólo ocurre con Visual Paradigm sino con muchas aplicaciones Java con interfaz gráfico SWING. Siempre que usemos Linux con Compiz (efectos gráficos) activado. El problema es que al lanzar la aplicación (en el ejemplo, al lanzar Visual Paradigm), la ventana sale «en blanco» :

Hay dos soluciones a este problema:

1) La obvia, desactivar Compiz momentáneamente (desde consola $ metacity –replace podría valer)

2) El problema concreto es que AWT no soporta (en todos los sentidos 😉 el gestor de ventanas Compiz
Así que hay que decirle a AWT que use otro. ¿Cómo? Así:

export AWT_TOOLKIT=MToolkit

Lo que hace que AWT use Motif como gestor de ventanas.

La solución está documentada en la web de Visual Paradigm (No, VP no es libre . Sí, VP está hecho en Java. Sí, lo sé, pero es una aplicación extraordinaria)

Proyecto DJ Java: ejecuta componentes nativos Linux en Java

«Any sufficiently advanced technology is indistinguishable from magic.» Arthur C. Clarke.
(«Cualquier tecnología lo suficientemente avanzada es indistinguible de la magia.»)

Eso es lo que he sentido al ver «The DJ Project», un proyecto Java bajo licencia LGPL que permite integrar componentes nativos Linux en aplicaciones Java Swing. Traducido al castellano y con un ejemplo: puedes integrar el plugin de Flash en una aplicación Java Swing y controlarlo por programación desde Java. Puedes enviar desde Java parámetros a funciones Flash y viceversa. Puedes usar el plugin VLC, o el navegador Mozilla desde una aplicación Swing. Y todo ello funcionando en Linux sin problemas… o en Windows! (en MacOSX… tal vez, no tengo constancia de que no se pueda, pero tampoco de que sea posible en este sistema operativo).

La instalación es un poco compleja, dado que primero hay que tener XulRunner instalado:

sh-3.2$ xulrunner -v
Mozilla XULRunner 1.8.1.4_0000000000

Una vez hecho esto, hay que asegurarse de tener Java 1.6 y una versión moderna, no vale el update 2 o 3, sino que al menos, ha de ser el 5:

java version "1.6.0_10-beta"
Java(TM) SE Runtime Environment (build 1.6.0_10-beta-b25)
Java HotSpot(TM) Client VM (build 11.0-b12, mixed mode, sharing)

Para lanzar la aplicación de demostración de DJ Java lo más sencillo es hacerlo a partir de la demo en formato Java Web Start, pero primero hay que indicar dónde tenemos instalados los plugins de Firefox (el plugin de Flash, por ejemplo):

$ export MOZ_PLUGIN_PATH=/usr/lib/firefox/plugins/

Ahora sí, podemos lanzar la aplicación de mostración:

$ ./javaws http://djproject.sourceforge.net/ns/DJNativeSwingDemo.jnlp

Las posibilidades que abre esta librería para el desarrollo de aplicaciones multimedia son impresionantes…

HackIt! Nivel 11: backtracking

Después del dolor del nivel 10 (un nivel genial no quita que no pueda ser doloroso 😉 llegamos al nivel 11 un tanto «acongojados», porque asumimos que, como la dificultad vaya en aumento, nos pueden dar las uvas.

Sin embargo, tras leer el enunciado, yo creo que este nivel no debería de haber ocupado el puesto número 11, sino alguno inferior, pues es resoluble incluso por «fuerza bruta visual», es decir, cogemos lápiz, cogemos papel y se puede resolver (no es trivial, pero se puede hacer con algo de tiempo y paciencia). Pero me estoy adelantando; la prueba pide que, en el siguiente tablero, encontremos un camino tal que el número de baldosas de cada color que atravesemos sea el mismo. Por ejemplo, 2 verdes, 2 azules y dos amarillas. El blanco no cuenta (casillas inicial y final). Se sobreentiende que no se puede pisar 2 veces la misma casilla (no lo dice el enunciado pero es una asunción que hago):

Aquellos de vosotros que habéis estudiado algoritmos de backtracking en el pasado (y os acordáis de algo 😉 me imagino que os estaréis frotando las manos, porque efectivamente, es resoluble por backtracking. Por cierto, cómo cambia la carrera de informática… hoy en día, en mi facultad, la asignatura de «Estructuras de datos y algoritmos» en Ingenieros Técnicos en Informática (que por cierto me tocó impartir este año), no se incluía la parte de backtracking por distintas cuestiones que mejor me ahorro comentar (y no son todas por «culpa de los profesores»). No me parece bien. Así que, el año que viene (y si los hados me designan a Donostia otra vez) pienso dar la tabarra hasta que encaje, como antaño, esta parte de la asignatura en el temario. Tal vez tenga que pedir también que nos pongan una máquina de café más cerca del aula… 😉

Ahora que estamos en temporada de exámenes, sé que cualquier excusa es buena para dejar de estudiar (como dice mi blog-colega txipi, «incluso os enrolaríais en un carguero uzbeko» con tal de no hincar los codos 😉 …. esta prueba de HackIt tiene su cosita: es probable que aprendáis (aprender de verdad) más de recursividad y algoritmos de backtracking resolviéndola por vuestra cuenta que estudiando la teoría correspondiente. Os pasaré mi propuesta de solución en Java en unos días… aunque ahora que lo pienso, igual la guardo como ejercicio para el año que viene };-)