Historia de una integración (ii): La arquitectura

7 comentarios

El inicio de un proyecto siempre es un pequeño caos. Donde no había nada, ahora hay una multitud de cosas por hacer. Entre ellas, definir la arquitectura de la aplicación con la que guiar el posterior desarrollo. Para obtener la información necesaria, de forma paralela se debe iniciar también el análisis de los requisitos y contexto del proyecto.

La aplicación

La aplicación de esta historia -os recuerdo- es un front-end web Java que permite realizar acciones concretas sobre varios módulos de un sistema SAP.

Para no aburrir, resumiré los requisitos y el contexto del proyecto en
  • (i) aplicación dividida en módulos (uno por cada módulo SAP más un módulo Administración),
  • (ii) integración mediante webservices SOAP,
  • (iii) multiples servicios y todos, inicialmente, sin desarrollar ni definir su interfaz,
  • (iv) pantallas basadas en formularios web y tablas RIA,
  • (v) dos pantallas más complejas basadas en un potente grid de datos que permita manejar una gran cantidad de registros (alrededor de 200) sin paginación, ordenación por todas las columnas, modificación de algunos campos de forma inline y multiselección para ejecutar acciones sobre los registros seleccionados,
  • (vi) mantenimiento de una réplica sincronizada en base de datos de la estructura de centros y catálogo de materiales de SAP,
  • (vii) elevado número de usuarios, varios miles registrados, con picos de más de cien usuarios conectados simultaneamente,
  • (viii) ejecutable en IE6 y
  • (ix) equipo de desarrollo con dedicación parcial y formado principalmente en Hibernate y Struts.

Principios

La experiencia me ha enseñado la importancia de unas pocas reglas básicas que he convertido en los principios sobre los que procuro diseñar y desarrollar mis proyectos. Son estos:
  • Simplicidad (KISS, Keep it simple, stupid). En realidad una aplicación web no es nada compleja. Normalmente basta con aplicar el patrón de diseño MVC más una lógica y ordenada estructura de paquetes y clases. Y si la cosa se complica, no tener miedo de realizar los refactoring necesarios para volver a tener la complejidad controlada.
    Cuidado con la sobreingeniería. No te vuelvas loco con los patrones GoF si no estás creando un framework. Para una aplicación son más importantes los patrones GRASP.

  • Reutiliza, no repitas (DRY, Dont repeat yourself). Mucho cuidado con el copypaste y con el código pegamento y boilerplate. Utiliza detectores de código duplicado (pej. Checkstyle y PMD), crea componentes reutilizables y usa clases template para evitar el código boilerplate. El ejemplo más típico y dañino sería la gestión de conexiones y transacciones en base de datos.

  • Reutiliza, no reinventes (evita el sindrome NIH, Not invented here). Apache, Springsource, Eclipse, JBoss, Codehaus, Sun,... ¿de verdad no existe una solución éficaz a tu problema ya creada, documentada, probada y mantenida?

  • Diseña software facilmente testeable (TDD, Test Driven Design). Al menos las capas de negocio y datos deben poder ser probadas de forma sencilla, automatizada y sin necesidad de desplegar la aplicación en un servidor. No confundir con la metodología Desarrollo guiado por pruebas.

La arquitectura

La aplicación utiliza una arquitectura en N capas, estructurada en las capas de (i) integración con SAP, (ii) acceso a base de datos, (iii) lógica de negocio o middleware y (iv) presentación. A continuación pasaré a describir cada una de las capas y las tecnologías utilizadas en ellas.

Integración con SAP

El sistema SAP contaría con un XI, o infraestructura de intercambio, donde estarían definidos los distintos servicios web que usaría nuestra aplicación para realizar acciones concretas en los módulos SAP implantados.

Es la capa más importante. Al fin y al cabo es un proyecto de integración. No podía haber fallos ni improvisaciones. Así que para implementar los clientes webservices decidí usar Axis2. Es un framework que conozco muy bien, destaca por su madurez, rendimiento y sus altas capacidades de configuración y compatibilidad con casi todos los OXMs (Mapeador Objeto-XML) existentes.

