miércoles, 26 de diciembre de 2007

Criteria Query en Hibernate

Uno de los puntos débiles que encontré en el nuevo estándar JPA (Java Persistence API de Sun), es que no provee una funcionalidad análoga al Criteria Query de Hibernate.

El Criteria Query nos permite definir consultas con un estilo orientado a objetos, muy distinto al clásico SQL o HQL. La primera impresión del API me resultó un poco extraña, difícil de leer. Por ejemplo, el siguiente query con Criteria:


List personas = sess.createCriteria(Persona.class)
.add(Restrictions.like("nombre", "Fede%"))
.add(Restrictions.isNull("edad"))
.addOrder(Order.asc("nombre"))
.list();
sería el equivalente a éste otro con HQL:

String query = "from Persona where nombre like 'Fede%' and edad is not null order by nombre asc";
List personas = sess.createQuery(query).list();

Sin dudas el query HQL es mas fácil de leer a simple vista, la versión orientada a objetos requiere un análisis mas detallado.

Pero por otro lado, que sucedería si la consulta tuviera que armarse dinámicamente?
Por ejemplo, si el usuario selecciona las opciones por las cuales desea realizar la búsqueda, entonces el "where" del query debemos establecerlo en tiempo de ejecución. En éste caso es dónde personalmente le encuentro una gran ventaja al Criteria porque podemos hacer cosas como:

Criteria criteria = sess.createCriteria(Persona.class);
if (nombre != null) {
criteria.add(Restrictions.eq("nombre", nombre));
}
if (edad != null) {
criteria.add(Restrictions.eq("edad", edad));
}
if (pais != null) {
criteria.add(Restrictions.eq("pais", pais));
}
List personas = criteria.list();

El código anterior define una consulta que toma como entidad base a "Persona" y luego dependiendo de si hay un valor asignado para nombre, edad y país agrega las restricciones al Criteria.

Para resolverlo en HQL deberíamos armar el query concatenando strings, que no está mal, pero puede inducir a errores en la definición, me parece que en estos casos es mas natural usar el estilo orientado a objetos del Criteria.

Además permite desarrollar un esquema de consultas genérico, donde el usuario del sistema "arma" su propio query sin mayor esfuerzo por parte del desarrollador, en próximos posts publicaré ejemplos.

martes, 18 de diciembre de 2007

Una avenida en India

El fin de semana pasado, mientras borraba archivos viejos, encontré un video que filmé en el año 2004 cuando tuve que viajar por trabajo a Bangalore, India. Lo recuerdo como si fuera hoy, mientras estaba en una avenida llamaba Mahatma Gandhi comencé a filmar el tránsito que pasaba, de repente sin haberlo planeado entra en foco una persona caminando de una forma sumamente extraña, como pueden apreciarlo en el video mas abajo.
Unos días después volví a ver a otra persona en la calle caminando de la misma manera, me comentaron que es un problema relativamente común en India que se da por la descalcificación de los huesos.

En algún post futuro voy a contar otras experiencias bastante extrañas que viví en India...

Groupthink y el fanatismo tecnológico

En el último Encuentro Genexus participó un expositor argentino llamado Silvio Szostak, director de sistemas de cervecería Quilmes, habló sobre los factores humanos que influyen en el éxito o fracaso de los proyectos de sistemas.
Por lo general en éste tipo de charlas se exponen situaciones que ya hemos vivido, lo interesante es que uno descubre que tienen nombre y las particularidades han sido investigadas por profesionales.

Uno de los temas presentados fue el fenómeno groupthink, estudiado por Irving Janis en 1972: "Un modo de pensar en el que los participantes se ven atrapados en un grupo que lucha por imponer la unanimidad, anulando la evaluación de alternativas".

Cuando nos fanatizamos con un tema perdemos objetividad y eso se profundiza si nos movemos en ámbitos donde la gente comparte la misma "camiseta", para decirlo en términos futbolísticos.

Por ejemplo, ahora que está de moda el tema de las papeleras en Uruguay, cuando los medios de comunicación van a Fray Bentos y consultan a los pobladores sobre su opinión con respecto a Botnia, a veces me da la sensación que algunos contestan presionados por tener la cámara delante, temen opinar negativamente y ser señalados como traidores a la patria. Lo mismo sucede del otro lado del río Uruguay en Gualeguaychú, pero al revés.

