Cierre y resumen del 2009

1 comentarios
Finalmente este año 2009 llega a su fin. Ha sido un año que ha dado mucho de sí. Marcado, profesionalmente hablando, por La Crisis, Oracle compra Sun y el rugir de lo Ágil. Es tiempo de hablar con uno mismo, celebrar los éxitos, reconocer los errores, aprender de las experiencias y plantearse nuevas metas. Descansar el cuerpo y la mente, para volver ya el año que viene con renovadas fuerzas.

En lo relativo a este blog, me quedo con la espinita clavada de no haber superado el número de posts del año pasado. 35 el año pasado, por 34 éste. Por poco. Y eso que iba por muy buen camino, pero en Agosto me mudé y con el ordenador en el suelo, aún a falta de elegir mi despacho, se hace muy duro escribir.

Lo que sí han aumentado considerablemente han sido el número de visitas y el número de suscriptores. El primero se ha doblado (cerca de 35.000), aunque mucha culpa la tienen las visitas desde Google, y el segundo se ha quintuplicado (190). Pero lo que más me ha gustado han sido los debates que se han generado en algunos posts. Muchas gracias a todos.

El top 5 de los posts más visitados de este año ha sido (1) Buenas prácticas para desarrollar Servicios web SOAP, (2) Esquema de un Sistema de Gestión de Desarrollo Software, (3) Chuleta Maven, (4) 10 formas de mejorar tu código y (5) Programación basada en Google.

Una de mis nuevas experiencias de este año ha sido gracias a Jorge Rubira, que me invitó a participar en los podcasts Servicios web y Testing de aplicaciones de javaHispano. Fue un auténtico placer contribuir en ellos junto al susodicho, a Alfredo Casado, Leonardo de Seta y Jorge Luis Bugarín.

También me ha dado tiempo a hacer un experimento con AdSense. No es que quisiera monetizar el blog, simplemente tuve un ataque de emprendedor y quería ver, de primera mano, cómo funcionaba el tema de la publicidad en páginas web. De hecho, no ha llegado a generar ni 5 euros y no se cobra nada hasta que no se ganan al menos 70. En el próximo diseño del blog lo eliminaré.

Otra opción que estoy meditando es si pasarme a contractor o freelance y anunciar mis servicios por el blog. Ya veremos...

Llegados a este punto, sólo me queda desearos un Feliz 2010 y dedicaros un brindis por el talento.

Participación en el podcast Testing de aplicaciones de javaHispano

4 comentarios
En javaHispano han publicado las dos partes del podcast Testing de aplicaciones en el que tuve el enorme placer de participar durante una noche del ya lejano mes de Noviembre.

El podcast fue en realidad una intensa tertulia, junto a Alfredo Casado, José Luis Bugarín y Jorge Rubira, donde mezclamos la importancia y ventajas del testing automático de aplicaciones con experiencias, buenas prácticas, técnicas, frameworks y herramientas.

La primera parte se centra más en introducir el testing automático, los tipos de tests, buenas prácticas y la metodología TDD.
Mientras que en la segunda parte se tratan herramientas y frameworks concretos, principalmente del mundo Java, para terminar comentando cómo explotar el testing al máximo desde un entorno de integración continua.

Poco más que añadir a lo contado en el podcast y comentado en javaHispano. Sólo volver a animaros a dar el salto a hacer testing a los que aún no lo habéis hecho. Merece la pena.

Espero que os haya gustado.

Un test para todos tus mapeos Hibernate v2.0

2 comentarios
El otro día uno de mis chicos me dió un tirón de orejas. Resulta que el test para probar todos los mapeos de las entidades Hibernate de un proyecto que publiqué en el pasado, no es correcto para la versión 3 de Hibernate. La culpa es del método iterate de Query, que si bien en la versión 2 de Hibernate hacía un select de todas las columnas, en la versión 3 sólo lo hace de aquellas que forman el identificador de la entidad.

Así que nueva versión del test, compatible con Hibernate 3 y un poco más sofisticada. Allá va.


public void testHibernateMappingsOk() {
boolean allOk = true;
Map metadata = sessionFactory.getAllClassMetadata();
for (Iterator i = metadata.values().iterator(); i.hasNext();) {
EntityPersister persister = (EntityPersister) i.next();
String entityName = persister.getEntityName();
try {
Query q = session.createQuery("from " + entityName);
q.setMaxResults(1);
q.uniqueResult();
} catch (HibernateException e) {
logger.warn("ERROR probando el mapeo de la entidad " + entityName, e);
allOk = false;
}
}
assertTrue(allOk);
}

¿Agil o Agilista?

7 comentarios
2009 es el año Agile. Se ha convertido en la nueva moda, en el nuevo hype y para algunos en la nueva gallina de los huevos de oro. Ha llevado un tiempo desde que se escribió el Manifiesto en 2001, pero finalmente Agile se ha convertido en una auténtica revolución que está llegando -mejor o peor- a todas partes.

Hasta en España -más vale tarde que nunca- se suceden los podcasts, encuentros, conferencias, cursos, seminarios y charlas. Por llegar, ha llegado hasta a las LanParties! Lo próximo será un Open Space en Madrid. Todo ello bien apoyado desde agile-spain, la Comunidad Agile en castellano.

Es una gran noticia. Está haciendo mucho ruido. Y eso es bueno. Es muy bueno. Porque ante todo, lo que Agile transmite es un mensaje. Un mensaje que informa de que existen mejores formas de desarrollar software y que por primera vez viene de abajo a arriba, desde la gente que sabe desarrollar software a la gerencia y a los clientes.

Mi experiencia

Éste es un mensaje con el que estoy totalmente de acuerdo y que intento llevar a cabo en todos los equipos y proyectos por los que he pasado en los últimos años. No ha sido fácil. Sin apoyos, autoformándome en mi tiempo libre e introduciendo los cambios poco a poco, sacando horas de donde se podía.

Primero adopé la visión y objetivo del Manifiesto y los Principios Ágiles.
Luego fuí aplicando muchas de las llamadas Prácticas Ágiles en el desarrollo de los proyectos, como el diseño y desarrollo dirigido a pruebas (TDD), automatización, integración continua, iteraciones, concepto de hecho, diseño simple y evolutivo, revisiones de código, retrospectivas y documentación inteligente o útil.
Finalmente he utilizado algunas de las técnicas de las Metodologías Ágiles para transformar la forma de organizar el trabajo del día a día y alcanzar un nivel de agilidad más completo.
Consiguiendo así evolucionar la forma de desarrollar software, haciéndo proyectos más estables, eficaces y adaptables a los inevitables cambios, para satisfacción del cliente y propia.