Acceso a base de datos

La aplicación debía contar con su propia base de datos para la gestión de usuarios, datos propios y mantener una réplica sincronizada periódicamente de la estructura de centros y el catálogo de materiales gestionado en SAP.

A pesar de que el catálogo era enorme (cerca de 100 mil registros), el schema en sí no iba a contar con muchas tablas y era bastante sencillito. Por lo que el Oracle9 del cliente no iba a ser ningún cuello de botella.
Así que no ví mayor problema en usar Hibernate, con la esperanza de que nuestro supuesto dominio en él nos permitiera despreocuparnos relativamente de esta capa y ganar tiempo de desarrollo.

Middleware

Para implementar la capa de lógica de negocio no tuve muchas dudas, Spring como framework principal y dominante. Spring permite (i) integrar el resto de tecnologías que ibamos a usar y (ii) cumplir con los principios antes comentados, ambos de forma natural y sencilla. Además de aportar su motor de inyección de dependencias y sistema de AOP. En mi opinión, características básicas de cualquier desarrollo enterprise.

También hemos utilizado Spring Security como solución de seguridad, Quartz para las tareas programadas, la útil Commons Lang y el binomio Commons Logging/Log4j para el logging.

Presentación

Intentaré ser breve, como framework web decidí usar Struts1 (los motivos más abajo) para controlar la navegación hasta las pantallas principales.

Como sistema de plantillas para las pantallas, otro veterano, Tiles. Usar un sistema de plantillas es básico para mantener lo más simple posible las distintas jsps que formaban cada pantalla.

Dentro de cada pantalla está prohibido usar código Java, usamos Jakarta Taglibs como librería de etiquetas implementación de la estupenda especificación JSTL, la última gran especificación.

La parte RIA viene en 2 sabores, DWR y jQuery. DWR es un framework Ajax no muy conocido que permite invocar métodos de clases Java de la aplicación desde código Javascript en el navegador cliente. Es potentisimo, sencillo y muy configurable. Además cuenta con soporte para Reverse Ajax.

Mientras que JQuery aporta toda la magia visual con su legión de plugins y el tan necesario toque cross-browser. Destacar los widgets de jQuery UI y los plugins jQuery Validation y jQuery Grid.

Alternativas desestimadas

Ahora lo leo y parece sencillo. No lo fue. Dejaré las valoraciones para otro día...
Lo que sí voy a hacer es nombrar algunas alternativas que descarté durante el proceso de diseño y porqué.
  • Cualquier otro framework web. Sí, ya sé que Struts1 está pasadísimo, más muerto que SOA y el propio Java juntos, y hay otros frameworks web mejores. Pero eso no lo convierte en un mal framework y es él que domina mi equipo y yo mismo. Tampoco había tiempo para aprender otro y aunque lo hubiera, personalmente, no tengo claro cúal debería ser su sucesor, ¿Struts2, Spring MVC, GWT, Seam, JSFs, Wicket,...?
    Como ya he dicho sólo lo ibamos a usar para la navegación, así que nos sobraba.
  • OSGI. Sí es una aplicación modular, pero en realidad la necesidad de activar y desactivar módulos es practicamente nula.
  • JPA. ¿Para qué? Si vamos a usar Hibernate y punto. Y encima con características específicas como el Criteria o el delete_orphan. IMHO esta especificación llega tarde y además mal.
  • Ext-Js. No sólo es una delicia visual, es realmente eficiente en comparación con el resto de clones que han ido saliendo. De hecho, lo estabamos evaluando en otro proyecto más pequeño cuando nos pilló el cambio de licencia. Ahora usamos jQuery y estamos más que contentos.

Así que ya teniamos el entorno de desarrollo y el diseño general de la aplicación definidos. Era el momento de empezar el desarrollo. Pero eso ya será otro post...

Buenas prácticas para programar tests

1 comentarios
[MOD 090413: Modificación de propiedad Repetible]

