Blog de SQUaC
Mañana miércoles, en el Encuentro Ideas Emprendedor 2.0
Abril 28th, 2009 - [Enlace local]
Manaña miércoles, 29 de abril, asistiremos al Encuentro Ideas Emprendedor 2.0: Internet como Oportunidad de Negocio que se ha organizado en el campus de la Universidad Politécnica de Valencia (UPV).
El acto contará con una charla de Eduardo Manchón, co-fundador de Panoramio y que actualmente trabaja en Google.
¡Nos vemos allí!
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
Historia de una integración (iv): Colaboración
Abril 27th, 2009 - [Enlace local]

Personajes
Esta historia tiene muchos personajes. Además de los usuarios, el cliente, mi equipo y mi jefe, están los distintos equipos de cada módulo SAP con su consultor a la cabeza. Y por supuesto el analista interlocutor del cliente, el llamado Product owner de Scrum, como nexo de todos.Él es el verdadero héroe de esta historia. Trabajador, comprometido, eficaz, comprensivo, dialogante mediador y afable. Rompe con todos las ideas preconcebidas que se pueden tener del cliente funcionario.
La clave para vencer la complejidad humana está en la colaboración. Parece fácil, al fin y al cabo todos teniamos el mismo objetivo: sacar el proyecto adelante.
Pero no sólo fue difícil, en algunos casos ha sido absolutamente agotador. Las personas mediocres tienden a adoptar una postura defensiva y esquiva, están más preocupados por salvar su culo que por el proyecto. Convierten cualquier asunto en una crisis y no se dan cuenta de que así sólo ponen más de manifiesto su ineptitud.
Afortunadamente también había buenos profesionales con los que ha sido una satisfacción trabajar. En realidad me voy a ahorrar los detalles. Supongo que lo entenderéis.
Comunicación
En cualquier caso la mejor forma de colaborar de forma productiva es cuidando la comunicación y las relaciones interpersonales. No hay por qué llevarse mal sólo por ser de diferentes empresas.Respecto a la comunicación me gustaría hacer una serie de observaciones/recomendaciones:
- Usa el medio de comunicación más adecuado. Cara a cara, teléfono o correo electrónico. El correo electrónico es el más flexible pero también es el más frio y propenso a malentendidos, tanto de significado como de actitud.
- Evita discusiones por correo, usa el teléfono y luego mandas un correo resumen.
- Comunícate con la persona adecuada directamente. Evita los intermediarios, simplemente ponles en copia o al tanto.
- Asegúrate 2 veces antes de señalar el fallo de otro.
- Incluye siempre toda la información relativa que puedas, como mensajes, capturas de pantalla, fecha y hora, etc.
- Ser amable o pedir disculpas no es pecado.
- Sé comprensivo. Ponte siempre en el lugar del otro. Piensa que no eres el único que tiene trabajo y que tú también te equivocas.
Problemática de un proyecto de integración
Los problemas técnicos de colaboración en un proyecto de integración se resumen en disponibilidad de entorno y de juegos de datos de pruebas. El entorno de desarrollo/pruebas no siempre está disponible. Y aún con el entorno disponible, no siempre existe el juego de datos requerido.Para minimizar esto lo mejor es usar Mocks que simulen el entorno y devuelvan los datos requeridos. De esta forma te independizas del entorno hasta el último momento, las pruebas de integración. Es la evolución del llamado hardcodeo.
Pero para que los Mocks sean realmente eficaces es necesario que los interfaces estén clara y explicitamente definidos. No sólo el nombre, tipo y orden de los campos de entrada y salida. También los formatos (fechas, cantidades, etc.). Esta definición debe hacerse en un lenguaje formal y procesable por una máquina para (1) evitar errores de interpretación y (2) automatizar la construcción de clientes y servicios. En el caso de los servicios web SOAP se usa el estándar WSDL.
Finalmente me gustaría destacar la importancia del documento Pruebas de integración. Debe estar actualizado y contener un completo juego de casos de prueba que cubra toda la casuística de entrada y salida. Incluidos los posibles errores. Además estas pruebas deben automatizarse cuanto antes para poder usarse como pruebas de regresión.
En resumen, las personas somos más difíciles que la tecnología. Por lo que colaborar no es sencillo. Pero es la única forma de sacar un proyecto adelante. Haz más fácil el trabajo de los demás y el tuyo será más fácil. No seas mezquino.
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
Historia de una integración (iii): El desarrollo
Abril 22nd, 2009 - [Enlace local]
El entorno de desarrollo estaba implantado, la arquitectura estaba definida, el análisis estaba en marcha. Era el momento de iniciar el desarrollo, antes de que el tiempo (y el cliente) se echara encima.
Pero pronto quedó claro que los servicios web SAP iban a tardar más de lo previsto. De hecho, ni siquiera disponiamos de los ficheros WSDL que describen el interfaz, que empezaron a llegar por cuenta gotas un par de meses después. Por supuesto, más de uno tuvo que ser modificado y remodificado. Esta situación nos obligó a ser extremedamente ágiles, cambiando la prioridad de los módulos, reconstruyendo los clientes webservices y modificando el modelo de la aplicación a menudo.
Metodología
No hemos seguido ninguna metodología concreta al pie de la letra. Aunque sí es cierto que nuestra forma de trabajar está ampliamente inspirada en Scrum y las prácticas ágiles que promueve. Sobre Scrum podeis leer más aquí y aquí.Os dejo algunas notas de la estrategia que utilizamos:
- Desarrollo incremental con una versión mayor por módulo. Empezando por el módulo de Administración.
- Los requisitos fueron traducidos en nuestro JIRA a tareas de tipo New Request dentro de la versión correspondiente. Los cambios en los requisitos fueron añadidos como tareas de tipo Improvement. Desgraciadamente cuando la versión estaba cerrada no siempre se añadían como tareas hijas...
- Simulación de los servicios web SAP mediante Mocks de los clientes webservices. Como ya he dicho los servicios no estaban, pero nosotros necesitabamos ya disponer de datos que pintar en las pantallas! Así que simplemente implementamos los interfaces de los servicios con unas clases tontas que devolvian datos más tontos aún. Mocking manual pero efectivo.
- Testing de la capa Middleware. Toda la lógica de la aplicación está en nuestras clases service que son llamadas desde las pantallas mediante DWR. Los controladores web (Actions de Struts) practicamente sólo realizan navegación y precarga de campos de formularios. Focalizar el testing en la capa Middleware permitió independizarse totalmente de la capa Presentación y el servidor de aplicaciones, aumentando así la velocidad de desarrollo global.
- Testing de la capa Acceso a base de datos. Para probar los distintos daos de esta capa usamos un script sql para inicializar la bbdd a un estado conocido junto con los tests transaccionales de Spring que automaticamente hacen rollback evitando la modificación del estado y la fácil configuración entre datasources dependientes e independientes del servidor de aplicaciones. Una más del montón de cosas que te facilita Spring.
- Integración contínua. Básico en cualquier fase de test seria. Además de actuar como control de calidad de nuestro código. Pero de Hudson ya hablé en su día...
- Estructura del proyecto. Para atajar la dificultad en un proyecto es básico tener una estructura inteligente y ordenada del mismo. Nuestra estructura de código fuente estaba formada por un gran paquete por módulo, más un paquete comun. Luego dentro de cada módulo, los subpaquetes web, dao, ws, modelo y services.
- Tags, branches y merges. El cambio de prioridades entre módulos que sufrimos más el desarrollo incremental por módulos podrían habernos costado más de un disgusto serio sin una buena estrategia de control de versiones.
Dificultades
Hasta aquí parece que ha sido un paseo, pero en realidad hemos sufrido lo nuestro también. A parte del tema de la colaboración con el resto de equipos, tuvimos que hacer frente a varias dificultades en:- Integración mediante webservices. Se veía venir. Sinceramente e IMHO, los servicios web SAP están, como mucho, diseñados regularmente. Abundan los datos duplicados e innecesarios, no existen namespaces ni schemas comunes y aún nadie me ha podido explicar por qué existe un servicio web por cada operación! Además los WSDLs son generados por alguna herramienta SAP de forma automática que no cumple el WS-I. Lo que nos obligó a usar XMLBeans como OXM (Databinding Java-XML), aunque esto no tiene nada de malo, y también a tener que modificar a mano un par de WSDLs. Y luego está el tema de la infraestructura de red del cliente en producción y sus proxys, pero ésto también lo he contado ya.
- Pruebas de los servicios web. Descubrimos muchos bugs en los servicios web SAP. Yo diría que sus equipos de desarrollo los probaban poco. Las modificaciones, a veces, ocasionaban nuevos bugs donde antes funcionaban. Pronto quedó claro que no tenían una fase seria de test. Al final tuvimos que programar nosotros las baterias de tests para los servicios web SAP.
- Gestión de requisitos. Sabiamos que los requisitos iban a cambiar. Pero no tanto. El sistema de gestión de requisitos antes comentado no favorece el control de cambios en los requisitos, es demasiado frágil y requiere demasiado trabajo en mantener la descripción de la tarea inicial y las hijas, además de mezclarse aspectos de descripción de funcionalidad con pura implementación. En el futuro probaremos con una Wiki para los requisitos y el JIRA para las tareas exclusivamente con referencias al Wiki.
- Formación. Inicialmente, y para mi sorpresa, el nivel de dominio del equipo en Spring e Hibernate era más bajo de lo esperado. Esto nos dió problemas especialmente en mapeos avanzados de Hibernate que provocaban que (1) algunas operaciones fallaran y (2) se realizaran más consultas de las necesarias. También destacar la dificultad, al principio, de trabajar con multiples ficheros de configuración Spring debido al número de módulos y las necesarias configuraciones para mocks y testing.
Luego la cosa mejoro. Aunque a día de hoy Hibernate sigue sin convencer a más de uno pero con Spring todos han caido rendidos.
- Proceso de sincronización. Todas las noches debe actualizarse una estructura de 7 tablas con PKs y FKs compuestas con casi 100 mil registros obtenidos mediante cientos de llamadas a 2 servicios web. Es una operación compleja y costosa, con o sin Hibernate. Fue necesario rediseñar los servicios web SAP para operaciones de consultas masivas que minimizaran el número de llamadas y optimizar los mapeos Hibernate así como los algoritmos usados. Al final pasamos de más de 1 hora de ejecución (tiempo inaceptable) a apenas 10 minutos.
- Testing en la capa de presentación. En su momento no conseguimos hacer funcionar los tests funcionales web basados en Selenium en nuestro servidor de integración contínua, así que esta parte de test se hizo de forma manual. Como la aplicación era una aplicación web RIA bastante grande que tenía que funcionar en IE6, sumado a los cambios de requisitos y modificaciones en los servicios web, os podeis imaginar lo que hemos pasado...
Creo que no me dejo nada. Los temas de colaboración e implantación proximamente...
» Leer más, comentarios, etc...
Blog de SQUaC
Nuestro primer día en el WWW2009
Abril 22nd, 2009 - [Enlace local]
Hoy hemos asistido en Madrid a nuestra primera jornada en el WWW2009, uno de los eventos internacionales más importantes (si no el que más) en lo que respecta a la web.
Puede hacerse un seguimiento en tiempo real del evento en Twitter, o ver algunas imágenes en Flickr. De nuestra experiencia personal, y en lo que respecta a la temática del blog, nos gustaría destacar esto:
- Tim Berners-Lee, uno de los fundadores iniciales de la web, ha insistido un par de veces... [sigue ...]
» Leer más, comentarios, etc...
DGG
7 razones por las que considero que un buen programador es más eficiente que 10 no tan buenos
Abril 18th, 2009 - [Enlace local]
No quiero empezar este post sin dejar claro que no me considero buen programador, probablemente tú si lo seas, pero antes te recomiendo leer este artículo : Diez señales de que no eres tan buen programador como piensas, al menos te hará dudar.
Estas son mis razones por las que defiendo que es mejor un buen desarrollador que 10 noramalillos:
- Con menos código generan más funcionalidad. Al diseñar mejor las clases y las funciones repiten menos código, así con menos líneas generan más funcionalidad. Al tener menos código fuente que revisar el tiempo empleado en detectar y corregir bugs se minimiza.
- Generan código más limpio y más fácil de leer. Al ser más sencillo de leer también es más fácil de extender y corregir bugs.
- Generan más código en menos tiempo. Conocen mejor el api y tardan menos en implementar las funciones.
- El código tiene menos proporción de bugs.
- Al utilizar (siempre que sea necesario) patrones de diseño su código es más fácil de extender y modificar.
- El código está mejor documentado y tiene mejores comentarios, por lo tanto, es más sencillo de extender o modificar por futuros programadores.
- Los programas son más eficientes. Conocen mejor la estructura de los diferentes tipos de datos y la complejidad de sus funciones, por lo tanto siempre los tendrán en cuenta a la hora de diseñar una función.
Por tanto, generan código más eficiente, en menos tiempo, mejor documentado, con menos bugs y mucho más sencillo de leer, extender y corregir.
Por todas estas razones me gustaría ser mejor programador.
Posted in Desarrollo, Gestión Tagged: programación
» Leer más, comentarios, etc...
Ideas + Ingeniería del Software
Postmortem: estimaciones y creación del sprint backlog
Abril 18th, 2009 - [Enlace local]
Estamos cerrando el último proyecto, una aplicación de gestión de datos con múltiples perfiles que controlan el trabajo y la información introducida por los demás. Acaba de entrar en explotación con bastante éxito: ni un error en los cuatro primeros días de uso, fundamentales porque corresponden con una primera fase que tiene un plazo límite. A partir de ahora, mantenimiento correctivo y algo de evolutivo.
Es un buen momento para comenzar el postmortem y analizar los errores cometidos.
Hemos usado Scrum como metodología, y la conclusión es que nos ha aportado tan poco como cualquier otra metodología que hubiésemos usado, pero al menos no ha molestado. No creo que nos haya aportado un auténtico valor, pero creo que estamos en el buen camino. El gran reto que teníamos para el desarrollo del proyecto era el uso de una pila de desarrollo nueva para casi todos, y contra eso no hay metodología que valga.
El product backlog se hizo a partir de las reuniones de contacto con los usuarios y de los primeros documentos de prototipado y requisitos que nos pasaron. Hasta ahí, bien, no es un artefacto que tenga mayor complicación.
Para estimar el product backlog hicimos planning poker con el equipo, tras haber contado de qué iba el proyecto. A todas luces la estimación era muy optimista, y se cumplió aquello de que los técnicos son positivos y que los gestores son pesimistas. Sin que sirva de precedente, los gestores tenían razón. Sin embargo, creo que si el mismo equipo volviese a comenzar el proyecto sí cumpliría las estimaciones que salieron de esa reunión. La experiencia en la tecnología y una mejor gestión de los requisitos habrían hecho que se hubiese podido implementar en los tiempos dichos.
Creo que nuestro gran error desde el punto de vista de la metodología fue la creación del sprint backlog. Lo hizo una persona (yo, como Scrum Master). Gran equivocación. Lo debe hacer el equipo en conjunto. El equipo careció de una visión global del proyecto, lo cual no trajo más que problemas:
- Se adquirieron tareas en el orden incorrecto.
- No se sabía qué era común y qué no, así que era más difícil organizarse para la reutilización.
- "Marchas atras" por mala comprensión de las tareas.
- Funcionalmente se depende del criterio de una única persona.
- La estimación de las tareas habría sido más acertada con un mejor conocimiento del problema.
- ...
- No es una tarea trivial, y es poco tolerante a errores. No pasa nada si haces mal un campo en una pagina, pero un error en el modelo de entidades puede tener consecuencias bastante dramáticas. Hacerlo exige un conocimiento profundo de los requisitos.
- Una equivocación de una persona puede tener un desagradable efecto de malentendidos de los requisitos en cadena.
- No es fácil compartimentar inicialmente para que la gente pueda trabajar independientemente.
- El product backlog lo hará el Scrum Master como esta vez, antes de la primera reunión (tampoco tiene sentido movilizar a más personas para él).
- En el sprint meeting el sprint backlog se hará entre todos los miembros del equipo. En vez de llevar a la reunión el sprint backlog prefabricado, leerlo, y estimar a partir de esa lectura, se generará durante ella, y tras la creación de cada tarea se hará la estimación de la misma. Sí, nos llevará mucho más tiempo, pero no será perdido, sino invertido.
- En caso de tratarse de una aplicación de gestión, probablemente durante el propio sprint planning se hará un modelo de entidades (entidades del sistema y su relación entre ellas, sin necesidad de entrar a nivel de propiedad). Algo muy básico, pero que permita tener un punto de arranque común y afianzar los requisitos. Eso sí, me mantengo en la opinión de que con Hibernate ya debemos trabajar en términos de entidades y no de tablas.
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
Tipos de programador
Abril 17th, 2009 - [Enlace local]
Me gusta simplificar las cosas. Es algo que no puedo evitar, cúanto más simple es algo, más perfecto me parece. Por eso el otro día cuando leía a Jeff Atwood exponiendo los 8 tipos de programador que según él existen, no pude evitar pensar ¡¿8 tipos para algo tan sencillo?! ¿¿8??
Me vino a la cabeza uno de mis antiguos posts donde hablaba de cómo valorar a los miembros de un equipo. Pero esto es diferente, son tipos de programador. Así que intenté borrar el post de Jeff de mi mente, sobretodo la parte de hacerse famoso... y llegué a la conclusión de que sólo existen 3 tipos de programador:
- El primer tipo sería el programador que es capaz de aprender por sí mismo.
- El segundo tipo sería el programador que es capaz de aprender con la ayuda de otros.
- El tercer tipo es aquel que no es capaz de aprender ni por sí mismo ni por los demás.
Es así de sencillo. Actualmente nuestro mundo vive una evolución imparable y un programador debe vivir en un estado de contínuo aprendizaje que le permita reinventarse a sí mismo en caso necesario.
Por aprendizaje no me refiero a memorizar por memorizar. Aprender implica descubrir y comprender nuevos conceptos para ser capaz de relacionarlos con conocimientos previos de forma coherente. El conocimiento se aumenta con conocimiento.
El primer tipo es un programador superior porque no depende de nadie. Es capaz de buscar, encontrar y aprovechar las fuentes de conocimiento que necesita por sí mismo. Su propio código es una de ellas porque tiene un potente espiritu crítico. Pero sobretodo tiene una vocación y un talento natural. Disfruta realmente programando, resolviendo problemas y experimentando.
El segundo tipo es un programador que tiene la inteligencia necesaria para convertirse en un excelente profesional. Todo dependerá de su actitud, porque aunque es capaz de diferenciar entre lo bien y lo mal hecho, debe esforzarse en aprovechar las oportunidades que se le presenten para aprender. Principalmente, gracias a sus compañeros, pero también un libro, un artículo en internet o el código fuente de un proyecto open-source que utiliza.
El tercer tipo es un programador cuyas acciones no tienen un porqué. No razona porque no aprende, sólo memoriza una parte. Va a lo fácil, a sobrevivir. Necesita constante soporte y supervisión. Hoy hace bien una cosa y mañana la misma la hace mal. Su código es fuente de la mayoría de bugs totales. Daña la moral del equipo. Y a la larga, resta más que suma.
En definitiva -insisto- el programador capaz de aprender por sí mismo es superior, el que es capaz de aprender con la ayuda de otros es brillante y el que no es capaz de aprender ni por sí mismo ni con ayuda de otros es inútil.
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
Historia de una integración (ii): La arquitectura
Abril 15th, 2009 - [Enlace local]

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...
» Leer más, comentarios, etc...
DGG
1.000.000.000.000.000 de conexiones de internet en 2019
Abril 13th, 2009 - [Enlace local]
En el año 2019 se estima que se el número de conexiones a internet superará al número de conexiones que existen en el cerebro humano. ¿Podría llegar Internet a pensar de la misma manera que lo hace un cerebro humano?
Un vídeo de Simón Hergueta.
Posted in Uncategorized Tagged: internet video
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
Buenas prácticas para programar tests
Abril 13th, 2009 - [Enlace local]
[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.
» Leer más, comentarios, etc...
Developing my life » desarrollo
ILO
Abril 11th, 2009 - [Enlace local]
Algunas pics que tomé cuando estuve por ilo …
Es todo por este post, nos leemos!
Tambien te puede interesar
» Leer más, comentarios, etc...
PHPBSD.net » webmaster
WordPress con el FeedBurner de Google y su maldito proxy
Abril 10th, 2009 - [Enlace local]
Hace tiempo escribí un post acerca de como usar FeedBurner para los feeds de un WordPress que se ha quedado algo obsoleto debido a algunos cambios en WordPress respecto a la URL de los feeds y a la compra de FeedBurner por parte de Google.
Si todavía crees que usar FeedBurner es una buena idea (yo nunca lo tuve claro) la forma más cómoda de configurarlo es modificando el archivo .htaccess, aunque también existen plugins específicos (por ejemplo el FD Feedburner Plugin).
Se trata de añadir lo siguiente al .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} !FeedBurner [NC]
RewriteCond %{HTTP_USER_AGENT} !FeedValidator [NC]
RewriteRule ^feed/(.*)$ http://feeds2.feedburner.com/xxxxxx [R,L]
Con lo anterior conseguimos que nuestro WordPress únicamente genere el feed para FeedBurner y que el resto de clientes (navegadores, arañas, etc.) sean redirigidos a la URL de FeedBurner.
Teóricamente este es el mejor método para usar FeedBurner ya que seguimos difundiendo la URL del feed original y así siempre podemos dejar de usar este servicio sin muchos inconvenientes. El problema está en que al haber la redirección muchos usuarios siguen el enlace del feed con el navegador y se suscriben a la URL del feed de FeedBurner… o sea que con el tiempo acabaremos con lectores suscritos a ambas URLs.
El método alternativo es modificar el theme de WordPress, o usar algún plugin, para difundir directamente la URL del feed de FeedBurner.
Proxy de Google
Si teníamos una cuenta en FeedBurner y la hemos migrado a Google recientemente, a parte del engorroso cambio de la URL del feed, quizás hemos notado que ahora la URL que difunde tu feed para cada post pasa por un proxy de Google.
En principio esto ya sucedía antes y el cambio únicamente es que ahora en lugar de pasar por feeds.feedburner.com pasa por feedproxy.google.com (aunque en mi caso antes de migrar la cuenta a Google no pasaba por ningún proxy, tengo caché, lo puedo demostrar :)
En cualquier caso si queremos desactivar completamente el proxy de Google hemos de cambiar la configuración de nuestro feed en FeedBurner. Concretamente se trata de desactivar la opción “Item link clicks” de la sección “TotalStats” dentro de la pestaña “Analize”. Con esto seguiremos teniendo estadísticas de número de lectores e ítems vistos (información más que suficiente) pero difundiremos siempre la URL original de cada post, algo muy recomendable para SEO (como bien nos explicaba Armonth hace tiempo).
Así es como debería quedar la configuración en FeedBurner:

Entradas relacionadas:
- Usando mod_rewrite y FeedBurner para las feeds de un blog con WordPress
- Actualizar un WordPress a la última versión
- Internacionalización de temas en WordPress usando gettext
» Leer más, comentarios, etc...
Ideas + Ingeniería del Software
Java en Google App Engine
Abril 8th, 2009 - [Enlace local]
Hasta ahora el hosting accesible (gratuito o de precios ajustados) era territorio dominante de la plataforma LAMP (Linux + Apache + MySQL + PHP) o derivados. Este ha sido uno de los factores determinantes de la proliferación de herramientas open source para foros, blogging, etc.
Por el contrario el mundo empresarial está copado, también en gran parte, por Java (aunque sitios como Flickr o Yahoo! demuestran que PHP es un sistema que no tiene que limitarse a eso, pero este es otro tema).
Hoy Google ha anunciado la disponibilidad de Java en Google App Engine. Además, con soporte para JPA. Por fin hay una alternativa real al LAMP (¡ojo, que no tiene nada de malo, pero las alternativas siempre son buenas!).
» Leer más, comentarios, etc...
Blog de Julio César Pérez Arques
La circunstancia
Abril 5th, 2009 - [Enlace local]
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.
» Leer más, comentarios, etc...
HardBit
Asp.Net MVC + JQuery en Mac OS X con Mono
Abril 5th, 2009 - [Enlace local]
Con la noticia de que ahora Asp.Net MVC es “Open Source”, ya se han realizado ports a la plataforma de Mono, en esta ocasion les mostrare como hacer funcionar el addin de Asp.Net MVC para MonoDevelop.
Antes que nada debemos instalarnos la ultima version de Mono y MonoDevelop para Mac OS X. Asi que descargaremos sus respectivos instaladores, les dejo las ligas a continuación.
Mono
MonoDevelop
Instalamos Mono y a continuacion MonoDevelop una vez que tengamos esto, ejecutamos MonoDevelop y vamos al menu “herramientas” y luego “gestor de complementos”.
Agregamos un complemento, no sin antes agregar un repositorio con la siguiente dirección (http://mjhutchinson.com/mdrepo).
Una vez que hemos hecho esto creamos un proyecto Asp.Net MVC
Agregamos los archivos correspondientes de Jquery como se muestra en la siguiente imagen.
Lo siguiente es practicar y sacarle provecho a esta plataforma
y a continuacion vemos el resultado usando JQuery.
Cualquier duda o comentario a [me {at} hard-bit.net]
———–
Actualizacion: Ya no es necesario usar el reposito comentado antes, ahora ya estan en los respositorio oficiales de Mono
, gracias a Josue por la info
» Leer más, comentarios, etc...
HardBit
Crear un elemento para el panel de control de Windows
Abril 5th, 2009 - [Enlace local]
En esta ocasion veremos como crear un elemento para el panel de control de windows y como ejecutar una aplicacion desde esta, los elementos del panel de control nos pueden de ser de utilidad para configuraciones de aplicaciones o servicios. Personalmente lo uso para configurar y manejar el estado de un servicio de windows, es una manera facil para que los usuarios de nuestras aplicaciones puedan usuarlas.
Empezaremos por lo mas imporante, un CPLApplet (Control panel applet) no es mas que una dll comun que por lo general tiene una extesion .cpl y que exporta la funcion CPlApplet (__stdcall) el cual es el punto de entrada para el applet.
La funcion CPlApplet recibe 4 parametros que son los siguientes.
Parametros
- hwndCPl
- Identificador de la ventana principal. Use el parametro hwndCPl para dialogos u otras ventanas que requieran un manejador de la ventana padre.
- uMsg
- El mensaje enviado al “Control Planel Application”.
- lParam1
- Informacion adicional para un mensaje especifico.
- lParam2
- Informacion adicional para un mensaje especifico.
Ya que conocemos los parametros recibidos por la funcion, vamos a ver los tipos de mensajes que recibe uMsg.
Control Panel messages.
CPL_DBLCLK:
Mensaje enviado cuando el usuario selecciona un icono asociado a un elemento del panel de control, el valor del parametro Param1 indica el valor del indice del elemento, el valor del parametro lParam2 es un puntero a una estructura CPLINFO or NEWCPLINFO regresada por el mensaje CPL_INQUIRE o CPL_NEWINQUIRE. El valor regresado es ignorado.
CPL_EXIT:
Mensaje enviado despues del ultimo mensaje CPL_STOP, Windows usa FreeLibrary para liberar la dll y sus respectivos recursos. El valor regresado es ignorado.
CPL_GETCOUNT:
Mensaje enviado despues de CPL_INIT, debe regresar el numero de subprogramas soportados.
CPL_INIT:
Mensaje enviado despues de ser cargado el elemento en el panel de control.
CPL_INQUIRE:
Mensaje enviado despues de CPL_GETCOUNT, debe proveerse la informacion especifica de cada subprograma, el valor del parametro lParam1 indica el indice del subprograma, el valor del parametro lParam2 es un puntero a una estructura CPLINFO. El valor de regreso es ignorado.
CPL_NEWINQUIRE:
Mensaje similar a CPL_INQUIRE.
CPL_STARTWPARMS:
Mensaje similar a CPL_DBLCLK.
CPL_STOP:
Envia un mensaje para deter el elemento del panel del control para antes de descargar la extesion del panel de control.
Bien ahora que ya conocemos la estructura de la funcion CPlApplet, vamos a crear un ejemplo en VS2008, tambien puede usar Visual C++ express edition, o su compilador de C/C++ favorito.
Vamos a crear una dll convencional y a incluir el archivo cpl.h el cual contiene los mensajes e informacion necesaria del cplapplet.
#include
Y a escribir el codigo correspondiente usando la funcion mencionada anteriormente y exportandola.
En el ejemplo que escribi el applet muestra la calculadora de Windows, ustedes pueden mostrar un dialogo o ventana escrito en la misma dll, pero eso no se limita ahi, como esta en el ejemplo pueden llamar a una ventana de configuracion escrita en .Net, etc…
Veamos una captura de pantalla de como se muestra nuestro elemento en el panel de control.
Les dejo aqui el ejemplo.
Cualquier comentario o duda a [me (en) hard-bit.net]
» Leer más, comentarios, etc...
Developing my life » desarrollo
Flisol 2009
Abril 2nd, 2009 - [Enlace local]
Como todos los años aún
se realiza el Festival Latinoamericano de Instalación de Software Libre. En chiclayo la organizacion estará a cargo de los amigos de CISLUSS. En la empresa donde trabajo EQSOFT estamos comprometidos con el apoyo y promoción al movimiento del Software Libre, asi que estaremos Ernesto y yo en chiclayo brindando una charlas y unos talleres.
Ernesto (a.k.a. kami) estará dando una charla sobre “Costo de Propiedad Total para evaluación de soluciones de software” y un taller sobre PostgreSQL, ¡la base de datos libre!
.
Por mi parte estaré dando un taller de Php for Applications – P4A. La cual es una herramienta que nos permite desarrollar aplicaciones web de una manera profesional y rápida.
A parte de nosotros tambien estara Renato (a.k.a. necudeco o tacutacu) dando un taller de “Acceso ordenado a datos – phpORM”.
Asi que sino tienes nada que hacer el sabado 25 de abril entonces anda al flisol, conoces a la gentita y ademas aprendes algo interesante y productivo. Nos vemos en el flisol a los 4 gatos que me leen
.
Es todo por este post, nos leemos!.
Tambien te puede interesar
» Leer más, comentarios, etc...
PHPBSD.net » webmaster
Interesantes usos y alternativas de __toString() en PHP 5.x
Abril 1st, 2009 - [Enlace local]
Desde la llegada de PHP 5.0 disponemos de varios métodos mágicos para nuestras clases PHP, entre ellos tenemos __toString() que nos permite codificar cómo queremos que se comporte una clase cuando una instancia de ella se convierte a un string.
Aunque a simple vista el método __toString() pueda parecer poco importante en PHP éste toma mucha relevancia si trabajamos con symfony o algún otro framework orientado a objetos donde la información de la base datos se encuentra mapeada en un modelo de objetos.
A pesar de que __toString() está disponible desde la versión 5.0.0 del PHP en mi opinión no empieza a ser realmente útil hasta la versión 5.2.0, algo que en el changelog del PHP reflejaron con un tímido:
Changed __toString() to be called wherever applicable. (Marcus)
Hasta entonces __toString() sólo se llamaba cuando se usaba echo() o print() lo que limitaba mucho su funcionalidad. Desde la versión 5.2.0 __toString() se llama siempre que tratemos a un objeto como a un string.
Por ejemplo dada la siguiente definición de clase:
{
public function __toString()
{
return $this->getName();
}
}
Hasta PHP 5.2.0 sólo podíamos invocar a __toString() con:
Desde la versión 5.2.0 podemos hacer varias cosas interesantes con __toString() sobretodo relacionadas con el manejo de arrays de objetos, algo muy frecuente en los frameworks que corren por ahí hoy en día.
Por ejemplo si obtenemos el típico array de objetos con symfony:
Trabajando directamente con las funciones de PHP entre otras muchas cosas podemos:
- Ordenar el array de objetos con un simple sort()
- Eliminar objetos duplicados del array con un array_unique()
- Generar una lista separada por comas para la presentación con un implode()
- Buscar un objeto determinado dentro del array con array_search()
Alternativas a __toString()
Si no tenemos la suerte de trabajar con PHP 5.2.x, o si queremos poder trabajar con un método distinto de __toString() para determinadas operaciones con arrays de objetos, podemos usar un código parecido al que propongo a continuación:
{
protected static function getMethodValues($list, $method)
{
$items = array();
foreach ($list as $key => $obj)
$items[$key] = $obj->$method();
return $items;
}
protected static function getObjectList($items, $list)
{
$ret = array();
foreach ($items as $key => $item)
$ret[] = $list[$key];
return $ret;
}
public static function arraySortByMethod($list, $method, $sort='desc')
{
$items = self::getMethodValues($list, $method);
asort($items);
if ($sort=='desc')
return array_values(array_reverse(self::getObjectList($items, $list)));
return self::getObjectList($items, $list);
}
public static function arrayUniqueByMethod($list, $method)
{
$items = self::getMethodValues($list, $method);
return self::getObjectList(array_unique($items), $list);
}
public static function arrayImplodeByMethod($list, $method, $sep)
{
$items = self::getMethodValues($list, $method);
return implode($sep, $items);
}
public static function arraySearchByMethod($list, $method, $needle)
{
$items = self::getMethodValues($list, $method);
return array_search($needle, $items);
}
}
Lo anterior es más una propuesta de código que algo decente para ser distribuido. Simplemente se trata de trabajar con un array temporal para almacenar los valores del método solicitado, correr la función PHP y, si es necesario, volver a construir el array de objetos.
Algunos ejemplos de uso:
$sin_duplicados = objectTools::arrayUniqueByMethod($users, 'getName');
$pos = objectTools::arraySearchByMethod($users, 'getName', 'oriol');
//y por último en una plantilla...
echo 'Usuarios: ' . objectTools::arrayImplodeByMethod($users, 'getName', ', ');
Fácilmente se pueden añadir tantos métodos de tratamiento de arrays como se necesiten... o mucho mejor hacer un método que simplemente reciba como variable la función PHP a ejecutar. En mi caso de momento sólo necesito estos en concreto y también así los puedo controlar individualmente.
Aunque estos métodos de objectTools nacieron como "parche" rápido dado que no tenía PHP 5.2.x para un proyecto symfony, ahora, una vez solventando el problema con los servidores, los sigo encontrando útiles en múltiples situaciones. Por supuesto se ha de tener presente el poco rendimiento de este código frente a realizar queries a medida usando el objeto Criteria, pero si ya tenemos un array de objetos en memoria sí que será más óptimo trabajar con él en lugar de lanzar varias queries contra la base de datos.
Entradas relacionadas:
























