domingo, 11 de julio de 2010

GWT o como facilitar la vida al programador de Javascript

Buenos días a todos, me dispongo a escribir esta entrada escuchando el nuevo de Kylie Minoge (Aphrodite) del que me gusta especialmente esta canción:
Y sin más dilación entraré a tratar en el tema que me ha traido hoy con vosotros, Google Web Toolkit, GWT a partir de ahora. Como muchos de vosotros sabréis, o quizá no tantos, este producto de Google es una herramienta que facilita/abstrae al programador web del tedioso mantenimiento del Javascript, pues cuando no se usa un buen framework para el desarrollo de Javascript, como Joose, del que nos habló Javi hace tiempo, que permite realizar programación orientada a objetos en Javascript resulta dificilisimo encontrar errores y mantener ese código. Cito directamente de la página de introducción del GWT, que aunque sea de la versión 1.7 sirve para resumir lo que quiero decir:
Actualmente, la creación de aplicaciones web resulta un proceso pesado y propenso a errores. Los desarrolladores pueden pasar el 90% de su tiempo estudiando las peculiaridades de los navegadores. Por otra parte, la creación, la reutilización y el mantenimiento de una gran cantidad de componentes AJAX y bases de código JavaScript pueden ser tareas complejas y delicadas. Google Web Toolkit (GWT), especialmente en combinación con el complemento de Google para Eclipse, facilita estas arduas tareas al ofrecer a los desarrolladores la posibilidad de crear y mantener rápidamente aplicaciones JavaScript con interfaces complejas, pero de gran rendimiento, en el lenguaje de programación Java.
Aunque a mi me parece que el 90% del tiempo en entender las particularidades de cada navegador me parece una super exageración, si es verdad que los componentes en cada navegador funcionan de una forma distinta, permitiendo GWT abstraernos de estos detalles.Además facilita el desarrollo de la progración con AJAX.
Si a alguien le ha resultado interesante este componente y quiere ponerse manos a la obra tan solo tiene que empezar por esta pequeña introducción en la que los chicos de Google nos cuentan como empezar a trabajar con esta herramienta, como se integra con eclipse y otros aspectos fundamentales de la configuración. Aunque en la página anterior no venga como integrarlo con Netbeans, en el propio blog de google tienen una entrada contando como realizar una aplicación GWT en este entorno de desarrollo.
Una vez terminados estos pasos, es recomendable ver el tutorial que explica como hacer la primera aplicación Web. Otra de las ventajas que tiene usar GWT es que permite el uso de JUnit como framework para realizar las pruebas unitarias, y como todos sabemos es una herramienta indispensable. Aquí he encontrado como integrar GWT con JUnit.
Poco más que decir de este framework que se ha convertido en mi herramienta de trabajo en estos meses que llevo ya trabajando en Qwi. Solo me queda por decir que de vez en cuando se echa de menos programar tu propio Javascript aunque gracias a JSNI se puede introducir el código javascript queramos. Por otro lado hay veces que me gustaría poder moldear a mi gusto las estructuras HTML que genera, pues hay veces que crea estructuras que no son necesarias para lo que queremos construir en un momento dado. Es verdad que con GWT con UiBinder que permite definir la estructura de la página en un xml y luego en la clase java asociada tratar los elementos que hemos definido, por decirlo de alguna manera, dinámicos, es relativamente fácil controlar las estructuras generadas.

miércoles, 9 de junio de 2010

ManyToMany en Hibernate con anotaciones

Muy buenas a todos, ya se que me echabais de menos, así que he decicido volver a escribir por aquí. En esta ocasión os voy a contar como representar con Hiberante una tabla Many To Many, pues ha sido una de las cosas que más me han dado la lata en el nuevo curro.
Para entrar en situación voy a exponer un pequeño ejemplo con el que todos los labos y ex-labos estaremos familiarizados:
Supongamos que por una extraña razón a Geno se le juntan muchos marrones encima (cosa que no pasa casi nunca ;)) y por otro lado están (estabamos) todos los precarios, entonces le encarga a Rafa que los reparta de una forma sencilla. Rafa como está apuntito de casarse piensa que lo mejor es hacer una aplicación sencilla para que Geno la pueda utilizar y le deje escribir su tesis, que aunque él cree que la lleva bien aún le queda por escribir unas 100 páginas.
La aplicación será llamada Brown Dispatching y su modelo de datos generaría unas 3 tablas:
  • Una tabla para cada miembro del labo, donde podríamos incluir el nombre del precario, el nombre de la máquina, las horas que está o cualquier otra información que pudiese resultar útil para esta situación. En el caso del ejemplo, creo que con el nombre bastaría, además que somos pocos y nos conocemos perfectamente.
  • Otra tabla para cada marrón, indicando el nombre, una descripción y una fecha límite por poner unos campos de ejemplo.
  • La tercera tabla sería la que finalmente enlazaría a los marrones con los precarios. Por lo que tendría unicamente el identificador único de marrón y el identificador único de usuario.