Por otro lado, en la informática, quién se atrevería en una reunión de usuarios linux a opinar que prefiere usar el Microsoft Project para gestionar proyectos frente a las opciones open source?
O en una charla de programadores "devotos" de .NET quién se animaría a decir que para desarrollar y hostear un carrito de compras se inclinaría por PHP?
Sería como que una persona confesara que adora las achuras a la parrilla en un país donde las vacas son sagradas...

En posts anteriores dí mi opinión sobre la Guerra de Plataformas y sobre Bilardistas vs Menottistas en la Informática, sigo pensando que cuanto mas nos alejamos de los dogmatismos y de las posiciones extremistas, mas nos enriquecemos como profesionales.
En lo personal, como desarrollador Java desde hace varios años, no me tiembla la voz al reconocer las agilidad de desarrollo y la independencia tecnológica que se logra con Genexus, o las ventajas de una plataforma como .NET que ofrece un IDE integrado con todo lo que el programador necesita. Aclaro que estoy muy conforme con la tecnología Java, pero eso no quita que reconozca y tome lo bueno de las otras opciones.

En un blog vecino, del grupo DevelUY, leí un post titulado Talibanes del Software Libre, realmente me causó gracia el juego de palabras. Quiero rescatar la idea, si dejamos los fanatismos para otras actividades y evitamos caer en el groupthink, seguramente nos va a ir mejor.

Les dejo el link de la exposición, se las recomiendo en su totalidad, en el minuto 48 aproximadamente es dónde se habla sobre el groupthink.

Hasta el próximo post!!

viernes, 14 de diciembre de 2007

Bilardistas vs Menottistas en la Informática

En el fútbol argentino siempre se habló de Bilardistas y Menottistas en cuanto a la estrategia seguida para llegar a los objetivos, y muchos hinchas se identifican con uno de los dos bandos.

Para los que no siguen el fútbol, les comento que César Luis Menotti y Carlos Salvador Bilardo fueron los directores técnicos que llevaron a la Argentina a ganar los mundiales del año 78 y 86 respectivamente. Ambos siempre estuvieron diametralmente opuestos en su pensamiento futbolístico:

A Bilardo se lo consideró un técnico "resultadista", capaz de usar cualquier medio para ganar, sin importar la "estética" del juego desplegado. Para los uruguayos sería alguien como Julio Ribas o Gregorio Pérez.

En cambio, a Menotti muchos lo consideran un "lírico", es decir que privilegia el "juego bonito" y no concibe los triunfos sin desplegar un buen espectáculo. Juan Ramón Carrasco sería quien mejor encarna ese pensamiento en Uruguay.

Si reflexionamos un poco sobre estos dos polos de pensamiento, podríamos ver que aplican a muchos ámbitos, en éste caso quiero referirme al área de desarrollo de software.
Como pasa en toda generalización, muchos pueden no sentirse identificados en alguna de las posiciones, pero acá va vamos...
Si tuviera que clasificar a los profesionales informáticos, lo haría de la siguiente forma:

Menottistas: Desarrollan software siguiendo las recomendaciones arquitectónicas a "rajatabla". Se los podría considerar dogmáticos o puristas, tratan de resolver todos los problemas aplicando patrones de diseño y no son afines a tomar atajos que estén fuera de los principios.
Prefieren frameworks de desarrollo altamente customizables y adaptables, la complejidad de uso de los mismos queda en un segundo plano en la elección. Generalmente optan por arquitecturas Java distribuidas y multicapa.

Bilardistas: Consideran que el software es una caja negra que debe limitarse a resolver las necesidades del cliente, en ese caso el objetivo está cumplido. Aplican una receta conocida y no dedican mayor esfuerzo a estar en línea con la tecnológica del momento. Son pragmáticos, generalmente prefieren el camino mas corto para resolver los problemas, aunque no sea lo recomendado en la bibliografía.
Prefieren herramientas CASE (por ejemplo Genexus) que resuelvan transparentemente las complejidades técnicas, o en su defecto eligen Visual Basic 6 por la simplicidad de su uso.

Aclaro que exageré un poco las descripciones para marcar las diferencias. Sinceramente no me siento completamente identificado por uno de los dos, aunque reconozco que en mis comienzos estaba mas cerca de lo que describo como Menottismo, ahora estoy mas en el centro.