Hoy puedo decir que mis esfuerzos por ser Ágil me han ayudado a ser mejor profesional y, también, a formar equipos que desarrollan mejor software y con los que da gusto trabajar. Aunque aún me queda mucho por aprender y mejorar, hoy soy consciente de que estoy en el camino correcto. Hace unos años no podía decir lo mismo.

Peligro

Sin embargo, últimamente noto el mensaje excesivamente -casi exclusivamente- dirigido a la implantación de las Metodologías Ágiles y principalmente Scrum.

Conviene recordar que las Metodologías Ágiles no son metodologías de desarrollo software en sí, sino simplemente de trabajo. Scrum (pej) no define qué entregables debe tener un proyecto, no define ni siquiera tipos de proyecto, si se debe usar UML, Diagramas Gantt, ni nada. Scrum es tan aplicable al desarrollo de software como a cualquier tipo de proceso divisible en tareas, pej. una mudanza! De hecho nuestro tan aclamado Scrum no es una metodología originalmente creada para el desarrollo de software.

En mi opinión, para poder usar una Metodología Ágil, primero es necesario que el proyecto tenga un nivel técnico alto, basado principalmente en automatización, pruebas e integración continua. Cómo podemos adoptar un desarrollo en iteraciones, si no tenemos modo de garantizar (al menos en parte) que el código que funcionaba en la iteración N sigue funcionando en la iteración N+1. ¿Mediante la repetición de fases de pruebas manuales? ¿Y eso es desarrollar mejor software?
Citando a mi colega Alfredo Casado: sin excelencia técnica no hay agilismo, sólo post-it pegados por las paredes. Y sinceramente el nivel técnico medio de los proyectos software a día de hoy deja bastante que desear.

Por otro lado, no puedo dejar de preocuparme cuando leo mucha de la publicidad que se le está haciendo a las Metodologías Ágiles y a Scrum. Cosas del tipo sólo existen 2 tipos de metodologías: en cascada y ágiles, o sólo hay 2 formas de desarrollar buen software: trabajar en la NASA o usar Scrum, o si no obtienes beneficio de aplicar una Metodología Agile es porque no lo estás aplicando en su totalidad, por tanto debes contratar un experto en Agile o Scrum es el remedio contra la crisis mundial. Por supuesto todo rodeado de los nuevos buzzwords de turno, que así como que engaña impacta más.

Todas estas falacias -y otras más- no hacen sino distorsionar el mensaje original (mejores formas de desarrollar software) y dejar una imagen de vendedor de teletienda que no hace ningún bien, y sólo puede generar desconfianza. Supongo que va asociado al hype, pero ¿qué tal si intentamos todos ser un poco más responsables?

También me preocupa -y mucho- el tema de las certificaciones en Scrum y el ansia de algunos por llegar a ser Agile Coach. Donde algunos ven la luz que iluminará el futuro, yo sólo veo una gallina; de huevos de oro, eso sí. Tiene toda la pinta de convertirse en el MBA de nuestro sector. Y si no, al tiempo.

En realidad Scrum no es aplicable a más de la mitad de los proyectos. Entre otras cosas, requiere una enorme disponibilidad por parte del cliente (el Product Owner es parte del equipo), equipos con dedicación absoluta y de alto nivel técnico y una sala de reuniones por equipo disponible a primera hora. Al final tienes que adaptar Scrum a tus circunstancias, pero entonces yo pregunto: ¿y no será más fácil adaptar la metodología que se esté usando para agilizarla? Ah no, que eso no sería cool.

Conclusión

¿Quiere ésto decir que las Metodologías Ágiles no aportan valor? En absoluto. Claro que aportan. Pero cada cosa en su sitio, sobre todo porque no siempre es posible y viable implantar una Metodología Agile oficial. Una Metodología Agile es la punta del iceberg, la guinda del pastel, debajo necesitamos una sólida base construida a partir del Manifiesto, Principios y Prácticas Ágiles.

No podemos dejarnos llevar por el hype de las Metodologías Ágiles, un hype que cada día tiene más parecidos con la religión que con desarrollar software, tanto por el fanatismo como por el negocio generado. De hecho hasta el nombre de Agilismo ha calado. Pero yo no quiero ser Agilista, yo no necesito creer en ninguna Metodología concreta ni en guías espirituales.

Yo quiero ser Ágil. Y se puede ser Ágil sin seguir fielmente una de las Metodologías Ágiles oficiales. Porque el valor de ser ágil es evidente: automatización, pruebas, integración continua, entregas periódicas de un software que funciona, equipos orgullosos y comprometidos con su trabajo, código de mejor calidad, documentación útil, respuesta frente a cambios en los requisitos, compresión y colaboración del cliente,... entre otros. Ésto sí son mejores formas de desarrollar software!

Tip Eclipse: Renombrar atributo junto a sus métodos get/set

3 comentarios
Uno de los refactorings que más me gustan de Eclipse es el de Renombrar sobre el propio editor de código, sin necesidad de usar un diálogo o nueva pantalla. El genial Alt+May+R.

Pero como soy muy maniático con los nombres, muchas veces me da por cambiar el nombre de los atributos, por lo que tengo que ir a sus correspondientes métodos get/set y renombrarlos a mano. En el colmo de la perrería, a veces lo que hago es borrarlos y volver a generarlos automáticamente.

Ahora, con Eclipse 3.5 Galileo es mucho más sencillo. Basta con pulsar 2 veces el mismo atajo Alt+May+R sobre el nombre del atributo y aparecerá un diálogo con las opciones de renombrar también sus métodos get y set.


Encima tiene memoria y te guarda tus preferencias. Esta gente piensa en todo!

Cómo configurar el uso de memoria de un servidor en Eclipse

0 comentarios
Antes de irme de fin de semana -qué ganas- dejo una chuletilla sobre cómo modificar la configuración de arranque y el uso de memoria de un servidor en Eclipse y en general.

Recuerda que la JVM usa 2 tipos de memoria. La memoria Heap donde se crean los objetos y que es gestionada por el GargabeCollector que se encarga de liberar memoria en caso necesario. Y la memoria PermGen que se utiliza principalmente para cargar las definiciones de las clases de forma permanente, pero también para trabajar con código nativo.

1) En Eclipse, ir a: Run -> Run configurations -> TuServidor -> Arguments -> VM Arguments

2) Para evitar el clásico java.lang.OutOfMemoryError: Java Heap space, usar las opciones de la VM:

-Xms64m
-Xmx256m