En todo proceso de construcción moderno y profesional existe una fase de test o pruebas. Esta fase de test cuenta con total protagonismo, como demuestran el tiempo, recursos y herramientas dedicados. No hace falta pensar en la construcción de un puente, un avión o un formula1, piensa simplemente en el proceso de construcción de una batidora.

Este post es una recopilación de buenas práticas para programar tests. Es un pequeño granito de arena para ayudar a fomentar la fase de test en nuestro mundo del desarrollo de software.

Las buenas prácticas están clasificadas según su naturaleza. Y como siempre, son buenas prácticas sólo respecto a mi propia experiencia y criterio. Así que estáis más que invitados a participar.

Propiedades de un test

  • Automático. Todos los tests deben poder ejecutarse de forma automática.
  • Independiente. El resultado de la ejecución de un test no debe depender de la ejecución de otro test.
  • Repetible. El resultado de la ejecución de un test debe ser repetible en el tiempo. Para ello el test no debe depender de las circunstancias del contexto ni otros recursos. Si es necesario el test inicializará el contexto y recursos a un estado conocido o lo simulará mediante Mocks.

Estructura dentro del proyecto

  • El código de test debe ir contenido en una carpeta fuente distinta de la del código de la aplicación.
  • Una clase test debe pertenecer al mismo paquete que la clase de la aplicación que prueba. De este modo podrá ejecutar no sólo sus métodos públicos, sino también aquellos con modificador protected y package.

Código de test

  • El código de test debe tener la misma importancia que el código de aplicación.
  • Reutiliza código de test. Usa herencia, clientela y métodos estructurados para reutilizar ese código común que prepara el contexto, la entrada de los métodos o comprueba los resultados.
  • Una clase test debe tener un nombre significativo. Por lo general será el mismo nombre que la clase de la aplicación que prueba más el sufijo Test o Tests.
  • Un método test debe tener un nombre significativo que resuma claramente el caso de prueba u objetivo del test. Pej. es mucho mejor usar testBuscarProductosPorNombreNoExistente que testBuscarPr4.
  • Un método test debe probar un único caso de prueba.
  • El código de un método test debe ser comprensible y estar estructurado en (i) preparación del caso de prueba particular y su entrada, (ii) ejecución del caso de prueba (método a probar) y (iii) comprobación del resultado.
  • La longitud de un método test debe cumplir los estándares de codificación del equipo. En caso necesario, refactoriza extrayendo métodos reutilizables que ejecuten los pasos de preparación y comprobación.

Casos de prueba

  • No te limites al caso de prueba fácil.
  • Incluye casos de error como casos de prueba. Pej. crea casos de prueba donde la entrada es incorrecta, saltan excepciones o el resultado debería ser null.
  • Crea un caso de prueba para cada bug detectado.

La circunstancia

0 comentarios
Yo soy yo y mi circunstancia, y si no la salvo a ella no me salvo yo.

La filosofía de Ortega y Gasset nos transmite la importancia de las circunstancias y los puntos de vista para entender la vida y por tanto resolver cualquier asunto.

Si aplicamos esta filosofía a nuestro mundo del desarrollo software, podemos plantear que un proyecto es sus requisitos y su circunstancia. De modo que para convertir un proyecto en éxito, debe estudiarse y superarse primero su circunstancia. Sólo así podremos dar solución a los cambiantes requisitos.

La circunstancia de un proyecto estaría formada principalmente por las particularidades de todas las personas que intervienen en él, no sólo el equipo de trabajo, sino también el cliente, el usuario, el comercial, el administrador de sistemas,... todos.

Además del componente humano, también deben tenerse en cuenta los riesgos específicos potenciales y los requisitos no funcionales críticos.

La circunstancia debe ser un factor clave a la hora de elegir una tecnología y una arquitectura para desarrollar un proyecto. Ignorarla sólo puede llevarte al fracaso.

Estudia el proyecto desde todos los puntos de vista posibles y actua en consecuencia. Cómo si no podrá tu proyecto satisfacer las necesidades del usuario en cuanto a funcionalidad y usabilidad. Cómo si no podrá tu proyecto satisfacer las expectativas del cliente en cuanto a tiempo, coste y mantenibilidad.