Está claro que no todo es blanco o negro, solo pretendo reflejar dos posiciones que he escuchado muchas veces.

¿Ustedes se sienten representados por alguna de las clasificaciones?

miércoles, 12 de diciembre de 2007

Manejo de Fechas en Java

Éste es un tema que puede parecer básico, pero usualmente veo ejemplos en la web que utilizan estrategias totalmente "retorcidas" para formatear fechas o hacer operaciones con las mismas.

Desde hace un tiempo uso un framework que facilita el manejo de fechas en Java y se puede integrar muy bien con Hibernate. Le podemos decir adiós a las "transformaciones" entre java.util.Date y java.sql.Date, también al manejo del GregorianCalendar.

El nombre del framework puede resultar un poco extraño en español, pero les aseguro que no es una broma, se llama Joda Time.
Con solo agregar el jar en el classpath tenemos acceso a una infinidad de opciones para trabajar con fechas, por ejemplo:

  • Sumar/restar días, meses o años a una fecha
  • Obtener la diferencia en días entre dos fechas
  • Saber el día de la semana de una fecha (lunes, martes, miércoles...)
Siempre trato de no usar el API directamente, por lo general tengo dos clases que las llamo:
  • DateOnly (soporta manejo de fecha)
  • DateTime (soporta manejo de fecha-hora)
las mismas delegan las invocaciones a una instancia particular del framework, así evito estar acoplado al producto.

Para integrar el manejo de fechas con Hibernate, implementé dos UserType, éstas clases son las que tienen la lógica de mapear los atributos DateOnly de las entidades con sus correspondientes columnas en la base de datos.

Mas adelante voy a tratar de subir algún ejemplo de código para bajar un poco mas en detalle.
Les dejo el link de la documentación oficial.

Hasta el próximo post!!

Model Driven Architecture en Java

Simplificando su definición, la metodología MDA (Model Driven Architecture, especificada por el OMG) propone definir la funcionalidad de las aplicaciones de forma abstracta, independientemente de tecnologías, por ejemplo con UML; y luego dada la especificación de alto nivel, se podría "traducir" la misma a una implementación concreta en Java o .NET mediante una herramienta automatizada.

Hay varias herramientas que siguen el paradigma MDA, la mayoría muy verdes en mi opinión, aunque si leemos las presentaciones prometen el paraíso, los proveedores le "ponen color" a sus productos, como decimos en Uruguay.

Por ejemplo, el año pasado evalué AndroMDA, es una herramienta que permite tomar un modelo UML y transformarlo en componentes deployables para plataformas como J2EE y .NET. También incluye un kit para desarrollar generadores de código o personalizar los existentes.

En un momento estuve cerca de empezar a usar AndroMDA en mi trabajo, pero no me pareció conveniente porque ya teníamos un esquema de desarrollo definido y la personalización de los templates no era sencilla, en ese momento no había documentación suficiente, como pasa en muchos de los proyectos open source.
Por lo tanto me basé en varios artículos sobre code generation para desarrollar algo in-house.

Si analizamos los cronogramas de los proyectos, veremos que dedicamos un tiempo considerable en implementar ABMs (Alta, Baja, Modificación), cuando por lo general es una funcionalidad accesoria. Lo realmente importante son los casos de uso que involucran procesos de negocio, por ejemplo registrar una transacción bancaria.
Basándome en la premisa anterior, lo natural era comenzar a estudiar la automatización del desarrollo de los mantenimientos.

Lo primero fue llegar a un ABM estándar (como el "Work With" de Genexus), por ejemplo con: búsqueda, ingreso, detalle, modificación y eliminación de usuarios; siempre tratando de estandarizar los nombres de los componentes (páginas JSP, clases Java, etc).

El siguiente paso fue identificar los lugares que hacían referencia a la entidad en juego, para así poder definir un template y usar expresiones en esos lugares.

