Jul 13

Seguir las reglas a ciegas

Veo esta duda en StackOverflow en la que preguntan si hay alguna forma de que los getter y setter en java se puedan generar automáticamente desde código, igual que muestra cómo se hace en Javascript. Mirando las respuestas, se llega por ejemplo a proyectos como Project Lombok, en el que poniendo anotaciones @Getter y @Setter en el atributo, los genera automáticamente.

Si vamos un poco más allá, también el lenguaje Groovy hace automáticamente estas cosas, pone en los bytecodes compilados métodos getter y setter para los atributos, de forma que podemos usarlos desde otros lenguajes como java.

Maravilloso, todos sabemos que hacer los atributos privados y poner setter y getter es una de las buenas costumbres de programación y es pecado no hacerlo, así que todas estas maravillosas herramientas lo hacen AUTOMATICAMENTE por nosotros, ahorrándonos escribir el tedioso código.

Pero creo que nos olvidamos del fondo. ¿Por qué es bueno hacer los atributos privados y poner getter y setter?. La respuesta todos la sabemos: encapsulación. Pero, ¿nos hemos parado a pensar realmente qué es eso?

Imagina un atributo privado "chisme" con su correspondiente getter y setter

private double chisme;
public void setChisme(double chisme) {
   this.chisme=chisme;
}
public double getChisme() {
   return this.chisme;
}

La ventaja de la encapsulación es que si más adelante decido que en vez "chismes" tengo "trvilorios" (todos sabemos que los "chismes" y los "trivilorios" son equivalentes y podemos obtener unos de otros) y que en vez de double, es un BigDecimal, podemos hacer esto

private BigDecimal trivilorio;
public void setChisme(double chisme) {
   this.trivilorio = getTrivilorioAPartirDeChisme(chisme);
}
public double getChisme() {
   return getChismeAPartirDeTrivilorio(this.trivilorio);
}

Y esta es la verdadera ventaja, hemos cambiado el atributo, pero mantenemos los setter y getter de chisme, haciendo las cuentas necesarias en esos métodos. De esta forma, todo el código que use nuestra clase seguirá usando setChisme() y getChisme() y seguirá trabajando con chismes y no con tirvilorios, no necesitamos cambiar nada, posiblemente ni siquiera recompilar ese otro código,  y todo seguirá funcionando.

Pero si usamos maravillosas herramientas que generan automáticamente los getter y setter, perdemos el encapsulamiento, que es precisamente el único motivo de la existencia de esos setter y getter. En el momento que cambie "chisme" por "trivilorio", aparecerán automáticamente getTrivilorio() y setTrivilorio(), pero desaparecerán, también automáticamente, getChisme() y setChisme(), por lo que todo el código que hay por ahí usando setChisme() y getChisme() se debe rehacer, recompilar…. y posiblemente hacer las conversiones de chisme a trivilorio y viceversa, o bien tocar el código que usaba chismes y ahora tiene que usar trivilorios.

Así que ojo con estas herramientas. Si queremos que el código que usa nuestra clase no tenga que cambiar y usamos estas herramientas, después de cambiar chisme  por trivilorio, debemos escribir manualmente los métodos getChisme() y setChisme() con su correspondiente conversión, manteniendo así la compatibilidad y la encapsulación. Por supuesto, setTrivilorio() y getTrivilorio() pueden y deben añadirse, automática o manualmente.

Mar 26

Jugando con los IDEs para Grails

 Cuando me puse a jugar con Grails, cogí el IDE al que estoy acostumbrado, eclipse, y me puse con él. Enseguida empecé a echar de menos los autocompletar, la sintaxis coloreada y demás comodidades a las que nos acostumbran los IDEs, así que tocaba buscar plugins adecuados.

Los plugins que encontré para groovy y para grails me resultaban más bien escasos o incluso no se dejaban instalar. Al final conseguí una sintaxis coloreada de groovy, con el compilado automático deshabilitado y sin ningún tipo de integración con Grails. No se puede arrancar la aplicación Grails ni, por supuesto, depurarla.

