Sep 30

Empiezo con JavaHelp

Otra de las asignaturas que tenía pendiente con java es JavaHelp. Una librería adicional de java que facilita el crear las ventanas de ayuda de nuestras aplicaciones, haciendolas similares a las de cualquier aplicación que usemos habitualmente. Una ventana de ayuda con una tabla de contenidos en forma de árbol, un texto en lado derecho por el que podemos navegar, ayuda contextual pulsando F1 en cualquier ventana, etc.

Los primeros ejemplos que vi buscando tutoriales me dejaron totalmente perplejo. La cantidad de ficheros xml que había que configurar para que la ayuda funcionara y lo complejos que parecían me dejaron totalmente fuera de juego.

Así que si debía ser por las malas, pues por las malas. Cogí el tutorial oficial de sun -si el enlace no funciona quizás es porque tengas que aceptar los términos de la licencia-, lo imprimí y me he puesto a leerlo desde el principo.

El tema de los ficheros de configuración ya me ha quedado claro y no era para tanto. De hecho, he escrito un pequeño resumen de los ficheros de configuración de JavaHelp en la Chuwiki.

En cuanto al código, haciendo copy-paste ya tengo un pequeño ejemplo funcionando, pero aunque intuyo el significado de las líneas que he copiado, prefiero terminar de leer el manual de sun, para enterarme bien enterado. Supongo que mañana en la cafetería en la que suelo desyunar lo liquide -nuevamente el nerd que lee cosas raras en las cafeterías-

Una cosa que no me ha hecho gracia de JavaHelp es que parece que es difícil de depurar. Salvo el primer fichero .xml que se lee en la configuración, del resto no avisa si encuentra errores de sinaxis. Simplemente lo ignora y la parte de ayuda relativa a ese fichero .xml no funciona. Por otro lado, cuando no encuentra uno de los items que le indicamos, directamente saca una excepción por pantalla, por lo que puede estropearnos nuestro log de salida.

Sep 28

Un detalle de los genéricos de Java

Simplemente, una pequeña cosa que no sabía de los genéricos de java y que me ha llamado la atención.

Supongamos que tenemos un método que pretendemos que reciba una LinkedList de números y nos devuelva la suma de todos ellos. La LinkedList es un genérico y queremos ponerla concreta. Se nos puede ocurrir, por ejemplo, poner esto

public double suma (LinkedList<Number> listaNumeros) {
   …
}

Esto tiene una pequeña pega. Podemos instanciar una LinkedList<Number> y meter ahí cualquier tipo de número, como Float, Integer, Double, etc. La llamada al método funcionará perfectamente

LinkedList<Number> lista = new LinkedList<Number>();
lista.add (new Integer(3));
lista.add (new Float(2.2));

double resultado = suma (lista);

Sin embargo, si instanciamos una LinkedList<Double>, LinkedList<Integer>, … dará error al llamar al método, puesto que no es lo que el método espera de parámetro, una clase LinkedList<Number>.

El truco, que es lo que me ha llamado la atención, es declarar el método con una sintaxis tan extraña como esta

public double suma (LinkedList<?extends Number> listaNumeros) {
   …
}

De esta forma, admite cualquier LinkedList<Cosa> donde Cosa sea una clase que herede de Number, es decir, cualquiera de las que mencionamos anteriormente.

Sep 27

Punto para la reutilización

Cuando empezamos a hacer proyectos con java similares a los que hacíamos en C++ y con la experiencia de ellos, lo primero que hicimos, porque sabíamos que era un punto muy importnte, fue nuestra propia librería de sockets. Una librería que facilitaba a la gente que tuviera que enviar mensajes el envío de los mismos. La librería se guardaba el mensaje y lo enviaba cuando hubiese conexión. Esta librería aisla a la gente de si los bytes del mensajes se envía todos de golpe o en varios bloques, de si la conexión se rompe o no, etc.

En un momento dado, gente de otro departamento nos pidió un trozo de nuestro proyecto, con el que pensaban comunicarse mediante sockets. Aislamos ese trozo, haciendo un main() aparte, instanciamos nuestra clase de sockets y todo listo en menos de un día de trabajo. Los del otro departamento hicieron su parte de código. Como no tenían librería de sockets, los codificaron con las funciones básicas de sockets que da Visual C++. Luego nos tocó integrar. Una parte importante del tiempo de integración se fue en depurar su código de sockets, recién salido del horno.