Gracias a Hibernate, esta tercera tabla no habría que implementarla, pero si que deberíamos implementar las otras 2 entidades. A partir de la versión 1.5 existe una opción para meter anotaciones en el propio código del Bean y éste ha sido el método que he elegido yo para realizar el ejemplo.
imports ...
@Entity
@Table(name = "T_PRECARIOS")
public class Precario implements IGwtSerializableParameter {

 private Long id;
 private String name;
 private Set browns;

 // ID SETTER AND GETTER
 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 @Column(name="ID")
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }

 // NAME SETTER AND GETTER
 @Column(name = "NAME", nullable = false)
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }

 // BROWNS SETTER AND GETTER
 @ManyToMany(
   cascade = { CascadeType.MERGE,
      CascadeType.PERSIST },
   fetch = FetchType.EAGER
   )
 @JoinTable(
   name = "T_PRECARIOS_BROWNS",
   joinColumns = { @JoinColumn(name = "PRECARIO_ID") },
   inverseJoinColumns = { @JoinColumn(name = "BROWN_ID") }
   )
 public Set getBrowns() {
  return browns;
 }
 public void setBrowns(Set browns) {
  this.browns = browns;
 }
 ...
}
import ...
@Entity
@Table(name = "T_BROWNS")
public class Brown implements IGwtSerializableParameter {

 private Long id; // Unique identifier for brown
 private String name; // Brown's name
 private String description; // Brown's description
 private Date finalDate; // Brown's final date
 private Set precarios; // Set with the "precarios" associated

 // SETTER AND GETTER FOR ID
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "ID")
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }

 // SETTER AND GETTER FOR NAME
 @Column(name = "NAME", nullable = false)
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }

 // SETTER AND GETTER FOR DESCRIPTION
 @Column(name = "DESCRIPTION", nullable = false)
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }

 // SETTER AND GETTER FOR FINAL DATE
 @Column(name = "FINAL_DATE", nullable = false)
 @Temporal(TemporalType.DATE)
 public Date getFinalDate() {
  return finalDate;
 }
 public void setFinalDate(Date finalDate) {
  this.finalDate = finalDate;
 }

 // SETTER AND GETTER FOR "PRECARIOS"
 @ManyToMany(
   mappedBy = "browns",
   cascade = { CascadeType.MERGE,
      CascadeType.PERSIST },
   fetch = FetchType.EAGER
   )
 public Set getPrecarios() {
  return precarios;
 }
 public void setPrecarios(Set precarios) {
  this.precarios = precarios;
 }
 ...
}
En modo de anotaciones de Hibernate, las notaciones se pueden poner en la definición del atributo o en el Getter del mismo, como se puede ver yo he elegido ponerlas en el getter.
Las anotaciones más importantes para el ejemplo que he traído son las asociadas a los Set (de java.util). En estas se representa que tipo de unión se quiere entre las entidades.
En la entidad Precario, se define por un lado el tipo de unión que se va hacer entre las tablas, con los atributos cascade y fetch en la anotación ManyToMany, mientras que en la anotación JoinTable se indica el nombre de la tabla resultante de hacer el join de las entidades y el nombre de las columnas. En la entidad Brown, se define simplemente el ManyToMany indicando que atributo de la otra clase modela está relación, y se indica el tipo de unión que se realiza.
Creo que esto es suficiente clase sobre Hibernate de momento, pero si alguien tiene alguna duda/sugerencia al respecto soy todo oídos. Por cierto, puede que haya alguna manera más eficiente para modelar esto, pero no se me ha ocurrido un ejemplo que modele mejor las necesidades de crear un ManyToMany, y también puede ser que haya forma mejor de realizar el ManyToMany dado que apenas llevo unos meses con Hibernate y no soy ni mucho menos un experto. Aqui solo he tratado de plasmar mi experiencia con esto. Un saludo!

miércoles, 2 de junio de 2010

Abajo esas etiquetas

Yo creo que a todos nosotros, a modo de introducción, nos dijeron que el HTML/XML es un formato de texto plano fácilmente legible y editable por humanos en el que se puede formatear cualquier documento. Nos mintieron. Si editar HTML cumpliese esas promesas no utilizaríamos procesadores de texto ni se editaría la Wikipedia en wikicode, ni las entradas de los foros en BBCode.

Cuando preparamos un fichero README al distribuir software, la tradición manda que esté escrito en texto plano y a no más de 80 columnas para que pueda ser utilizado en el mayor rango posible de situaciones (adicionalmente se pueden incluir versiones en HTML o PDF). Hoy me gustaría recomendaros el formato markdown para este tipo de tareas porque tiene una sintaxis simple, existen herramientas para traducir los documentos a otros formatos y por encima de todo, es un formato directamente legible.