Siguiendo con google, por las páginas de grails y asociadas, acabas llegando a que hay un IDE basado en eclipse y con muy buena integración con groovy/grails. Este IDE es STS (SpringSource Tool Suite). Pero yendo a la página correspondiente, resulta que para bajarlo me piden el nombre, el apellido, el teléfono, la empresa, mi puesto en la empresa, el sueldo, el tercer apellido de mis abuelos (de todos) y la partida de nacimiento, así que pasé totalmente de bajarlo.

También vi por internet que Netbeans soporta bien groovy y grails sin necesidad de plugins, viene ya integrado. Me lo bajé y lo probé. Mi primera impresión fue muy buena. Hace años, cuando usaba/probé netbeans, recuerdo que tenía un arranque muy lento y pesado. La nueva versión parece que arranca en un tiempo prudente. La integración con grails bien, se pueden arrancar las aplicaciones grails (no he probado a depurar, pero supongo que sí). Me bastó con abrir el proyecto grails ya creado con grails create-app para ponerme en marcha. Sin embargo, sigo acostumbrado a eclipse y hay cosas de netbeans que no me gustan, más por gusto personal que por defectos del IDE.

Así que me armé de valor, fuí a la página de STS, puse el nombre de mi compañero de mesa en el curro, su dirección, su teléfono, su tarjeta de crédito, le engañé para que me pasara su certificado de penales que también piden y me bajé el STS. Luego, Aitortxu en twitter me comenta de una página en la que se puede uno bajar STS sin descubrirle a nadie sus intimidades.

El STS una maravilla. Es un eclipse, por lo que ya estoy acostumbrado a él, y viene "tuneado" para hacer aplicaciones web, aspectj, una cosa que se llama roo (una especie de grails, pero puramente java), jpa, etc, etc. Grails y Groovy no vienen por defecto, pero hay una pestaña llamada "dashboard" en la que con un par de clicks nos baja los plugins correspondientes y funciona todo bien.

La sintaxis coloreada, ejecución, autocompletar y demás todo bien. Viene todo lo necesario para trabajar a gusto, aunque tanto plugin hacen el arranque y la instalación un poco pesados. El autocompletar como todo autocompletar en lenguajes no tipados: si sabemos de qué tipo es la variable, bien, si no lo sabemos, imposible. Así que me quedo definitivamente con STS. Aparte, me he puesto a jugar un poco con los proyectos JPA (viene con EclipseLink) y aun a pesar de no tener ni idea, lo que he intentado me ha salido a la primera o casi, lo que quiere decir que es más o menos intuitivo y robusto ante torpes como yo.

Mar 21

Sigo jugando con GfxBuilder

 Ayer pasé parte del día entretenido con GfxBuilder he intentando hacer un gráfico estadístico para el tablero Kanban en el que ando metido.

Registro las fechas en que cada pegatina sale de la primera columna (se supone que de alguna manera se empieza a trabajar en ella) y la fecha en que llega a la última (se supone que se termina el trabajo en ella), con la intención de hacer algún gráfico que nos de idea de cuánto tarda en promedio una pegatina en recorrer todas las columnas, cuantas hay a medio hacer cada día, etc.

Así que en el momento de visualizar el gráfico, recolecto toda esa información y me pongo a echar cuentas para definir los puntos a dibujar. Una vez hecho, intento dibujar una polyline de GfxBuilder…. y me da un ClassCastException. Dice que no puede hacer cast de ArrayList a Number. Bueno, me habré equivocado, seguro que dentro de donde se espera un número he metido sin querer algún tipo de lista. Miro, remiro y reviso y nada, todo aparentemente está correcto. Así que quito mi código e intento dibujar, con copy-paste, la polyline del ejemplo. Vaya, da exactamente la misma excepción y el ArrayList que no puede convertir es el de los puntos.

Me pongo con google y acabo en el repositorio de fuentes de GfxBuilder y en concreto, en la clase PolyLineNode.groovy, que es la que se supone pinta las polilíneas. Curioso, el atributo points que es donde se supone debe estar el array de puntos se declara como double. Y ello no les impide, en otros sitios del código, hacer cosas como points.size(). No creo equivocarme, pero tiene pinta clara de ser un bug/despiste.