Es un ejemplo que asigna 64mb a la memoria heap de inicio y le permite crecer hasta un máximo de 256mb. Esta configuración debería ser más que suficiente si estás en desarrollo y sólo tienes una aplicación configurada para arrancar en el servidor. Antes de incrementarla, tómate unos segundos para meditar si el fallo pudiera ser causa de un memory leak.

3) Para evitar el igualmente clásico java.lang.OutOfMemoryError: PermGen space, usar las opciones de la VM:

-XX:PermSize=64m
-XX:MaxPermSize=128m

Es un ejemplo que asigna 64mb a la memoria perm de inicio y le permite crecer hasta un máximo de 128mb. De nuevo, este ejemplo debería ser más que suficiente si sólo tienes un par de aplicaciones configuradas en el servidor. Aunque todo dependerá del número de despliegues en caliente que realices habitualmente sin reiniciar el servidor.

Otra opción es intentar que el garbage collector recicle la memoria permgen. Para ello prueba a activar el recolector concurrente con los siguientes parámetros:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled


Finalmente un par de enlaces a las páginas oficiales de opciones de la VM y la guía de tuning del gc de la jvm 5.

Primeras impresiones con Pentaho Data Integration (Kettle)

4 comentarios
UPDATE 090814: Se añade información sobre la ejecución de una transformación y su impact.

A veces en un proyecto software es necesario extraer, transformar y cargar información de una o varias fuentes de datos. A este proceso se le conoce como ETL.

Los ejemplos típicos de procesos ETL incluyen (i) extracciones de datos desde ficheros con diversos formatos, bases de datos o servicios web, (ii) transformaciones como traducciones de valores, calculos de nuevos valores, cruces de fuentes de datos, filtrar registros, generación de claves, división de columnas o pivotar filas a columnas y viceversa, y (iii) cargas a ficheros o tablas de bases de datos.

La tarea puede llegar a ser bastante compleja, no sólo por la diversidad de las fuentes de datos sino por la variedad de transformaciones a realizar. Sobre todo en el caso de las grandes organizaciones, las llamadas Enterprise, donde cada departamento funciona como le da la gana.

Esta semana me ha tocado (lo que tienen las vacaciones, las de los demás claro) realizar un proceso ETL relativamente simple. Así que he aprovechado para probar la aplicación Pentaho Data Integration, también conocida como Kettle o Spoon, que forma parte de la suite opensource Pentaho de Business Intelligence.

La instalación es muy sencilla. Es una aplicación Java, así que necesita tener instalada una JVM. Por lo demás es simplemente descargar, descomprimir y ejecutar el script de arranque.

Con Kettle puedes crear transformaciones y trabajos (jobs) de forma visual arrastrando, uniendo y configurando los distintos pasos.

Una transformación incluye pasos de extracción, transformación y carga del tipo anteriormente comentado y muchos más. Cada uno de estos pasos se puede previsualizar por separado. Una vez diseñada la transformación, se puede validar, ejecutar, debugear, monitorizar, analizar su impacto en el rendimiento y obtener el código sql que genera.


Un trabajo te permite configurar cómo y cuando se ejecutará una transformación. Sus pasos incluyen, a parte de ejecutar una transformación existente, planificar el inicio, abortar, enviar y recibir emails, operaciones con ficheros, ejecutar un http get, evaluar condiciones sobre ficheros, servidores y tablas, ejecutar scripts sql, javascript y shell, validar xml, escribir log y usar ftp, entre otros.


Conviene tener en cuenta el impacto de la transformación sobre la base de datos a la hora de planificar su ejecución en Producción. Normalmente son tareas muy pesadas que pueden afectar al rendimiento general durante muchos minutos. Así que deben ser ejecutadas en horario de mínima actividad.

El uso de Kettle es muy intuitivo y ágil desde el principio, como se puede en las flash demos que hay disponibles en la wiki. De hecho, en menos de una hora ya tenía hecha una primera versión de mi transformación a la que sólo le faltaban algunos detalles de formatos. Para ser mi primera vez estuvo muy bien!

En la wiki también existe una buena cantidad de documentación. Además existe una guía de usuario en pdf bastante completa que merece la pena tener a mano como referencia.

Una sorpresa que me llevé fue que está traducida en parte al castellano. Aunque como todo no puede ser perfecto, el típico botón Ok o Aceptar ha sido traducido por Vale...

En resumen, Kettle (Spoon) me ha encantado. Es muy completo, sencillo y eficaz. Me va a hacer la vida muy fácil cuando tenga que realizar tareas de ETL.

Chuleta Maven

6 comentarios
UPDATE 20100126: Añadido cómo configurar el máximo de memoria heap

A continuación una chuleta con buena parte de lo que llevo aprendido usando Maven estos dos últimos meses más algunas referencias.

> 1. CREAR PROYECTOS


Crear un proyecto jar

$ mvn archetype:create -DgroupId=com.example -DartifactId=example-jar-project

Crear un proyecto war
$ mvn archetype:create -DarchetypeartifactId=maven-archetype-webapp -DgroupId=com.example -DartifactId=example-war-project


> 2. ECLIPSE


Configurar plugin eclipse para descargar fuentes y javadocs de las dependencias


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<!-- Ojo, la versión 2.6 tiene bugs con AJDT -->
<version>2.5</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>

Crear variable M2_REPO
Ir a Window -> Preferences -> Java -> Build path -> Classpath variable -> New
Name: M2_REPO
Path: /ruta/a/tu/.m2/repository

Generar ficheros de configuración de un proyecto jar Eclipse
$ mvn eclipse:eclipse

Generar ficheros de configuración de un proyecto war Eclipse
$ mvn eclipse:eclipse -Dwtpversion=1.5

Cargar un proyecto en Eclipse
Ir a File -> Import -> General -> Existing project into Workspace -> Select root directory

Borrar ficheros de configuración proyecto Eclipse
$ mvn eclipse:clean

Ahora más que nunca, se recomienda no subir a CVS o similar los ficheros de configuración del proyecto en el IDE.



> 3. CONFIGURACIÓN DE PLUGINS MÁS COMUNES


Configurar un plugin para este pom y sus hijos

En build -> pluginManagement -> plugins

Configurar un plugin sólo para este pom
En build -> plugins

Configurar encoding y versión java de compilación

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.4</source>
<target>1.4</target>
</configuration>
</plugin>

Configurar plugin surefire para ignorar fallos de tests, definir patrones de nombres de tests aceptados y configurar propiedades de sistema (locale) durante la ejecución de los tests

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<includes>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
</includes>
<systemProperties>
<property>
<name>user.language</name>
<value>es</value>
</property>
<property>
<name>user.country</name>
<value>ES</value>
</property>
</systemProperties>
</configuration>
</plugin>