Historia de una integración (i): El principio

9 comentarios
Esta es la historia de un proyecto de desarrollo software. Como toda buena historia tiene momentos difíciles, personajes complejos, un final féliz y más de una lección que aprender.

Antecedentes

En enero del 2008 comenzó una nueva etapa profesional para mi, cambié de compañía en búsqueda de nuevos retos y proyectos donde trabajar, y continuar aprendiendo, en lo que verdaderamente me apasiona, las nuevas tecnologías de desarrollo software. Atrás dejé una cómoda posición como Analista en una factoria de software al cargo de varios aburridos y antediluvianos proyectos de mantenimiento de una importante TELCO.

Así me encontré al frente de un equipo de desarrollo de 3-6 personas, residente en un importante cliente del sector sanitario público, y dirigiendo un buen número de proyectos Java, consistentes en nuevos desarrollos y mantenimientos.

Pero no sólo yo tenía ganas de cambios para el 2008. En una decisión tan valiente como inesperada, el cliente decide implantar un completo sistema SAP R/3 para sustituir la gran mayoría de sus sistemas de gestión.

Para esta obra faraónica se ha confiado en la típica pirámide de empresas, compuesta por (i) la super multinacional que aporta el nombre, más la élite, (ii) la cárnica el grupo hispano líder que aporta referencias de éxito en proyectos similares más la clase media y (iii) la empresa regional con aspiraciones que aporta el toque local, instalaciones y una masa de programadores a buen precio. Una organización digna de un imperio persa.

El proyecto

Mi parte en la historia sería la de dirigir un proyecto consistente en desarrollar una aplicación web Java que hiciera de front-end para varios módulos del futuro SAP R/3 del cliente. El proyecto empezó oficialmente en junio con la idea de llevarlo de forma paralela a la implantación de SAP. El objetivo era poner en funcionamiento una primera versión para el 1 de enero del 2009 para un número de usuarios controlado y poco a poco ir difundiendo su uso. A día de hoy la aplicación está implantada de forma completa y funcionando estable y eficázmente.

Como os imaginaréis ha sido una experiencia apasionante pero también muy exigente. Aunque me ha hecho pasar más de un trago amargo, en general estoy satisfecho con su resultado final y sobretodo con lo aprendido por el camino. Un camino que intentaré plasmar en esta serie de posts que espero se conviertan en un útil ejercicio de retrospectiva al que estais todos invitados.

Ecosistema software

No quería cerrar el post sin contar algo de verdad. Así que describiré las distintas partes que forman el ecosistema software que he ido construyendo desde mi llegada.
  • Eclipse. Una de las primeras decisiones que tomé fue usar Eclipse JEE como ide principal, por su potencia como editor e integración con el resto de herramientas y librerias que usamos. Anteriormente se usaba una antiquísima versión del IntelliJ IDEA pero no entraba en los planes corporativos adquirir licencias más modernas.
  • CVS. Es el sistema de control de versiones que tiene implantado nuestro cliente para todos sus proyectos. No hay más. Mi parte aquí se redució a fomentar algunas buenas prácticas de uso, principalmente a incorporar las dependencias de cada proyecto en su estructura.
  • Tomcat. Las aplicaciones se implantan en un servidor JBoss 3.2.6 y en un 4.2.2 las más recientes, pero en desarrollo usamos un Tomcat 6 como servidor individual por su mayor velocidad de arranque y fácil integración con Eclipse. Nuestras máquinas de desarrollo no son ninguna maravilla y Eclipse no se integra con JBoss 3.2.6 por si solo (sí con el 3.2.3), para ello necesitabamos las JBoss Tools. Pero entonces todo el entorno iba a pedales, cuando con Tomcat 6 vuela.
  • ANT. El cambio a Eclipse-Tomcat y el hecho de incoporar las dependencias a la estructura de proyecto obligó a crear nuevos scripts Ant para automatizar las tareas de construcción de los proyectos. Aunque sólo los nuevos proyectos y los antiguos más significativos han sido migrados al nuevo entorno.
  • Hudson. No fue hasta el último trimestre cuando conseguimos implantar Hudson como servidor de integración continua. Actualmente realiza las tareas de construcción, testing unitario y análisis de código Java con los plugins de Emma, Checkstyle y Findbugs.
  • JIRA. Como herramienta de gestión de proyectos/tareas continuamos usando una antigua versión de JIRA. Es una maravilla y eso que no creo que estemos aprovechando todas sus posibilidades. Sólo echo de menos un wiki principal para todos los proyectos o individual por proyecto.