Y esto, aunque pueda ser un despiste, es realmente un problema. He hecho una prueba mínima y groovy compila eso sin cantar error. A pesar de estar puesto el tipo de points como double, permite llamar a size(). Desde mi punto de vista, este es el motivo por el que lenguajes que no son fuertemente tipados quedan descartados para grandes desarrollos. Todos cometemos despistes en algún momento y si somos un equipo de muchos desarrolladores en un proyecto, la probabilidad de despistes es muy alta. Y en este caso, el despiste que un lenguaje fuertemente tipado detecta en tiempo de compilado (e incluso un buen IDE en el momento mismo de escribirlo), se ha colado hasta la cocina, pasando por el repositorio y al público en general. Sí, diréis que hay que ser disciplinados, pero errar es humano y sobre todo en proyectos grandes con muchos humanos codificando. Eso sí, eso no quita que la gente de GfxBuilder haya dado por bueno un código del que ni siquiera han hecho un ejemplo básico para verlo funcionando.

Y seguimos pintando gráficos. Al no poder usar polyline, me dije, voy a pintarlo a base de muchos line. Hago el código, pruebo… y el gráfico sale vacío, sin errores ninguno, pero vacío. Reviso el contenido de los datos y es correcto, están dentro de los rangos de pixels de la pantalla y demás. Empiezo a probar cosas y en un momento dado se me ocurre dibujar junto a mis líneas una elipse usando la primitiva ellipse y curioso, me sale le elipse… y todas las líneas que antes no salían. Borro la línea de ellipse y entonces no sale nada. Pongo un circle y ya sale el círculo y las líneas. ¿Es posible que las líneas no salgan si no se dibuja además otro tipo de cosa que no sea una línea?

Bueno, pues el gráfico ya va avanzando, me ha costado más de lo debido por este tipo de cosas y seremos comprensivos con el asunto. GfxBuilder es joven y todavía está en version 0.2.3, por lo que entiendo está todavía en desarrollo y, por lo que veo, con "sus cosas".

Mar 17

Vuelta a los viejos tiempos

Hace un mes algo cambio en el trabajo. Mi grupo, en vez de seguir adaptando nuestro software de siempre a los distintos proyectos en curso (y corrigiendo las incidencias que siempre salen), hemos pasado a realizar software nuevo. Eso me ha llevado a decidir usar TDD, y para la parte de interface de usuario probar fest-swing, y a meterme con izpack para generar los instaladores … y cogida la inercia de probar las nuevas cosas que siempre he querido aprender/aplicar y no he podido, me he lanzado a probar más cosas, en casa y sin tener nada que ver con el trabajo. Openmap primero, tText después, lo de la google app engine con python, etc.

Al final me he decidido a hacer un pequeño tablero Kanban usando Grails. ¿Por qué Grails?. Pues simplemente porque no lo conozco. ¿Por qué subirlo a github? Pues porque nunca he usado git.  Y la verdad es que me ha enganchado bastante todo esto. Llevo varios días en casa programando hasta la una o las dos de la madrugada. Para alguien como yo, acostumbrado a irse a la cama sobre las once, eso son horas realmente intempestivas. Y desde los viejos tiempos de la universidad que no me quedaba programando hasta esas horas.

¿Qué tal con Grails?

La verdad es que me ha decepcionado un poco. La primera impresión con las primeras pruebas fue muy buena, con poco tiempo y pocas líneas de código se pueden hacer muchas cosas. Pero resulta que uso Google Chrome como navegador y tengo de pantalla de inicio una en la que salen las páginas más visitadas. Pues bien, rápidamente la página que muestra las excepciones de mi aplicación se ha convertido en una de las más visitadas y es un poco deprimente.

Por un lado, groovy, el lenguaje de grails, no es fuertemente tipado, por lo que los IDE no dan un auto-completar demasiado completo, cosa imposible si en ningún sitio aparece el tipo de la variable. Esto hace que los errores de sintaxis al escribir nombres de métodos o atributos estén a la orden del día y no los descubres hasta que compilas, aparte de tener que navegar por el código para ver cómo era el nombre exacto.

Además, grails entiende/busca ciertos atributos en las clases para hacer cosas, como hasMany, allowedMethods, belongsTo, etc. Pues bien, nuevamente un error de sintaxis al escribir alguno de estos puede darte quebraderos de cabeza un rato. Compilar, compila, pero luego un tablero kanban no "hasmany" pegatinas dentro y te sale vacío.