Y no hicieron librería de sockets.

Un par de años después, la misma persona del otro departamento viene con la misma necesidad, necesita un trozo de nuestro proyecto -otro distinto- al que se va a conectar con sockets. Nuevamente, en menos de un día preparamos toda nuestra parte. Esa persona, sin embargo, hizo copy-paste del código de sockets del proyecto de hacía dos años y lo puso en su nuevo proyecto. Luego modificó lo que creyó necesario. Y otra vez gran parte de la integración se nos ha ido en depurar otra vez errores similares a los que depuramos hace dos años en su código de sockets. Estos nuevos errores se debían en parte a la modificación del código pegado.

Y siguen sin hacer la librería de sockets.

Una de las pegas del código reutilzable es que no te das cuenta del tiempo que ahorras. Usamos nuestra librería de sockets una y otra vez y nos parece lo más natural del mundo. No piensas en el tiempo que ahorras si tuvieras que codificarla y depurarla cada vez en cada proyecto. Igual que no piensas en el tiempo que ahorras al usar directamente un JTextField o un JButton en vez de codifcártelo tú mismo cada vez -y depurarlo-. Afortunadamente, de vez en cuando pasan estas cosas con gente que trabaja de otra manera, y te das cuenta de la cantidad de tiempo que ahorras habitualmente de forma inconsciente.

Y la gran pega es que el jefe NUNCA se va a dar cuenta de lo útil que es el tiempo que malgastaste al principio de los tiempos, cuando tardaste dos semanas en hacer unos sockets tontos que el del otro departamente hizo en dos días. Tampoco se da cuenta que en el siguiente proyecto tú dedicaste 0 días a los sockets mientras que el del otro departamente nuevamente dedica dos días, y otros dos en el siguiente y otros dos en el siguiente…

Sep 24

Internacionalización en Java

Ya en su día leí algo sobre el tema de internacionalización de java, eso de que de forma más o menos automática salgan los textos de nuestra aplicación en el idioma del sistema operativo.

Cuando lo leí no me llamó especialmente la atención, ya que pensaba que símplemente era hacer unos ficheros de propiedades en los que se pone etiqueta=valor, donde etiqueta es un nombre que nosotros queramos para cada etiqueta que vayamos a visualizar y valor es el texto que debemos mostrar. En el código bastaba con cargar dicho fichero de propiedades e ir leyendo de ahí las etiquetas que queríamos poner en pantalla.

Sin embargo, hay otra posibilidad que puede pasar desapercibida, al menos, a mí se me paso. Podemos meter esas etiquetas directamente en código, en una clase que herede de ListResourceBundle. Debemos hacer una clase por cada idioma.

De esta forma, si en el código decimos ResourceBundle.getBundle("Etiquetas") y estamos en español de España, java buscará primero una clase Etiquetas_es_ES.class de la que obtener las etiquetas y si no la encuentra buscará el fichero Etiquetas_es_ES.properties

Otra cosa curiosa, es que java busca hasta tres clases o ficheros. En nuestro caso anterior, busca primero Etiquetas_es_ES. Si no lo encuentra, busca Etiquetas_es y si no lo encuentra, busca Etiquetas. De esto, lo realmente interesante es que podemos hacer los tres ficheros o clases con esos nombres y si existen los tres, java buscará la etiqueta en ellos en ese orden, hasta que la encuentre. De esta forma, por ejemplo, podemos poner las etiquetas en españos en Etiquetas_es. Luego, para Argentina, hacemos un Etiquetas_es_AR con sólo aquellas etiquetas que cambien respecto al español de España.

Un tema que me ha resultado más interesante de lo que me pareción en principio y que me ha dado una muestra más de la forma de hacer de java.

Por supuesto, he hecho mi pequeño tutorial de internacionalización en java.

Sep 20

Botones flotantes

Esta es una calculadora que hice un día que me aburría. La hice para entretenerme.

¿Qué tiene de entretenido hacer una calculadora?. Bueno, pues hacer una calculadora que no funcione como las calculadoras normales. Intenta usarla y verás lo que pasa.