Mis planes para este año implican las siguientes mejoras:
  • Selenium. Hemos estado experimentando con Selenium para hacer testing funcional de aplicaciones web. Sin embargo estamos teniendo problemas a la hora de ponerlo en funcionamiento en el Hudson. Lo que está dificultando mucho su aceptación y uso generalizado. Aún así lo encuentro básico para dar el siguiente paso de calidad en nuestro modelo de desarrollo. Todos sabemos el infierno que es actualmente el desarrollo web...
  • Maven. Aunque Ant es una herramienta genial, el elevado número y hetereogeneidad de proyectos que llevamos hace difícil el mantenimiento de los scripts. Por eso y otras razones quiero probar Maven en uno o dos proyectos serios.
  • Mylyn. Mylyn es un plugin para integrar Eclipse con la mayoría de sistemas de control de tareas/tickets de forma avanzada. No sólo permite tener visibilidad de los tickets en Eclipse, también dota de memoría a Eclipse para recordar qué ficheros del proyecto están asociados con cada tarea. Con lo primero espero, sobretodo, mejorar la trazabilidad entre lo que hace el código realmente y lo que dice la descripción de la tarea.
  • Wiki. Tengo ganas de probar una wiki para gestionar la documentación interna que vamos generando, en lugar de, como hacemos ahora, crear y copiar documentos word a una carpeta compartida. También me gustaría probarla como herramienta de especificación de requisitos de los proyectos con capacidades reales de colaboración y control de versiones automatizado. La idea sería enlazar desde la descripción de las tareas en el Jira a las páginas del wiki.
Con ésto doy por terminada esta primera parte de introducción y ecosistema. En la segunda me centraré en la arquitectura de la aplicación.

Evaluando WireframeSketcher, plugin Eclipse para diseñar prototipos de pantallas

8 comentarios
Me encuentro sumido en un nuevo proyecto, consistente en realizar una fase de análisis de una importante aplicación para gestionar de expedientes en un organismo público. Oh sí, metodología en cascada en toda regla...

Pero a lo que iba, una de las partes más importantes del entregable para el cliente son las pantallas, si no la más. Hasta ahora cuando me ha tocado hacer un esbozo de pantalla, alias wireframe, he sobrevivido con lo primero que he pillado. Pero esta vez, dada la cantidad de pantallas a hacer, me lo he tomado un poco más en serio y he descubierto esta pequeña maravilla: WireframeSketcher.

WireframeSketcher es un plugin para Eclipse que permite dibujar un wireframe de forma intuitiva, ágil y rápida. Muy rápida. Su paleta de componentes es muy completa, sirve tanto para aplicaciones web, como de escritorio. Destacar, también, una ayuda inteligente que te facilita alinear los componentes en base a guías. El acabado es estupendo, agnóstico a estilos y colores, como todo buen wireframe, y se exporta a PNG. Como muestra este screencast.

Requiere Eclipse 3.3. Se puede instalar de forma automática desde Eclipse usando http://wireframesketcher.com/updates como update site. Decir también que cuenta con su propia perspectiva y que de rendimiento va muy bien, no enlentece a Eclipse.

Aunque no todo iba a ser bueno. No es gratis. Pero tiene una versión de prueba permanente gratuita que lo único que hace es añadirte la marca de agua EVALUATION a las imagenes exportadas de las pantallas.
La otra buena noticia es que no es caro, 50-80 dolares cuesta una licencia. Para mí merece la pena, digo el dinero. Así que espero que mi jefe no ponga problemas.

Por qué Maven