Luego del ejercicio obtuvimos los siguientes componentes de software:

  1. Usuario.java: Clase del dominio que define los atributos del usuario, declara los mapeos de Hibernate mediante XDoclet.
  2. ABMUsuarioAction.java: Action de Struts con todas las operaciones.
  3. UsuarioForm.java: ActionForm de Struts con los mismos atributos que la clase de dominio.
  4. usuarioForm.jsp: Página de ingreso, detalle y modificación.
  5. usuarioList.jsp: Página con filtro de búsqueda y grilla de resultado con acciones.
  6. UsuarioServices.java: Interface que define los servicios de la entidad.
  7. UsuarioServicesImpl.java: Clase que implementa la interface de servicios.
  8. UsuarioDAO.java: Clase que implementa las operaciones sobre la base de datos.
Como primera aproximación, podríamos crear los archivos del 2 al 8 a partir de la clase de dominio usando introspection para descubrir los atributos de la entidad, por supuesto si usamos el estándar JavaBean para nombrar getter y setters.

Como template engine elegí Velocity, me pareció muy sencillo usar, tiene un lenguaje llamado VTL que incluye estructuras de control, operadores y expresiones.
Por ejemplo, para generar la interface de servicio, definimos el siguiente template (resumido):

public interface ${upperEntityName}Services {
static final ${upperEntityName}Services INSTANCE = new ${upperEntityName}ServicesImpl();

${upperEntityName} buscarByID(Long id);
void eliminar(Long id);
void ingresar(${upperEntityName} ${lowerEntityName});
void modificar(${upperEntityName} ${lowerEntityName});
List buscarTodos();
}

Lo que está dentro de ${} son expresiones, Velocity maneja un contexto en el que podemos insertar objetos con un nombre asociado, en el ejemplo sería upperEntityName y lowerEntityName.

Para invocar al generador usé ANT, la tarea solicita al usuario el nombre de la clase de dominio con su paquete incluido y a partir de la misma usa los templates de Velocity para crear todos los archivos en los directorios correspondientes.

Hemos llegado a automatizar un 95% del desarrollo de los ABMs, siempre tratando de que el generador deduzca la mayor cantidad de cosas posibles a partir del modelo de dominio. Por ejemplo si la entidad define un atributo de tipo Date, es casi seguro que en la JSP de ingreso necesitaremos una caja de texto con un calendario javascript a la derecha y una validación por fecha.

El proceso de desarrollo "copy, paste & replace" se puede optimizar y si invertimos esfuerzo en automatizarlo, no hay dudas que se gana mucho en productividad.

Hasta el próximo post!!

martes, 11 de diciembre de 2007

Query Cache en Hibernate

En un post anterior comenté sobre la utilización del First Level y Second Level Cache en Hibernate, otra opción interesante para mejorar la performance y rendimiento de nuestras aplicaciones es el uso del Query Cache.

En ciertos casos, nos interesa "cachear" el resultado exacto de una consulta, no objetos individuales. Por ejemplo, si tenemos un método en un DAO que retorna la lista de Monedas registradas en la base de datos, es muy probable que siempre retorne el mismo resultado ya que esa tabla no cambia a menudo, entonces es recomendable establecer la consulta como "cacheable".

Hay que tener en cuenta que el query cache solo almacena los identificadores de los objetos del resultado, es decir que lo debemos usar combinado con el Second Level Cache.
Entonces para el ejemplo que venimos manejando, hay que realizar los siguientes pasos:

  1. Establecer el property hibernate.cache.use_query_cache=true en el hibernate.cfg.xml
  2. Configurar la entidad Moneda como "cacheable", según lo publicado anteriormente
  3. Establecer la consulta como "cacheable":

List monedas = sess.createQuery("from Moneda")
.setCacheable(true)
.list();

Por lo tanto, la primera vez que se ejecuta la consulta, se retorna la lista de Monedas desde la tabla mediante un select, pero a partir de ese momento toda vez que se repita el query, el resultado va a ser retornado desde el cache, evitando la comunicación con la base de datos.

Ustedes se preguntarán: ¿Que pasa si agrego una nueva Moneda? ¿El query dejaría de ser válido?
Si, así es, si agregamos una nueva Moneda pasando por la session de Hibernate, el query se invalida automáticamente para que la próxima vez que se ejecute la consulta vuelva a obtener el resultado desde la base de datos.
Es importante aclarar que el comportamiento anterior no se cumple si insertamos una Moneda por afuera del aplicativo, es decir con un insert directo a la tabla, o si tenemos dos aplicativos separados que apuntan a la misma base de datos, en ese caso habría que usar JNDI para que todos compartan la misma SessionFactory.