> 4. COMANDOS ÚTILES EN EL DÍA A DÍA


Borrar carpeta de construcción

$ mvn clean

Ejecutar tests
$ mvn test

Construir proyecto
$ mvn package

Instalar proyecto en tu repositorio local
$ mvn install

Instalar (desplegar) proyecto en el repositorio de la organización (necesita configuración)
$ mvn deploy

Ejecutar Maven saltándose los tests (unitarios e integración)
$ mvn xxxxxxx -Dmaven.test.skip=true

Mostrar el stacktrace de excepción
$ mvn xxxxxxx -e

Mostrar información de debug
$ mvn xxxxxxx -X

Instalar una libreria de terceros en tu repositorio local
mvn install:install-file -Dfile=ruta/a/fichero/jar -DgroupId=com.example -DartifactId=nombre_libreria -Dversion=x.y.z -Dpackaging=jar

Instalar (desplegar) una libreria de terceros en el repositorio de la organización (necesita configuración)
$ mvn deploy:deploy-file -Dfile=ruta/a/fichero/jar -DrepositoryId=id_repositorio -Durl=url_repositorio -DgroupId=com.example -DartifactId=nombre_libreria -Dversion=x.y.z -Dpackaging=jar

Ver pom efectivo (suma de poms padres)
$ mvn help:effective-pom

Ejecutar Maven en modo offline
$ mvn xxxxxxx -o

Preparar Maven para poder ejecutarse en modo offline
$ mvn dependency:go-offline

Ejecutar Maven con máximo de memoria heap configurable (ejemplo con 512m)
$ mvn xxxxxxx -DXmx512m
o editar la variable de sistema MAVEN_OPTS=-Xmx512m


> 5. DEPENDENCIAS


Ver jerarquía de dependencias

$ mvn dependency:tree

Ver dependencias en orden alfabético
$ mvn dependency:resolve

Analizar uso de dependencias
$ mvn dependency:analyze



> 6. RECURSOS


Ciclos de vida

http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

Estructura estándar de carpetas
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

Propiedades
http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

Pom
http://maven.apache.org/ref/2.2.1/maven-model/maven.html

Plugins más comunes
http://maven.apache.org/plugins/index.html

Documentación oficial
http://maven.apache.org/guides/index.html

Libro gratuito: Maven La Guía Definitiva
http://www.sonatype.com/books/maven-book/reference/

Gestor de repositorios Nexus
http://nexus.sonatype.org/index.html

Esquema de un Sistema de Gestión de Desarrollo Software

12 comentarios
UPDATE 090731: Se mejora la imagen del esquema y se subraya la importancia de la automatización de la alimentación del Sistema.

Me encuentro sumido en un proyecto de consultoría para definir un Sistema de Gestión de Desarrollo de Proyectos o Ecosistema Software. Así que aprovecho para compartir una primera versión del esquema lógico sobre el que estoy trabajando.


Wiki

Es el punto de entrada principal al Sistema.
Contiene la información básica de cada proyecto y la organización.
Redirige al resto de aplicaciones del Sistema.
Permite la creación de documentación de forma colaborativa.
Control de cambios automático.
Documentación exportable a formato pdf.

Cms

Sistema de Gestión Documental para los documentos binarios, como word, powerpoint, etc.
No toda la documentación puede estar en el Wiki.

Project Management

Visión de alto nivel de la gestión de proyectos.
Cuadro de mandos ágil para directivos.
Gestiona resto de estados de un proyecto que no son Desarrollo.

Issue Management

Gestión del desarrollo de cada proyecto con sus versiones, tareas, equipo, trazabilidad, etc.

Scm

Sistema de Gestión de Control de Fuentes (CVS, Subversion, Git,... etc.)

Continuous Integration Server

Descarga, construye, prueba, analiza el código, crea informes de estado y despliega en el Demos Server los proyectos de forma automática y periódica.

Demos Server

Servidor de demos del estado actual de cada proyecto.

Otros

Notificaciones vía RSS y e-mail.
Single Sign On.
Privacidad.
Integración con el IDE del equipo de desarrollo para automatizar la alimentación del Sistema y garantizar la trazabilidad.


Ahora toca analizar alternativas y seleccionar la que más se ajuste a las necesidades del cliente.
Los mayores problemas están en (1) el análisis del Wiki y el Cms por la cantidad de alternativas disponibles y (2) en la herramienta de Project Management porque cada organización tiene un punto de vista muy personal sobre la gestión de proyectos, lo que interesa y lo que no. Así que no descarto que haya que desarrollar una aplicación a medida como suelen tener todas las organizaciones.

Cuanto vale un experto en programacion (ii)

20 comentarios
Empezamos nuestra vida profesional programando. A muchos nos encanta. Va más allá de una obligación o un mal menor y temporal en un camino mezquino. Es una pasión. Disfrutamos construyendo buen software y cúanto mejor lo hacemos, más nos gusta. Por eso nos cuesta abandonar la rama técnica de nuestro sector. Aunque es una rama corta, torcida y con un techo salarial injusto.

Hace unos dias os contaba que Kent Beck ofrecía sus servicios durante 2 horas de forma remota a través de ebay. Me pareció una buena prueba para saber dónde está este techo ahora. Para saber cúanto vale un experto en programación y animarme a no cambiar de rama.

Finalmente la puja se cerró en 405 dolares americanos. No llega a 300 euros al cambio actual. Más o menos lo que cualquier consultora cobra por una jornada de un perfil técnico medio aquí en España. No sé a vosotros, pero a mi me parece poco. Me cuesta creer que haya faltado repercusión o que la cuestión del remoto haya sido un impedimento. Sinceramente me esperaba más dinero. Sobretodo teniendo en cuenta que por casi cualquier curso o seminario con un profesor anónimo ya se está facturando eso o incluso más. Y no es lo mismo un formador que un experto.

La conclusión es tan clara como desmotivadora. Un experto en programación vale poco en comparación con otros expertos.

Por qué

Por un lado es un problema de actitud. Nos quejamos mucho en nuestros circulos internos pero reivindicamos poco o nada en comparación con otros colectivos de trabajadores.

Pero principalmente pienso que es un problema de no saber reconocer la calidad ni importancia del trabajo de un programador. Me explico. Reconocer la calidad del trabajo de un diseñador gráfico es sencillo (gustos aparte). Reconocer la calidad del trabajo de un experto en usabilidad es sencillo. Reconocer la calidad del trabajo de un tester es factible con métricas sobre el número de bugs detectados. Reconocer la calidad del trabajo de un formador también es sencillo. Calcular la comisión del trabajo de un comercial se hace todos los dias.