Existen muchos ejemplos en github, una web que se merece un apunte propio, puesto que soporta markdown y permite visualizar en texto plano o el resultado de procesarlo.

Como ventaja adicional, el hecho de adoptar markdown nos facilitará el ser consistentes con la notación de los documentos.

Algunas herramientas que podemos usar son el propio paquete markdown (debian | script en perl), pandoc (diversas conversiones), htmldoc (para pasar a pdf un html) y muchas otras utilidades. A la hora de editar markdown desde vim, podemos utilizar un poco de magia de vim.org: http://www.vim.org/scripts/script.php?script_id=2882

viernes, 21 de mayo de 2010

Git en tu prompt

Ultimamente, GIT está causando furor entre los miembros del labo. Aunque el cambio desde Subversion puede ser algo traumático si no se digieren bien los nuevos conceptos, el cambio de paradigma hacia el control de versiones distribuidos merece mucho la pena. Una buena introducción es el libro online Pro Git (recomendación vía Álvaro).

Hoy quiero compartir un snippet que permite personalizar el PROMTP de bash para que muestre en que rama de un repositorio GIT estamos trabajando y un asterisco si tenemos cambios pendientes. Para usarlo, basta con que lo copiéis a vuestro home y lo llaméis desde el .bashrc.

Como característica extra, el prompt cambia de color si abrís una shell de root para que no se os olvide cerrarla.


Actualización: si utilizáis el git desde los ports de mac, echadle un vistazo a este hilo para habilitar el comando __git_ps1

martes, 11 de mayo de 2010

Remontadas

Los sistemas de ficheros compartidos por red son muy útiles a mi me simplifican mucho la tarea de almacenar copias de seguridad en una máquina diferente. Basta con tener montada la partición y usarla como si fuese local.

Sin embargo, cuando hay problemas de red o cortes de luz puede ser necesario montar o remontar esas particiones y se puede tardar bastante tiempo en detectar si no se tiene cuidado. Una forma de atacar el problema es tener a mano un script en el cron. A continuación pego el que acabamos de poner en funcionamiento en el labo:

Podéis probarlo con la opción --verbose para ver qué hace paso a paso y que puede resumirse en comprobar si el montaje esta ido o desmontado y actuar en consecuencia. No olvidéis sustituir los puntos de montaje al principio del script!

lunes, 26 de abril de 2010

Limpiar ficheros en Python

¿No os molestan los ficheros, en general de código fuente, que están llenos de espacios al final de las líneas (los llamados trailing spaces) y otras degeneraciones varias: tabuladores mezclados con espacios normales, fines de línea estilo MS-DOS (retornos de carro) mezclados con otros UNIX, etc.? A nosotros sí.

Este es un problema que surge cuando un equipo trabajan sobre los mismos ficheros de texto, cada uno con su editor, en su sistema operativo... y entre Álvaro, Sebas y yo nos hemos propuesto solucionarlo.

Para ello, hemos creado un script en Python que toma como argumentos una lista indeterminada de ficheros y los "limpia". En concreto:

  • Elimina espacios y tabuladores al final de todas las líneas.
  • Elimina los retornos de carro estilo MS-DOS, para homogeneizarlos y que se vean "bonitos" en todos los entornos.
  • Opcionalmente, por medio del paso de un parámetro extra, se sustituyen los tabuladores de principio de línea por 4 espacios.
El uso es bien sencillo: 
python sanitize_nl.py [--retab] <fichero1> [<fichero2> ...]
...y listo. Ficheros limpitos y sin problemas.

Podeis descargarlo de aqui

jueves, 8 de abril de 2010

JSON con comentarios

JSON es un formato que permite representar estructuras de datos de una manera muy sencilla y compacta para su uso en aplicaciones web. El formato es deliberadamente simple y austero para evitar problemas, por ejemplo, sólo se utilizan comillas dobles y no se permiten comentarios.

Pero, ¿qué sucede si queremos utilizar JSON para representar configuraciones? Los comentarios son importantísimos y los parsers existentes no lo contemplan. Podríamos meternos en un infierno de expresiones regulares con los problemas que eso puede traer (las regex se quedan cortas para este tipo de trabajos) pero es mejor disponer de un parser adaptado a esta tarea.

Partiendo de la última versión del parser escrito en JavaScript de JSON.org hemos añadido los comentarios de línea (//) y bloque (/* */). Esta opción es más lenta que los parsers integrados en el navegador pero, a fin de cuentas, los ficheros de configuración no deberían ser enormes con lo que es un buen compromiso.

El resultado lo podéis descargar aquí: commented json parser. Para usarlo basta con incluir la biblioteca e invocarlo así:

var object = cjson_parse('{ "hola": /* adios */ "3", \n\
 "cumpleaños": "2009-12-12" // fecha temporal\n\
}');