Como habrán concluido, es recomendable usar el query cache solo en los casos en que una consulta se repite constantemente y la entidad resultado no cambia frecuentemente, por ejemplo: Países, Estados, Tipos y Monedas.

En mi opinión, éste tipo de configuraciones son las que hacen la diferencia a la hora de evaluar el rendimiento o performance de los aplicativos desarrollados con Hibernate.

Hasta el próximo post!

viernes, 7 de diciembre de 2007

Opciones de Inversión en Uruguay

Este post no es sobre tecnología, solo quiero compartir algunas ideas sobre las opciones de inversión que tenemos los uruguayos cuando nos quedan algunos pesos y queremos hacerlos rendir.

Aclaro que no soy experto en el tema, solo quiero comentar algunas opciones que conozco, ninguna de ellas es para "hacerse rico" en poco tiempo, eso no existe.

En Uruguay hay una cultura muy fuerte de ahorrar en dólares americanos, generalmente en un plazo fijo bancario, aunque a partir de la crisis económica que sufrimos en el año 2002 muchas cosas cambiaron. La gente empezó a depositar sus ahorros en cuentas a la vista (cajas de ahorro, por ejemplo), o peor aún, "debajo del colchón" en su casa.

Tener el dinero fuera del circuito financiero tiene dos inconvenientes claros:

1. Inseguridad: Sigue siendo mas seguro tener el dinero en el banco que en nuestras casas, frecuentemente aparece en la prensa local gente que sufrió robos por tener el dinero en una caja fuerte detrás de un cuadro.
2. Nula rentabilidad: No se generan ganancias de ningún tipo.

Entonces, ¿que opciones de inversión tenemos en Uruguay?
Las que conozco son:

Plazo fijo: Casi todos los bancos ofrecen depósitos a plazo fijo en diferentes monedas: pesos uruguayos, dólares, euros y recientemente en unidades indexadas (es una unidad que se ajusta según la inflación de precios, por lo que teóricamente preserva la capacidad de compra del dinero).

Bonos del Tesoro: Son títulos de deuda pública (emitida por el estado uruguayo) a largo plazo con pago de intereses semestrales, tasas fijas o variables y una rentabilidad promedio del 6% al 7,5% anual. Están exonerados del IRPF.

Letras de Tesorería: Son títulos de deuda pública (emitida por el estado uruguayo) de corto plazo, desde una semana hasta un año. Asegura una buena liquidez sin variar los niveles de rentabilidad. Actualmente las tasas fluctúan entre un 3 y 5 % anual. Están exonerados del IRPF.

Obligaciones Negociables: Son títulos de deuda privada. Las empresas usan éste mecanismo para obtener fuentes de financiamiento y no depender del crédito de una institución. Tienen una rentabilidad entre un 8 y 11% anual. Alguna de las empresas locales que emiten ON son: Fábrica Nacional de Papel, COFAC y Zona América, entre otras.

Acciones: Constituyen parte del capital de una empresa, la rentabilidad es muy variable según los beneficios que la empresa obtiene a lo largo del tiempo.

Algo que debemos tener claro cuando invertimos es saber cual es el objetivo del ahorro, por ejemplo si es para comprar una vivienda, un auto, o simplemente para tener un respaldo económico en el futuro.

En los bancos de plaza hay sectores que se dedican a comercializar los productos financieros mencionados y además brindan asesoramiento, por ejemplo el BROU y el ABN AMRO Bank.

Hasta el próximo post!

Scheduler en Java

Algunas aplicaciones necesitan que ciertos procesos se disparen automáticamente, sin intervención del usuario, en éstos casos precisamos una herramienta que nos permita planificar su ejecución.

En Java hay varios frameworks que funcionan como "Scheduler" o "Planificador de Tareas", personalmente he usado en varios proyectos uno que se llama Quartz, y con muy buenos resultados. Es sencillo de configurar y no depende del ambiente en donde corre el aplicativo, funciona en todos los application servers, al menos en Tomcat y en JBoss no he tenido inconvenientes.

Los pasos básicos para configurar Quartz son:

1. Bajar el framework desde la web del proveedor e incluir las librerías requeridas en el aplicativo
2. Crear una clase que implemente la interface Job y en el método execute escribir la lógica que necesitamos ejecutar periódicamente
3. Instanciar un SchedulerFactory (se debería hacer cuando el aplicativo esta iniciándose) y registrar el job anterior. Por ejemplo si en una aplicación web tenemos un listener o un servlet que se ejecuta por única vez podemos usar el siguiente código:

StdSchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
JobDetail jobDetail = new JobDetail("exampleJob", Scheduler.DEFAULT_GROUP, ExampleSchedulerJob.class);
int hour = 17;
int minute = 50;
Trigger trigger = TriggerUtils.makeDailyTrigger(hour, minute);
trigger.setName("exampleTrigger");
scheduler.scheduleJob(jobDetail, trigger);
this.getServletContext().setAttribute("QUARTZ_SCHEDULER_KEY", scheduler);


En éste caso registramos la clase ExampleSchedulerJob (es la que tiene la lógica del proceso, implementa la interface Job) para que se ejecute todos los días a las 17:50 (makeDailyTrigger).
Además la clase TriggerUtils brinda varias opciones para configurar tareas semanales, mensuales, etc.

Para implementar casos mas avanzados les recomiendo la documentación de Quartz, es muy completa.

Hasta el próximo post!

jueves, 6 de diciembre de 2007

Cache en Hibernate

En éste post quiero compartir mi experiencia en el uso y configuración de la funcionalidad de cache en Hibernate, no es una guía paso a paso o una referencia técnica, simplemente voy a tocar algunos items que considero importantes.

Generalmente todos los cache se basan en almacenar objetos en memoria para acelerar accesos posteriores, pero debemos aclarar que en Hibernate hay dos tipos de cache: el First Level y el Second Level.

El First Level Cache es el que mantiene automáticamente Hibernate cuando dentro de una transacción interactuamos con la base de datos, en éste caso se mantienen en memoria los objetos que fueron cargados y si mas adelante en el flujo del proceso volvemos a necesitarlos van a ser retornados desde el cache, ahorrando accesos sobre la base de datos.
Lo podemos considerar como un cache de corta duración ya que es válido solamente entre el begin y el commit de una transacción, en forma aislada a las demás.
Hibernate lo maneja por defecto, no hay que configurar nada, si por alguna razón queremos deshabilitar o evitar el uso del cache, podemos usar un tipo especial de session: StatelessSession, se obtiene de la sessionFactory con el método openStatelessSession(). Yo la uso en el caso de los procesos batch, por ejemplo cuando tengo que hacer inserts o updates masivos, así evito que cada vez que hago el save de un objeto, el mismo me quede en memoria y en el correr del proceso se produzca un error del tipo OutOfMemoryError. La StatelessSession no interactúa con el First Level Cache ni con el Second Level Cache, es casi como si utilizáramos JDBC directamente.

En cambio el Second Level Cache nos permite ir varios pasos mas adelante en la mejora de la performance. La diferencia fundamental es que éste tipo de cache es válido para todas las transacciones y puede persistir en memoria durante todo el tiempo en que el aplicativo esté online, lo podríamos considerar como un cache global.
Para habilitar el Second Level Cache hay que realizar los siguientes pasos:

1. Seleccionar un Proveedor de Cache. Yo utilizo EHCache.
2. Agregar en el hibernate.cfg.xml los siguientes properties:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_structured_entries">true</property>

3. Poner en el classpath del aplicativo el archivo de configuración ehcache.xml, según las instrucciones del proveedor.
4. Agregar en el mapping de las clases que seleccionamos como "cacheables" la siguiente entrada:
<cache usage="nonstrict-read-write"></cache>

Hibernate define cuatro niveles de cache que determinan el aislamiento:

  1. transactional: Garantiza un nivel de aislamiento hasta repeatable read. Es el nivel más estricto. Solamente se puede utilizar en clusters, es decir, con cachés distribuidas.
  2. read-write: Mantiene un aislamiento hasta el nivel de commited.
  3. nonstrict read-write: No ofrece garantía de consistencia entre el caché y la base de datos. Es una estrategia ideal para almacenar datos que no cambian habitualmente y que no sean demasiado críticos.
  4. read-only: Es la estrategia de concurrencia menos estricta. Recomendada para datos que nunca cambian.