Sin embargo, reconocer la calidad del trabajo de un programador no es fácil para alguien que no sea también programador. Características como la eficacia, estabilidad y escalabilidad del código de una aplicación no son fácilmente medibles a primera vista. Ni siquiera para un programador. Ya sea sobre el código o sobre la aplicación funcionando. ¿Es culpa del análisis, del código propio de la aplicación, de alguna librería externa, del servidor, del proxy, de la base de datos,...?

Mucho más dificil es responsabilizar de cualquier mérito o demérito a un programador concreto dentro de todo un equipo de desarrollo. ¿Trazabiliqué? Todos somos de excusa rápida para nuestros fallos y muy poco comprensivos para los de los demás.

La complejidad se multiplica para el caso de aplicaciones enterprise donde existen numerosas fuentes de datos, cuya integridad y fiabilidad no dependen directamente del programador pero si pueden afectar a la aparente calidad de su trabajo. ¿A quién no le han abierto una incidencia que realmente era por un bug en un servicio externo, por inconsistencia de datos o simplemente porque estaba caido algún sistema externo?

Al final el cliente termina por aceptar y convivir con que sus aplicaciones fallan y necesitan de grandes contratos en mantenimiento correctivo y funcional. Los comerciales hacen su trabajo. La empresa gana dinero. Y nosotros terminamos parcheando dinosaurios. Todo puede seguir como estaba.

Aún así, nosotros, los que programamos, sabemos que un buen programador no es que valga x2 o x3. Vale mucho más. Mientras que un mal programador ya no es que sume poco, es que llega a restar. Lo sabemos porque lo vivimos a diario, pero comunicar esta lección a otros niveles no es fácil.

Un futuro mejor pasa irremediablemente por medir la calidad de un proyecto, y por tanto medir la calidad de sus programadores. Con números delante, todo el mundo es capaz de medir y comparar. Para ello se puede (1) medir la calidad del código mediante métricas de análisis estático, (2) medir la cobertura de tests unitarios del código y (3) definir tests de aceptación funcionales y de esfuerzo sobre la aplicación. Con lo primero medimos mantenibilidad, con lo segundo fiabilidad y con lo tercero eficacia, estabilidad y escalabilidad.

Cuanto vale un experto en programacion

5 comentarios
Estamos acostumbrados a enfrentarnos a nuevos problemas por nosotros solos a diario. No nos queda otra. El aprendizaje a base de ostias investigación, prueba y error es una realidad por la que todos pasamos y que viene a cubrir las carencias de los sistemas de formación profesionales.

Pero muchas veces podemos dedicar días y días, incluso semanas, para dar con la solución. Se soluciona sí. Se aprende también. Pero no es eficiente. Por un lado, tiene un coste psicológico en la persona o equipo en forma de stress, desmotivación y quemado. Por otro, tiene también un coste económico en las cuentas del proyecto. Y hasta puede tener un coste en imagen si el cliente se entera o simplemente por entregar con retraso.

Contar con un experto podría resolver el problema de forma eficiente a la vez que mejoraría la formación del equipo. Por problema no sólo me refiero a un marrón, puede ser un conjunto de tareas importantes sobre las que el equipo no tiene aptitudes ni experiencia.

Conozco algunas compañías donde se cuenta con esa figura de experto al más puro estilo Señor Lobo de Pulp Fiction. Aunque son muy pocas y a veces el experto no es tan experto. Pero siempre está la opción de subcontratar a un verdadero experto para resolver el problema. En España no se lleva. Una pena.

Y todo este rollo al hilo de un sorprendente anuncio de Kent Beck en ebay, donde ofrece una sesión remota de programación en pareja de 2 horas. La sesión se hará mediante VNC para compartir la pantalla y Skype para comunicarse. Aunque puede ser para revisar código, las dos horas se pueden emplear en temas de diseño, testing o lo que se quiera. Va por 305 dolares pero aún faltan días para que se cierre la puja. Veremos como termina la cosa.

Sobre pruebas y errores

5 comentarios
Veo en las noticias las imagenes de una prueba de carga en un nuevo puente de una autovía en Galicia (España). Durante un momento me quedo absorto mirando la larga flota de camiones sobre el majestuoso puente. Impresiona. No puedo evitar pensar: Vaya! eso sí que es una prueba manual. Y luego yo quejándome sobre las pruebas manuales que hacemos en el desarrollo de proyectos software...

Bastan un par de segundos para darme cuenta de la tontería de mi reflexión. Si eso fuera una primera ejecución de una prueba exigente sobre un proyecto software recien construido, el puente se habría caido arrastrando a la flota de camiones tras él.

En el caso del puente, lo que no estamos viendo es todo el proceso de pruebas y control de calidad, que se ha realizado previamente en cada una de las fases del proyecto para evitar errores.

Pero comparar nuestro mundo de desarrollo software -¿ingeniería software?- con el de la construcción o cualquier otra ingeniería es una equivocación. Una equivocación torpe, injusta y desafortunada, porque, entre otras cosas, hace imaginarse a un programador como a un obrero. Así nos va.

Aunque centrémonos en los errores. Errar es humano. Obvio. A veces estamos distraidos, cansados, estresados, desmotivados o simplemente no somos perfectos y se nos escapan cosas.

Otro hecho es que los proyectos software salen a producción con demasiados errores. También obvio si estudiamos el ineficaz proceso de pruebas que se sigue en la mayoría de proyectos, basado en unas pruebas mínimas, manuales y sin documentar. Por lo que las pruebas dificilmente se repiten en el tiempo, aunque se modifique código afectado, haciendo aparecer nuevos errores o, peor aun, haciendo reaparecer viejos errores. ¿Vosotros compraríais algo cuyo proceso de pruebas fuera así?

Lo primero no tiene solución. Pero sí se puede minimizar el efecto. Contratando talento y con motivación.
Lo segundo sí tiene solución. Aplicar un proceso profesional de pruebas, basado en pruebas automatizadas, completas, independiente y repetibles. Los errores seguirán produciéndose, pero la mayoría serán detectados antes de llegar a producción.

Por supuesto, siempre hará falta alguna prueba manual pero, al igual que en el puente, será más un mero trámite de aceptación que el actual infierno de prueba y error sin fin.

Nuevo cambio de look y AdSense

0 comentarios
Aprovecho para anunciar un par de cambios en el blog: (1) nuevo cambio de look y (2) AdSense.