Para los que les interese el código, simplemente hace falta una clase Hilo que es la que se encarga de mover un componente por la pantalla

 class ElHilo extends Thread {
    private Window w;
    private double t=0;
    private double A=Math.random()*300;
    private double B=Math.random()*300;
    private double a=Math.random()*8-4;
    private double b=Math.random()*8-4;
    private Point pOriginal;
    public ElHilo(Window w) {
        this.w = w;
        pOriginal = w.getLocation();
    }
    public void run() {
        while (true) {
            double dx = A*Math.sin(a*t);
            double dy = B*Math.cos(b*t-Math.PI/2);
            w.setLocation( pOriginal.x+(int)dx, pOriginal.y+(int)dy);
            t=t+0.01;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

y un método recursivo en algún sitio capaz de ir rebuscando en el árbol de componentes para hacer "flotar" los que nos interesen

    public void meteEnWindows(Component componente) {
        if ((componente instanceof JButton) || (componente instanceof JTextField))
        {
        Point p;
        try {
            p = componente.getLocationOnScreen();
        } catch(Exception e) {
            return;
        }
        Window w = new Window(SwingUtilities.getWindowAncestor(componente));
        w.setLocation(p);
        w.add(componente);
        w.pack();
        w.setVisible(true);
        ElHilo hilo = new ElHilo(w);
        hilo.start();
        }
        if (componente instanceof Container) {
            Component[] hijos = ((Container)componente).getComponents();
            int numeroComponentes = ((Container)componente).getComponentCount();
            for (int i=0;i<numeroComponentes;i++)
                meteEnWindows(hijos[i]);
        }
    }
 

Pues nada, ahí está para el que guste de estas chorradas.

Sep 19

Día provechoso

Cada vez estoy convencido de que las empresas sacan cosas adelante por casualidad y porque Dios es misericordioso.

Esta mañana una reunión en la otra punta de Madrid. Me refiero a la provincia de Madrid. Trabajo cerca de la provincia de Guadalajara y la reunión fué cerca de la provincia de Toledo. Por supuesto, la reunión era para algo inútil y no llegamos a nada útil en ella -como era de esperar-.

Cuando volví a mi centro de trabajo, cerca de las dos y media, una cola de gente esperando para incordiarme. Que si a uno se le ha roto una tripa, que si el otro la ha perdido y el otro ni siquiera sabe que tiene tripa. Vaya, que estoy por comprar un aparato de pedir número, como los de los supermercados. Otra opción son las barras esas con cintas que ponen en las taquillas de los cines para hacer las colas.

Bueno, lo grave no es eso -en el fondo me siento apreciado por mis compañeros que vienen a verme -. Lo grave es que algo tan tonto como arrancar un script de compilado… no he podido hacerlo, en toda la tarde.

Y así van las empresas, que te buscan reuniones inútiles para que pierdas el tiempo en cosas muy importantes pero que no sirven para nada.

Sep 18

Sigo aprendiendo a ser un jefe pérfido

En su día, cuando entré a trabajar en la empresa, empecé de programador puro y duro. Alguien me decía qué tenía que hacer y lo hacía. Eran tiempos felices.

Más adelante, me dieron un grupo reducido de gente, tres o cuatro personas, a los que organizar y controlar el trabajo. Yo seguía programando, miraba los programas de esos tres o cuatro, y seguía siendo feliz, aunque un poco menos.

Hace ya unos meses que pretenden que organice y controle el trabajo de treinta personas. Apenas programo y me resulta imposible mirar el código de todos ellos ni organizarlos. Llevo desde que escribí el post del principio de Peter dándole vueltas al asunto sin llegar a nada en claro. De hecho, por eso escribí lo del principio de Peter, porque creo haber llegado a mi máximo nivel de incompetencia.

Sin embargo, esta mañana se me hizo la idea féliz. Ya sé cómo controlar a treinta personas -o a las que se tercien-. Basta seguir la tradición de los jefes que he tenido hasta ahora y que supongo que son como los que hemos tenido casi todos. La idea básica consiste en entrar a trabajar por la mañana, elegir a uno de los treinta al azar, preguntárle

  • ¿Qué estás haciendo?

luego preguntarle

  • ¿Cómo lo estas haciendo?

 y finalmente soltarle la bomba.

  • Así como lo estás haciendo no vale. Bórralo y hazlo de esta otra forma peregrina que se me acaba de ocurrir Además date prisa, porque sería bueno que hicieras también esta otra cosa estrafalaria que he visto en internet.

Bueno. Por supuesto, es broma … creo. Lo cierto es que es complejo organizar tanta gente. Y después de leer mucho sobre buenas constumbres de programación -test unitarios, diseño, UML, etc, etc-, cuando es responsabilidad tuya implantarlas y el si funcionan bien o no cae sobre tus hombros, te empizas a plantear si realmente son tan buenas cosas, si realmente son tan efectivas. Sobre todo, cuando no tienes pruebas reales ni estadísticas serias. Sólo lo que comentan los "gurus" sobre lo bueno que es todo eso.

Y también te entra la duda, cuando quieres implantar esas cosas, si la gente que programa no te verán como ese " jefe" que inventa cosas raras para fastidiarnos. Y te preguntas hasta que punto ellos están en lo cierto, al igual que tu lo estabas cuando juzgabas a tu jefe.

Sep 13

¿Merece la pena la documentación de diseño?

Me refiero a la documentación, a los diagramas UML y todo lo demás. Por supuesto, un programa si hay que pensarlo un poco antes de ponerse a codificar.

El tema es el siguiente:

Suponte que eres un programador listo, que sabes hacer bien el código, reutilizable, bien hecho y que funciona correctamente. Suponte también que trabajas tú solo en el proyecto. Posiblemente piensas en cómo vas a hacer el programa e intentas plasmarlo en una documentación con UML. Según lo haces, como eres inteligente, te vas dando cuenta de problemas de diseño y los vas corrigiendo. Al final tienes una documentación buena que te ha llevado un tiempo hacer. Luego te pones a codificar, pero no consultas en absoluto la documentación porque la conoces y tienes las ideas claras. Según codificas, vas haciendo pequeños cambios en el diseño, cosas que no previste anteriormente. Al final te sale un buen programa en condiciones … y has perdido el tiempo en hacer una documentación que no has necesitado y que ahora no es coincide exactamente con el código y tienes que arreglar.

¿Qué pasa si no hubieras hecho documentación?. Habrías pensado igualmente, quizás te habrías hecho unos esquemas en borrador para aclarar ideas, te habrías puesto a hacer el código, habrías ido corrigiendo y arreglando cosas sobre la marcha y al final llegarías a un resultado parecido e igual de bueno. Posiblemente lo hayas hecho en menos tiempo, ya que no lo has perdido en hacer una documentación formal. Basta con los esquemas en borrador para aclararte las ideas. ¿Necesitas la documentación ahora para el cliente? Una buena ingeniería inversa hace maravillas.

¿Y qué pasa si eres un programador torpe?. Da igual que hagas o no documentación. En cualquier caso tardarás mucho y no llegarás a un buen código. Si eres avispado, en cualquiera de ambos casos cogerás experiencia y la próxima vez lo harás mejor. La documentación mala que hagas no te ayudará  a hacer el código mejor y el código que has hecho seguramente no se parece en absoluto a la documentación que hiciste, porque no fuiste capaz de prever las cosas correctamente.

Vamos ahora a ser programadores en grupo. Si todos son experimentados, inteligentes y buenos programadores, posiblemente les baste con unas reuniones, unos esquemas en borrador y una pequeña planificación/distribución del trabajo. Cada uno cogerá bien la idea de lo que tiene que hacer y si se comunica con frecuencia con los demás, no habrá problemas graves de integración. Ganarán tiempo si no hacen esa documentación formal que posiblemente luego no miren y al final no se parecerá a la realidad y tendrán que corregir.

Si todos los programadores o algunos de ellos son torpes, nuevamente da igual hacer o no documentación. Las partes de ellos fallarán, irán peor o darán problemas.

Incluso aunque sólo haya un programador del grupo con conocimientos y experiencia suficiente, sería perder el tiempo. El diseño y documentación debería hacerlo él y los demás dedicarse a codificar estrictamente lo que ha diseñado el programador experimentado. Pero aún así ahorraría tiempo si en vez de documentos UML se dedica a escribir los esqueletos de las clases para que sus compañeros rellenen el código. Quizás herramientas como Together que según pintas UML genera esqueletos de clases sean más útiles, pero precisamente porque generan las clases.

Según voy cogiendo experiencia en el trabajo y me voy olvidando de "idealidades" , me voy convenciendo más de que es imposible convertir esas idealidades en realidad y que los métodos ágiles son mejores. Las metodologías deben ir orientadas a las personas, no a los procedimientos, no a generar documentación por generarla. Como he leído en algún sitio, "no hay mejor documentación que el código".

Mi experiencia me dice que a un grupo de programadores se les ayuda bien dándoles una especificación clara de lo que tienen que hacer en un lenguaje informal que les resulte agradable de leer. Se les ayuda viendo el trabajo conjunto de ellos por encima, de forma que les puedes advertir de cuándo dos de ellos están haciendo cosas parecidas o cuando puede haber conflictos entre lo que están haciendo. Funcionan bien cuando cada uno tiene bien definido qué tiene que hacer y como se relaciona con lo que hacen los otros. Y lo mejor es hacer todo esto de forma ágil, día a día. No con un documento formal al principio del trabajo.

¿Conoceis algún caso en el que una documentación formal haya resuelto algún problema? ¿En el que el tiempo de hacer la documentación más el tiempo de codificar y depurar sea menor que el de pensar informalmente, codificar y depurar?.

Sep 11

Vuelta al trabajo

Llevo varios días con este blog un poco abandonado. Se debe sobre todo a la vuelta al trabajo después de las vacaciones, que como todo el mundo, es el mejor depresivo del mundo.

Por un lado, a mí que siempre ando con ganas de programar y aprender cosas nuevas, me las ha quitado, al menos durante unos días. De hecho, nada más llegar a casa de las vacaciones, instalé un juego de estrategia de esos que me gustan y llevo enganchado varios días.

Y en el trabajo, creo que cada vez me quieren menos para código y pretenden que me dedique más a gestión. Aunque me resisto con todas mis fuerzas y en cuanto se me presenta ocasión abro el eclipse, llevo estos primeros días de reunión en reunión … haciendo planificaciones en vez de reuniones técnicas. Además, como en el trabajo la metodología de desarrollo brilla por su ausencia, no hay nada que contar intersante al respecto.

Lo único, que he aprovechado para instalar Wordpress en el servidor que tenemos allí. Así, a modo de blog, llevo las actas de las reuniones que hacemos. Las categorías del blog son los proyectos en los que andamos. Por supuesto, es la primera vez que hacemos actas de reuniones y quedan en un sitio visible. Y por supuesto también por iniciativa espontánea de un currito -yo- con aficiones informáticas que no tiene que ver con las del trabajo -web y blogs-.

Tengo que ponerme con el J2EE, sobre todo el tema de EJBs, que es el que me llama la atención y desconozco más…

Sep 07

SQLite y test unitarios

Al instalar WAMP en mi ordenador descubrí SQLite. Es una pequeña base de datos que no necesita nada de configuración y que escribe los datos en un fichero. Supongo que está pensada como base de datos simple para que puedan utilizar las aplicaciones, sin necesidad de todo el montaje necesario de un MySQL o similar.

Sin embargo, creo que hemos encontrado una posible aplicación para ella. Muchas veces, en los test unitarios es necesario tener una base de datos, por lo que el test no se puede correr si no está la base de datos disponible o si falla por algún motivo las conexiones con ella. Con SQLite parece que tenemos la posibilidad de tener ficheros con datos de base de datos, en el mismo sitio de los test, y sería a esos ficheros a los que nos "conectamos" para hacer el test. También es posible que la misma clase de test cree dicho fichero con ciertos datos, tablas o lo que sea.

Existe un driver de SQLite para java, por lo que una vez establecida la Connection, el resto del código es más o menos independiente de la base de datos a utilizar.

La posible pega es que SQLite está basada en C, por lo que es necesario tener su versión para el sistema operativo que se utilice. Esto quiere decir que en cualquier sitio donde se quiera pasar el test, se debe tener las librerías de esta base de datos.

De todas formas, es un pequeño descubrimiento que puede resultar útil para los test unitarios.