Otro tema importante es definir qué entidades vamos a "cachear", los candidatos naturales son por ejemplo las clases que representan: estados, tipos, países, monedas o similares.
Hay que tener en cuenta que cuando tenemos relaciones one-to-many hacia éstas entidades, debemos configurarlas como fetch=select, no como fetch=join porque si no Hibernate va a "levantar" la relación haciendo un join en lugar de intentar obtener el objeto desde el cache.

He tratado de simplificar al máximo el tema para que pueda ser un punto de partida, les recomiendo los siguientes links si están interesados en incorporar ésta funcionalidad a sus aplicaciones:
Hasta el próximo post!

lunes, 3 de diciembre de 2007

Guerra de plataformas

Es algo que se da inevitablemente, las discusiones sobre cual es la "mejor plataforma de desarrollo" se repiten constantemente, por lo general no conducen a nada porque prevalecen los dogmatismos y las personas tendemos a cerrarnos en nuestra posición y a no escuchar a los demás, bueno .... en realidad lo mismo pasa cuando hablamos de fútbol o política.

Actualmente considero que hay tres opciones consolidadas para desarrollar software empresarial a medida: Java, .NET o herramientas tipo CASE (por ejemplo Genexus), cada una con sus ventajas y desventajas.
Personalmente conozco mucho mas el mundo Java porque trabajo en él desde hace varios años, pero también he desarrollado en C# y soy analista Genexus, en cuanto a cual es mejor no tengo una respuesta definitiva, depende mucho del contexto del proyecto y de los recursos materiales/humanos que disponemos.

Lo que si es claro es que se han ejecutados proyectos exitosos con todas las tecnologías, en todo caso los fracasos se dan generalmente a causa de un relevamiento de requerimientos pobre o por una mala conformación del equipo de trabajo, no porque el proyecto se desarrolló en .NET en lugar de Java o viceversa.

Como dice el técnico de fútbol argentino Bambino Veira: "Se ha salido campeón con todos los sistemas tácticos, lo importante es tener buenos jugadores, que estén motivados y convencidos de lograr el objetivo", yo aplicaría esta frase también en nuestro ámbito.

Hasta el próximo post!

Trabajar en el exterior

En mi trabajo anterior tuve la oportunidad de viajar a Chile, India y Méjico durante un año en total para 3 proyectos diferentes, sin dudas fue una experiencia muy enriquecedora en todo sentido.

Aunque no todo lo que brilla es oro como dice el dicho, ahora que se viene el fin de año todavía recuerdo aquel 31 de diciembre de 2004, en pleno festejo tuve que acostarme temprano porque al otro día a las 8 de la mañana comenzaba un viaje interminable y en solitario hacia Bangalore-India, 3 escalas con 5 horas de espera en cada una, casi dos días de "safari". Ni hablar del cambio cultural que significó, desde la comida hasta la forma de relacionarse y encarar el trabajo. Fueron dos meses muy largos y duros pero no me arrepiento de haberlos vivido.

Este tipo de experiencias, mas allá de que pueden servir en lo económico, creo que nos hacen crecer en lo personal y como profesionales al obligarnos a salir de la "chacrita" y tomar otros desafíos.
De todos modos, para vivir me quedo con Uruguay, bendito país!! ... como dice el filósofo Sánchez Padilla ;)

Hasta el próximo post!

sábado, 1 de diciembre de 2007

Estimación de esfuerzo

Para mi es una de las áreas mas oscuras en el desarrollo de software, sigo siendo escéptico cuando me hablan sobre COCOMO y esas fórmulas "mágicas" con ponderadores que permiten calcular el esfuerzo de desarrollo en Java, Visual Basic o cualquier otra tecnología con solo un par de clicks.
Hay cientos de libros escritos sobre éstos temas y gente muy respetada que se dedica a la docencia, sin embargo no encuentro un método formal pero práctico de usar a la vez.