Hacía tiempo que me había cansado del anterior template, un día sin querer dí con este The Journalist y hoy he decidido probarlo, tras unas mínimas modificaciones. No tiene más.

El tema de AdSense sí requiere un poco más de explicación. No pretendo monetizar el blog. No creo ni que le fuera a sacar un euro aunque lo intentara. Sin embargo, sí quiero probar AdSense y ver cómo funciona de primera mano. Últimamente se me ha reactivado la vena emprendedora, así que quiero ver cómo va esto de la publicidad.

Como siempre, cualquier opinión sobre alguno de los 2 temas será más que bievenido!

Buenas practicas para desarrollar servicios web SOAP

12 comentarios
Como complemento a mi último post, Arquetipo de WSDL interoperable, he decidido publicar este post con varias buenas prácticas para desarrollar servicios web SOAP. Como siempre, son sólo buenas prácticas según mi criterio, conocimiento y experiencia.

  • Analiza qué servicios web y con qué operaciones hay que desarrollar. Parece de perogrullo, pero es uno de los fallos más repetidos. Según mi experiencia suelen darse 2 esquemas a la hora de desarrollar servicios web: (i) el servicio web dios con todas las operaciones para él y (ii) un servicio web por operación. Ambos son malos. El primero incluso peor. Así que piensa y diseña servicios web con las responsabilidades bien repartidas, que sean cohesivos, extensibles, escalables y reutilizables.
  • Escribe tu mismo el fichero WSDL (Contract-First). Es el interfaz, el contrato y, en definitiva, la clave para una interoperabilidad real e independiente de la tecnología. Además los generadores de WSDL pueden introducir dependencias con una tecnología concreta. Por eso merece la pena aprender a escribir WSDL (aquí) y schemas XSD (aquí).
  • A la hora de diseñar el interfaz de las operaciones, ten siempre en cuenta que es mucho más eficiente un único mensaje enorme que el equivalente en multiples mensajes.
  • Sé coherente con la nomenclatura de namespaces de la organización. No hay nada que de peor impresión que un servicio web que no ha cuidado los namespaces.
  • El WSDL debe ser compatible con el WS-I Basic Profile. El WS-I Basic Profile es un conjunto de especificaciones y buenas practicas definidas por la industria para obtener servicios web interoperables. Actualmente la última versión final publicada es la 1.1. Como mínimo, evita siempre los estilos RPC y sus tipos de datos no XML (SoapArrays), en su lugar usa el estilo Document/literal.
  • Usa http://localhost:puerto como dirección url del endpoint y deja que sea el motor de webservices el encargado de sustituirla por la real. Así evitarás tener un fichero WSDL por entorno.
  • Separa la definición de los mensajes del fichero WSDL. Para ello, diseña por separado un schema XSD donde se definan los mensajes y que sea importado por el fichero WSDL. Las principales ventajas son (1) reduce el tamaño/complejidad del WSDL, (2) permite utilizar editores especializados para el diseño del schema XSD y (3) permite reutilizar schemas y namespaces.
  • Define los mensajes de forma detallada mediante las restricciones de los schemas XSD. De esta forma podrás validar los mensajes a nivel de XML mediante el api XML u OXM que uses, sin necesidad de implementar código propio.
  • A la hora de diseñar el schema XSD, crea tipos y elementos globales (a nivel raíz) para poder reutilizarlos, tanto a nivel de elementos XML como clases del lenguaje de implementación del servicio web.
  • Además, usa minOccurs=0 para definir un elemento como opcional y nillable=true para indicar que un elemento puede ser vacío pero siempre estará presente en el mensaje XML. Ojo, no es lo mismo.
  • Si necesitas enviar ficheros adjuntos (attachments), hazlo a nivel de http attachment y no como un elemento del mensaje XML.
  • Automatiza el proceso de generar el Skeleton y las clases OXM de mensajes del servicio web a partir del WSDL (wsdl2code).
  • Para realizar pruebas unitarias del servicio web no necesitas desplegarlo, puedes programar tus tests a nivel de la clase Skeleton. Ahorraras mucho tiempo y ya desplegarás para las pruebas de integración o alguna demo.
  • Guarda log de los mensajes de entrada y salida junto con datos del cliente (ip, usuario), a nivel de fichero o base de datos.
  • Redacta un documento Guía de pruebas de integración que sea completo e incluya casos de error y no sólo los casos básicos.

Arquetipo de WSDL interoperable compatible con WS-I Basic Profile 1.1

3 comentarios
En este post voy a publicar un WSDL de ejemplo que cumple con el WS-I Basic Profile 1.1.

La clave de la interoperabilidad entre servicios web SOAP está en su interfaz WSDL. El WS-I Basic Profile es un conjunto de especificaciones y buenas prácticas definidos por la industria para desarrollar servicios web interoperables independientemente de la tecnología con que fueron desarrollados. Su última versión final es la 1.1 y debería ser un must-know para todos aquellos que tengan que definir un WSDL.

El WSDL de ejemplo está diseñado para que use un schema XSD donde definir los mensajes de petición y respuesta de las operaciones. De esta forma se puede usar un editor de XSD como ayuda para diseñar la estructura de los mensajes, que es la parte más importante del WSDL y que requiere el verdadero esfuerzo intelectual. Dejando de esta forma el proceso de definir el fichero WSDL a un mero trámite de copy&paste.Además es una buena práctica en una SOA publicar los schemas xsd para reutilizar sus elementos.

Este WSDL sólo tiene 1 operación. Además usa los siguientes literales como ejemplo:
  • Nombre del servicio: nombreServicio
  • Nombre de la operación: nombreOperacion
  • TargetNamespace del servicio: http://dominio/ws/nombreServicio
  • TargetNamespace del schema xsd: http://dominio/ws/nombreServicio/schema/msg

El fichero schema xsd nombreServicio_msg.xsd sería el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:tns="http://dominio/ws/nombreServicio/schema/msg"
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://dominio/ws/nombreServicio/schema/msg">
<element name="nombreOperacionRequest">
<complexType>
<sequence>
<element name="campo1" type="string"/>
<element name="campo2" type="string"/>
</sequence>
</complexType>
</element>
<element name="nombreOperacionResponse">
<complexType>
<sequence>
<element name="campo1" type="string"/>
<element name="campo2" type="string"/>
</sequence>
</complexType>
</element>
</schema>
La operación del servicio tiene 2 elementos de entrada y 2 de salida, todos de tipo string, a modo de ejemplo. Puedes modificar los mensajes existentes o crear mensajes para nuevas operaciones a tu gusto. No olvides modificar el targetNamespace.
Si el schema xsd se complica puedes plantearte dividirlo por operaciones o por entrada y salida.
Este fichero puede ser descargado aquí.