9 comentarios
Maven es la última pieza que he decidido acoplar en mi entorno de desarrollo o ecosistema software. Para los que no lo conozcais, Maven es una herramienta para gestionar el ciclo de vida de un proyecto Java. Desde mi primer trabajo hasta ahora he estado usando Ant para esta tarea con excelentes resultados.

Entonces por qué cambiar

Soy un apasionado de la parte de construcción de proyectos, lo que en inglés llaman Build Engineering. Llevo ya muchos proyectos, de desarrollo y mantenimiento, de todos los sabores y algún sinsabor también, hasta proyectos con un único servidor de desarrollo compartido y proyectos cero automatizados. Así que he comprobado y sufrido la importancia del sistema de construcción de un proyecto. Hasta que punto es capaz de multiplicar la productividad del equipo, aumentando la velocidad y eficacia de ejecución de los procesos del ciclo de vida.
En mi opinión más importante que usar tal framework o tal otro. Aún más valioso si queremos realizar testing e integración continua. Y en definitiva el camino para convertir nuestra profesión en una verdadera ingeniería.

Por eso, en mi opinión usar Maven, sobre otras alternativas, aporta las siguientes ventajas.

Estandariza la estructura de directorios

Hasta ahora cada proyecto ha tenido una estructura arbitraria, basada en el criterio del lider técnico, en la estructura de generación del IDE corporativo o simplemente copiada de otro proyecto. Así es común encontrarse con que en cada proyecto un mismo tipo de fichero se encuentra en carpetas diferentes sin ninguna razón especial, dificultando el día a día de los que trabajan con varios proyectos de forma paralela.

Maven propone una misma estructura para todos los proyectos, pero permitiendo que pueda configurarse de forma personalizada en caso necesario (convención sobre configuración).

Estandariza el ciclo de vida

Si la estructura de directorio de cada proyecto es un mundo, del ciclo de vida ni hablamos. Cada proyecto tiene sus propias fases, con su nombre, orden y requisitos que hay que aprenderse...

Maven aporta una implementación de ciclo de vida. Sin tener que programar nada. De modo que ejecutar cualquier fase del ciclo de vida es siempre igual en todos los proyectos Maven. Para el desarrollador común aprender a manejar un proyecto Maven implica haber aprendido a manejar todos los proyectos Maven.

Además este ciclo de vida es extensible, permitiendo, en caso necesario, añadir tareas personalizadas implementadas en Java o Ant, entre otros lenguajes.

Reutilización

El año pasado implantamos Hudson como servidor de integración continua. Además de las tareas de test y construcción lo usamos para sacar informes de calidad de código y cobertura. Todo mediante scripts Ant. Pero nuestros proyectos son muchos, muy hetereogeneos y ninguno usaba checkstyle, findbugs, ni cobertura, así que no fue nada inmediato configurarlos para Hudson, no es que nos llevara horas, pero si un rato por proyecto al tener que añadir librerias y modificar el script Ant.

Mientras que con Maven si habría sido inmediato gracias a su sistema de reutilización, tanto de uso de plugins como de herencia de configuración. Fue el momento que empecé a pensar en serio en usar Maven, hasta entonces no me salian las cuentas ventajas/coste.

Integración

La integración de Maven con las herramientas y frameworks que usamos en la actualidad es total. Además de las citadas anteriormente están Eclipse, Selenium, CVS, SVN, Hibernate y Axis2.

Gestión de dependencias

Uno de los problemas más complejos a la hora de configurar un proyecto es la gestión de dependencias. Hasta ahora yo siempre he optado por incluir todas las dependencias en la propia estructura del proyecto y por tanto en el scm. A pesar de la posible redundancia y malgasto de espacio por tener muchas dependencias repetidas entre todos los proyectos.

Maven aporta un sistema de gestión de dependencias basado en repositorios y una fuerte configuración en el proyecto.


También destacar que Maven está basado en la experiencia, criterio y buenas practicas de la gente de Apache. Como puede apreciarse en las características que trae de serie, como filtering, perfiles, arquetipos, sistema multi-módulo y construcción del sitio web del proyecto. Y esto es todo, ya iré contando como me va...