Cuando tengo que realizar una estimación de esfuerzo me baso en un esquema de clasificación de casos de uso por complejidad y luego según experiencias anteriores asigno una cantidad de horas/hombre para cada nivel. Eso nos da un esfuerzo aproximado de desarrollo, luego hay que sumarle otros items transversales a todo el proyecto, por ejemplo: ajuste del análisis, diseño, definición de la arquitectura, testing y documentación.
Además se presenta otro problema, estas estimaciones se hacen en horas/hombre, es decir imaginando que todas las tareas son realizadas por una sola persona en forma consecutiva. Inevitablemente luego vienen las discusiones cuando se pretende usar la matemática para hacer razonamientos como: "Si la estimación da 12 meses/hombre, entonces con 12 personas lo finalizamos en un mes", NOOO!!!.
En mi opinión ese cálculo simplificado no aplica en éste contexto, intervienen muchas mas variables, como por ejemplo la metodología a usar y la experiencia de las personas.

Generalmente cuando nos enteramos de nuevos proyectos, los vendedores ya han dicho "amén" a todos los requerimientos de los clientes, inclusive prometiendo plazos de entrega sin haber evaluado la factibilidad técnica. Así es como fracasan los proyectos, si desde que comenzamos a desarrollar ya estamos atrasados, los problemas no van a tardar en aparecer.
Seguramente la mayoría hemos pasado por ésto y lo seguiremos sufriendo si quienes se dedican a vender software no encuentran la manera de explicarle a los los clientes que no se trata de "soplar y hacer botellas", mas allá de las urgencias reales que puedan tener.

miércoles, 28 de noviembre de 2007

Carrera de Ratas en el Desarrollo de Software

Hace unos meses leí parte de un libro llamado “Rich Dad, Poor Dad” escrito por Robert Kiyosaki, en el que entre otras cosas habla sobre el círculo vicioso en el que entramos las personas por querer ganar mas dinero con el objetivo de mejorar el nivel de vida, pero a su vez para mantenerlo debemos trabajar cada vez mas y de ésta forma perdemos el foco de lo realmente importante.

Pero... ¿que tiene que ver ésto con la informática? ... bueno, en éste caso encuentro que lo que Kiyosaki llama carrera de ratas también se aplica al área del desarrollo de software, que es a lo que me dedico. No se si ustedes compartirán, pero siento que muchas veces nos distraemos en estar "agiornados" con las últimas tecnologías en lugar de concentrarnos en lo que realmente importa: resolver las necesidades de los clientes cumpliendo plazos de entrega y presupuesto con un producto de calidad. En la empresa donde trabajo tengo la libertad de incorporar nuevas herramientas, trato de estar atento a las tendencias del mercado pero solamente las incorporo si realmente agregan valor, me refiero a que el fundamento no se limite a "estar a la moda".

Por ejemplo, desde hace varios años desarrollo aplicaciones web basadas en Struts e Hibernate, utilizando una metodología basada en MDA (Model Driven Architecture), en posts futuros entraré en detalles. El hecho es que éste entorno lo tengo automatizado y hemos logrado una productividad alta, entonces me cuestiono si necesito migrar a JSF (Java Server Faces) o a otros productos novedosos como GWT (Google Web Toolkit). Tomando en cuenta las necesidades de los clientes, hasta ahora no hay razones que justifiquen el cambio, si bien se pueden encontrar críticas sobre Struts y comparaciones con otros frameworks MVC en las que puede salir perdiendo, personalmente convivo con sus defectos (que no son tantos) y aplico workarounds casi transparentes que no requieren demasiado esfuerzo. Otra cosa sería si comenzara a desarrollar desde cero, sin un know how acumulado, en este caso seguramente lo evaluaría desde otra perspectiva.

Por otro lado con Hibernate no tengo dudas, es por lejos el mejor framework open source que conozco, para quienes continúan usando JDBC como estrategia de persistencia les recomiendo que evalúen el cambio, pero tengan en cuenta que lleva tiempo dominarlo, no es cuestión de "tirarse a la piscina" en un proyecto complejo con recursos acotados.

Para terminar este post y como conclusión, creo que si bien no hay que estar al margen de las novedades, como profesionales debemos cada vez mas evaluar el costo/beneficio en su incorporación y evitar entrar en la "carrera de ratas" sin tener claro hacia donde nos lleva, simplemente por estar en la "cresta de la ola" o enriquecer nuestro CV.

domingo, 25 de noviembre de 2007

Primer Post

En éste blog intentaré compartir mi experiencia en el mundo de la Informática y además escribiré sobre otros temas de interés general. Soy uruguayo y me desempeño en el área de las Tecnologías de la Información, especialmente bajo la plataforma Java.