El fichero wsdl nombreServicio.wsdl sería el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="nombreServicio"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:tns="http://dominio/ws/nombreServicio"
xmlns:msg="http://dominio/ws/nombreServicio/schema/msg"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="http://schemas.xmlsoap.org/soap/encoding/"
targetNamespace="http://dominio/ws/nombreServicio">
<!-- Importacion de schemas -->
<import namespace="http://dominio/ws/nombreServicio/schema/msg"
location="./nombreServicio_msg.xsd"/>
<!-- Definicion de mensajes -->
<message name="nombreOperacionRequest">
<part name="body" element="msg:nombreOperacionRequest"/>
</message>
<message name="nombreOperacionResponse">
<part name="body" element="msg:nombreOperacionResponse"/>
</message>
<portType name="nombreServicio">
<!-- Relacion Mensaje-Operacion -->
<operation name="nombreOperacion">
<input message="tns:nombreOperacionRequest"
wsaw:Action="urn:nombreOperacion"/>
<output message="tns:nombreOperacionResponse"
wsaw:Action="urn:nombreOperacion"/>
</operation>
</portType>
<binding name="nombreServicioBinding" type="tns:nombreServicio">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<!-- Definicion de operaciones -->
<operation name="nombreOperacion">
<soap:operation soapAction="urn:nombreOperacion"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="nombreServicio">
<port name="nombreServicioPort" binding="tns:nombreServicioBinding">
<soap:address location="http://localhost:8080"/>
</port>
</service>
</definitions>

Lo primero sería modificar los nombres del servicio, operación y targetNamespaces de ejemplo. Puedes añadir nuevas operaciones a tu gusto. Como puedes ver, he puesto comentarios indicando los sitios que deberían ser modificados.
No cambies la url del endpoint. Por lo general, los servidores de webservices detectarán la url y realizarán la modificación de forma automática. De este modo te evitas tener una copia del WSDL por entorno (desarrollo, pruebas, producción, etc.).
Este fichero puede ser descargado aquí.

Una vez realizadas las modificaciones convenientes no olvides validarlo todo, el schema xsd y el wsdl.

Cuando la crisis golpea una consultora IT

14 comentarios
Estaba cantado. La crisis ha llegado a nuestro sector. Va a quedarse y va a hacer daño. Ha tardado lo justo en que las empresas del resto de sectores ya en crisis se han recortado su presupuesto en proyectos IT, tanto nuevos como de mantenimiento. El resultado (previsible) es que el modelo de negocio de las grandes consultoras IT no se sostiene y no se sabe adaptar a la nueva situación.

Son ya muchos años explotando un modelo de servicios desde un punto de vista basado unicamente en los números a corto plazo. Sin importar mucho más. Tecnología, conocimiento, proyectos, trabajadores o clientes. Son mentes financieras las que mueven los hilos al más alto nivel. Para ellas, el negocio IT no es muy diferente de cualquier otro, como podría ser el de las máquinas expendedoras.

Modelo de negocio Máquina expendedora

Existe una necesidad: el código. Y las consultoras hacen negocio con máquinas expendedoras de código. El código es un bien caro y se genera directamente dentro de las máquinas. Sin necesidad de comprar ninguna materia prima.

Que un cliente necesita código, pues negocias cúantas máquinas de cada tipo le pones, por cúanto tiempo y, ala, a facturar.

Las máquinas no tienen coste inicial, sólo de mantenimiento (salario) pero tampoco es que sea mucho. Como cualquier coste, se intenta reducir al máximo. No tiene mucha más preocupación. La prueba está en que existe una generalizada inversión de salario, donde no siempre a una máquina que aporta mayor valor le corresponde un mayor coste (salario).

Las instalaciones tampoco es que sean excesivamente costosas (luz, agua, ordenadores, internet,...) o amplias, ni necesiten estar estrategicamente situadas. Además, con suerte, al cliente le da por tener las máquinas en sus propias instalaciones, por lo que es un gasto menos.

En realidad no hace falta un modelo de negocio muy sofisticado. Ya es un negocio por si solo!

Últimamente estaban teniendo el doble problema de que se iban demasiadas máquinas y que además habia escasez de nuevas máquinas. La solución (muy finaciera) ha sido (1) adquirir máquinas que no son expendedoras de código pero pueden pasar por ellas (o al menos se lo parece), (2) importar o usar máquinas de otros paises y (3) subcontratar a otras consultoras más pequeñas y baratas. En realidad nada grave que requiera cambiar el modelo.

El golpe

El modelo era un éxito. Los records de facturación se han ido sucediendo año tras año. Hasta ahora. Al caer la economía de los grandes clientes de código, las consultoras se encuentran con excedentes de máquinas, los beneficios han caido y los objetivos se alejan.

Las primeras medidas

Una vez más, se toman medidas desde un punto de vista financiero. Dejar de contar con ese excedente de máquinas no es caro, mientras no sean muchas. Además las máquinas, de siempre, ni se quejan en exceso ni hacen mucho ruido. Así que no llevamos ni medio año de efecto crisis y ya asoman los primeros EREs. Y los que no se han dado ya es por no perder cotización en bolsa.

Otras medidas a tomar, igual de rápidas que de injustas, son:
  • Congelación de sueldos. El año pasado batiste record de facturación y se te paga congelándote el sueldo...
  • Invitaciones al personal en available para tomarse unas vacaciones sin sueldo aunque cotizando.
  • Reducción de la jornada laboral.
  • Reducir el número de días de vacaciones. Claro, todo el mundo sabe que aumentando en número de horas trabajadas, aumentas la productividad. Ésto último era puro sarcasmo.
En realidad no dejan de ser meros parches para maquillar las cuentas. No son soluciones.

Alternativas

Se echa en falta un poco de imaginación y de conocimiento del sector. ¿Por qué no hacer?
  • Formación. Se puede impartir y recibir cursos en vivo u online. Personal más preparado sí es igual a mayor productividad.
  • Investigación. Se puede investigar y evaluar nuevas tecnologías, herramientas y metodologías que permitan un verdadero aumento de la productividad.
  • Desarrollo de productos. Para posteriormente intentar su venta. Vender productos no genera un beneficio tan inmediato como vender servicios porque primero hay que desarrollar el producto, pero da dinero y prestigio.
  • Desarrollo de aplicaciones internas. Ya se sabe que en casa de herrero, cuchillo de palo, así que seguro que las aplicaciones internas son más que mejorables. Mejores aplicaciones intenas también mejora la productividad.
  • Incrementar la dotación en los proyectos activos. Ésto supone perder dinero o ganar menos en estos proyectos, pero seguro que incrementaremos la satisfacción del cliente y nuestras opciones para obtener nuevos proyectos con él.
  • Dar soporte a compañeros de otros equipos. Pocas veces eres el primero en resolver un problema, en vez de preguntar a Google o probar por probar, por qué no preguntar a un compañero de otro equipo.
  • ¿Colaborar en proyectos open-source de los que tu empresa se lleva lucrando años? Ja, que me da la risa...