La documentación de grails es bastante escasa. Si un tablero hasMany pegatinas, grails añade automáticamente de alguna forma el método tablero.removeFromPegatinas(). Pues bien, navegando por la documentación de grails no he encontrado ningún ejemplo de ese método, pero curiosamente, buscando en google, he llegado a un sitio de la documentación de grails donde sí pone el ejemplo (me hace la impresión de que es una documentación antigua que google encuentra, pero no está enlazada desde la documentación principal). Pues usas el ejemplo tal cual y no funciona, da errores de "deleted object would be re-saved by cascade". Buscando en los foros, veo que es un error que sale con frecuencia y no he visto en ningún foro que alguien dé una solución definitiva. Y lo peor no es que me dé ese error, porque si hago algo mal es normal que me de error, lo peor es que lo da de forma aleatoria en una misma ejecución. En una misma ejecución creo pegatinas, las borro, y unas las borra y otras falla, pero después de fallar, las vuelves a borrar y esta vez sí las borra … o no. Si grails tiene éxito y se usa, estoy seguro que algo estoy haciendo mal, pero desde luego, la documentación no ayuda a descubrirlo.

No todo es malo. Tiene muchísimas cosas que hacen el trabajo más rápido y más fácil. Por ejemplo, si una clase persistente en base de datos tiene los atributos nombre, apellidos y telefono, grails permite hacer consultas con métodos findAllByNombre(‘nombre’), o findAllByNombreAndApellido(‘nombre’, ‘apellido’) o findAllByNombreBetween(‘nombre1′,’nombre2’) y cualquier combinación larga y extraña que se te ocurra con los atributos de la clase, siguiendo ciertas reglas.

Seguiré jugando unos días con grails y la aplicacioncilla que estoy haciendo,

Nov 26

Alucinando con Grails

El otro día me puse a jugar con Grails, símplemente por ver de qué iba, y me he quedado alucinado.

La instalación realmente sencilla. Un zip a desempaquetar y poner un par de variables de entorno.

Luego generar una aplicación "hola mundo". Basta un comando sencillo para crear todos los directorios del proyecto, incluidos los ficheros del proyecto eclipse correspondiente.

El único código que hice para el ejemplo fue una clase groovy con un par de atributos y un controlador por defecto, que no es más que otra clase groovy con una única línea de código para poner a true una ¿variable? Y listo, ya está la aplicación "hola mundo" lista para arrancarse.

Se arranca y se arranca un pequeño servidor web de prueba con tu aplicación. Entras en el navegador y tienes una página web en la que aparece una lista de tus entidades almacendas en base de datos, con posibilidad de crear, editar y borrar dichas entidades desde el navegador, funcionando todo bonito y a la perfección.

Y eso es la primera cosa que me alucinó: Ha creado automáticamente unas tablas en una base de datos (HSQLDB por defecto) y ha creado toda la interface de usuario (web) para poder leer y modificar dicha tabla. Quizás la aplicación no es muy útil o exactamente lo que queremos, pero desde luego es una forma muy rápida de tener el esqueleto con lo básico.

Animado por este éxito, me pongo a investigar cómo se hacen dos entidades relacionadas entre sí. También es muy sencillo. Basta crearse la nueva clase groovy para la nueva entidad y poner algún atributo static "raro", que dice "hasMany", "belongsTo" y/o "mappedBy" y ya está hecha la relación. Nuevo controlador para la nueva entidad …. y nueva cosa alucinante: sin necesidad siquiera de rearrancar el servidor, se recrean las tablas, incluida la asociación y toda la interface web para manejar ambas entidades y las relaciones entre ellas.

En cuanto a la interface web, hay una por defecto para todo esto que no se ve, pero con un comando de grails podemos generarla para dejarla visible y podemos tocar en ella para modificarla o rehacerla entera a nuestro gusto.

Y ahí es donde me tropecé y me paré. No tengo ni idea de groovy ni de gsp (lenguaje que usa grails para la interface web y que imagino que el nombre viene de jsp al que han cambiado la j de java por la g de groovy), así que cualquier cambio no trivial (y muchos de los triviales) se me hace un mundo. De todas formas, parece una opción más que interesante para el desarrollo rápido de aplicaciones web. Sólo el hecho de que te puedas despreocupar casi totalmente (y digo casi sólo por precaución) de la base de datos y de su existencia, ya merece la pena.