Futuro

La vida son ciclos. Al final la crisis se irá. Algunos habrán caido, otros se habrán mantenido a flote y los más preparados habrán crecido. Pero, ¿habremos aprendido algo?

Hacer accesible un método Java en tiempo de ejecución

7 comentarios
No es habitual. Puede que incluso sea síntoma de un mal diseño OO. Pero en ocasiones nos puede venir muy bien ser capaces de hacer accesible un método en tiempo de ejecución. Por ejemplo, para hacer pruebas de un método privado.

El truco está en usar Reflection. Reflection es un API Java que forma parte del JDK (paquete java.lang.reflect) y que permite acceder y manipular la meta-información de las clases y objetos de tu código Java en tiempo de ejecución. No es algo que se use todos los días (a no ser que programes ides, debuggers o frameworks), pero conviene saber que existe y conocer sus capacidades, por si acaso...

Pero vayamos al grano. El código es muy sencillo. A partir de una instancia, (1) obtenemos su objeto Class, (2) obtenemos el objeto Method que representa el método en cuestión, (3) modificamos su accesibilidad y (4) finalmente lo ejecutamos pasándole los argumentos necesarios y guardamos su salida si tiene. Un ejemplo de un método sayHello con un parámetro String y un return String sería éste:


Method metodo = instancia.getClass().getDeclaredMethod("sayHello", new Class[]{String.class});
metodo.setAccessible(true);
String salida = (String)metodo.invoke(instancia, new Object[]{"argumento1"}));


¿Y si fuera un constructor? Practicamente igual, pero usando esta vez el objeto Constructor y teniendo en cuanta que ahora no tenemos una instancia. Un ejemplo con un constructor sin parámetros sería éste:


Constructor constructor = NombreClase.class.getDeclaredConstructor(new Class[0]);
constructor.setAccessible(true);
NombreClase instancia = (NombreClase)constructor.newInstance();


Y esto es todo. Rápido y fácil. Ahora no lo uséis mal...

10 formas de mejorar tu código

15 comentarios
[ACTUALIZACIÓN 030509: Añadido ejemplo de Antiobjeto.]

El otro día vi la presentación 10 Ways to Improve your Code que Neal Ford hizo en la QCon SF 2008 sobre cómo escribir mejor código y que ha publicado el portal InfoQ.

Es una presentación genial y muy práctica. Enseguida te das cuenta de que estás ante un gran programador que además sabe explicarse muy bien. Así que decidí tomar apuntes de estas 10 formas de escribir mejor código, que aprovecho para plasmar aquí y no olvidarlas.

1 - Métodos compuestos

Divide tus métodos en métodos más pequeños que realicen una única tarea claramente identificada. Así se obtiene un código más intuitivo y fácil de probar formado por métodos pequeños, cohesivos y reutilizables. Además es un código autodocumentado porque los nombres de los métodos se convierten en documentación.

2 - Diseño y Desarrollo orientado a pruebas (TDD)

Piensa en cómo se usará una clase y diseñarás mejor su interfaz y su relación con otras clases.
Una clase bien diseñada es fácil de probar.

3 - Análisis estático

Usa herramientas de análisis de código, como Findbugs, para evitar bugs, no violar buenas prácticas y escribir código más fácil de mantener.

4 - Buenos ciudadanos

En POO los ciudadanos son las clases. Una buena clase es aquella que se relaciona bien con las demás. Un ejemplo de mal ciudadano es el Singleton. Los singletons mezclan responsabilidades (su funcionalidad más asegurar 1 única instancia), son difíciles (sino imposibles) de probar y aumentan brutalmente el acoplamiento entre clases al usarse como las antiguas variables globales. En lugar de un singleton, usa un pojo con constructor privado para la funcionalidad y haz que sea una factoría la responsable de crearlo (usando reflection para saltarse el constructor privado) y asegurarse que sólo haya 1 instancia. Más sobre el peligro de los singletons aquí.

5 - YAGNI: you arent gonna need it

No programes lo que no vas a necesitar. Construye la funcionalidad más simple que necesites en cada momento.
No desarrolles de forma especulativa, pensando en posibles necesidades futuras.
Me encanta esta imagen:


6 - Cuestiona el porqué

No hagas las cosas porque sí. Piensa antes y comprueba.
A menudo, dentro de una empresa o equipo, se toman como leyes invariables algunas recomendaciones o soluciones concretas y circunstanciales. Incluso cuando su creador ha desaparecido. Seguro que todos tenemos algúna historia con esto...
Además a veces lo intuitivo no es cierto. Neal cita un estudio donde se observó que la programación por parejas produce código 15% menos rápido pero con 15% menos de defectos.

7 - SLAP

Usa el mismo nivel de abstracción para las líneas de un método.
Así conseguirás métodos compuestos de forma natural.

8 - Programación poliglota

Domina distintos lenguajes para resolver cada problema con el lenguaje más apropiado.

9 - Cada matiz

Aprende y aprovecha los matices especiales del lenguaje. Pej. en Java con reflection puedes hacer maravillas, como cambiar el modificador de acceso de métodos en tiempo de ejecución o construir objetos de clases definidas dinamicamente.

10 - Antiobjetos

Solemos modelar los objetos a imagen y semejanza del mundo real. Sin embargo, en ocasiones, es útil obviar la realidad para crear soluciones menos complejas. Es lo que se conoce como antiobjetos. Por ejemplo, si pensamos en el famoso juego Pac-Man, es lógico imaginar que son los fantasmas los que calculan su camino hacia pacman en base al tablero, su posición, la de pacman y si se comió la fruta. Pero en realidad es el tablero quien mueve los fantasmas!


Y tú, ¿conoces alguna otra forma?

Historia de una integración (iv): Colaboración

1 comentarios
La complejidad de un proyecto también radica en las personas involucradas, y no sólo en la tecnología. A más personas, mayor complejidad.

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.

Historia de una integración (iii): El desarrollo

2 comentarios
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...

Tipos de programador

8 comentarios
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.
Los del primer tipo son superiores, los del segundo brillantes. Los del tercero son inútiles.

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.

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...