lunes, mayo 09, 2011

Los 6 principios de Ágil Simple

Cuando estamos durante una implementación ágil, en particular en equipos ágiles nuevos, a menudo hacemos las cosas demasiado complejas y dificiles. Tenemos la tendencia a poner parches y sobre el proceso hastas que termina siendo un monstruo grande y poco útil. ¡Necesitamos intervenir a tiempo! Así que respiren profundo, relájense y veamos juntos cómo simplificar nuestra vida en un equipo ágil.

El punto de inicio son 6 principios básicos que llamo "Ágil Simple".

Los 6 principios de Ágil Simple

  1. Colaborar
  2. Trabajar juntos
  3. Respetar las prioridades
  4. Respetar al cliente, al proceso, al producto, al equipo y a nosotros
  5. Hacer la cosa más simple que funcione - y ahí parar
  6. Mejorar en cada iteración

Repasemos rápidamente esta lista.

1. Colaborar

Muy simple, "colaborar" significa comunicarse de forma efectiva entre nosotros. No existe un equipo ágil sin comunicación. La comunicación tiene que ser lo más cerca posible al tiempo-real , y con la mejora calidad. En contadas ocasiones las personas del equipo podrían no elegir el mejor método de comunicación, pero esto debería ser la excepción a la regla.

2. Trabajar juntos

El paso siguiente a comunicarse bien es trabajar juntos. Por ejemplo, un Dueño del Producto, un tester y un desarrollador llegan a un acuerdo sobre lo que significa una historia en particular. Esto nos significa que el tester y el desarrollador siguen caminos separados. Debemos trabajar juntos y cerca para asegurarnos que este entendimiento compartido siga siendo compartido. Por otro lado, la programación de a pares es beneficiosa por muchos motivos. Está probado que trabajar de a pres incrementa de forma significativa la calidad del producto sin afectar la productividad.

3. Respetar las prioridades

Siempre, siempre, siempre debemos trabajar sobre un backlog PRIORIZADO. Debemos trabajar sobre los requerimientos en el órden en que aparecen en el backlog a menos que surja alguna circunstancia excepcional (como ser una historia demasiado grande para que entre en la iteración, y esperamos a la siguiente iteración para meter antes una historia pequeña). Todos deberían seguir la regla "lo próximo para hacer debería ser una tarea de la más alta prioridad en la que podamos trabajar". Esto significa que más de una persona va a trabajar en la misma historia. Además significa que habrá menos historias abiertas (se limita el trabajo en progreso, o WIP). También nos lleva a entregar al máximo valor en cada iteración.

4. Respetar al cliente, al proceso, al producto, al equipo y a nosotros

¿Cuándo sabe el cliente exactamente lo que quiere? ¡Cuando lo ven, por supuesto! ¿Cuándo saben lo que sienten por el producto? Cuando lo ven. Tenemos que dejar al cliente que vea más seguido a su producto, recolectar el feedback y utilizarlo. Debemos respetar al proceso y seguirlo; todos somos responsables por el éxito del proceso. Debemos respetar al producto disminuyendo su complejidad y quitando la deuda técnica. Debemos respetar al equipo y no imponer metas irreales; el equipo tiene que ser sustentable y ser capaces de resolver sus propios problemas. Debemos respetarnos entre nosotros, trabajando juntos hacia el éxito y apoyandonos todo el tiempo. Podría seguir sobre este tema mucho más. Prueben hacer el siguiente ejercicio: en un papel escriban todas las distintas maneras en la que se podría mejorar el respeto sobre estos temas, y al lado de cada una escriban una lista de los efectos que generarían ese cambio. Se van a sorprender de la diferencia que pueden lograr.

5. Hacer la cosa más simple que funcione - y ahí parar

Todos en la industria del software tenemos la tendencia a hacer demasiado en cada característica. Es como si las recubriéramos en oro. Y es muy facil caer en esta trampa. Es común escuchar cosas como "mientras estaba en eso hice XYZ", o "la historia no decía nada, pero yo sé que al usuario lo quiere así que lo hice". Ninguna de estas frases deberían escucharse en un equipo ágil. Debemos hacer la cosa más simple que funcione - y luego parar. Debemos preguntarle al cliente (recordar que lo respetamos al involucrarlo) si estamos en lo cierto.

6. Mejorar en cada iteración

Recuerden, lograr un 1% mejor por cada iteración de 2 semanas hará que el equipo sea un 25% después de un año. No se necesitan grandes mejoras, sino muchas mejoras pequeñas. Este es el concepto clave de "Ágil Simple" porque nos permite entender que nunca seremos perfectos.

Estos 6 principios están pensados para que los equipos vuelvan a pensar en lo que es importante. Los principios están muy inspirados en los principios del desarrollo Lean. Yo creo en estos principios. Y creo que los equipos logran hacer una enorme diferencia cuando ellos también los creen. ¿Cuántos de estos principios están violando hoy, y qué van a hacer para volver a hacer lo esencial?

Original: 6 principles of Simple Agile, por Bob Hartman

lunes, enero 17, 2011

Prólogo del Libro: "Diseño Ágil con TDD" de @carlosble

Erase una vez que se era, un lejano país donde vivían dos cerditos, Pablo y Adrián que, además, eran hermanos. Ambos eran los cerditos más listos de la granja y, por eso, el gallo Iván (el gerente de la misma) organizó una reunión en el establo, donde les encargó desarrollar un programa de ordenador para controlar el almacén de piensos. Les explicó qué quería saber en todo momento: cuántos sacos de grano había y quién metía y sacaba sacos de grano del almacén. Para ello sólo tenían un mes pero les advirtió que, en una semana, quería ya ver algo funcionando. Al final de esa primera semana, eliminaría a uno de los dos.

Adrián, que era el más joven e impulsivo, inmediatamente se puso manos a la obra. "¡No hay tiempo que perder!", decía. Y empezó rápidamente a escribir líneas y líneas de código. Algunas eran de un reciente programa que había ayudado a escribir para la guardería de la vaca Paca. Adrián pensó que no eran muy diferentes un almacén de grano y una guardería. En el primero se guardan sacos y en el segundo, pequeños animalitos. De acuerdo, tenía que retocar algunas cosillas para que aquello le sirviera pero bueno, esto del software va de reutilizar lo que ya funciona, ¿no?.

Pablo, sin embargo, antes de escribir una sola línea de código comenzó acordando con Iván dos cosas: qué era exactamente lo que podría ver dentro de una semana y cómo sabría que, efectivamente, estaba terminada cada cosa. Iván quería conocer, tan rápido como fuera posible, cuántos sacos de grano había en cada parte del almacén porque sospechaba que, en algunas partes del mismo, se estaban acumulando sacos sin control y se estaban estropeando. Como los sacos entraban y salían constantemente, no podía saber cuántos había y dónde estaban en cada instante, así que acordaron ir contabilizándolos por zonas y apuntando a qué parte iba o de qué parte venía, cada vez que entrara o saliera un saco. Así, en poco tiempo podrían tener una idea clara del uso que se estaba dando a las distintas zonas del almacén.

Mientras Adrián adelantaba a Pablo escribiendo muchas líneas de código, Pablo escribía primero las pruebas automatizadas. A Adrián eso le parecía una pérdida de tiempo. ¡Sólo tenían una semana para convencer a Iván!

Al final de la primera semana, la demo de Adrián fue espectacular, tenía un control de usuarios muy completo, hizo la demostración desde un móvil y enseñó, además, las posibilidades de un generador de informes muy potente que había desarrollado para otra granja anteriormente. Durante la demostración hubo dos o tres problemillas y tuvo que arrancar de nuevo el programa pero, salvo eso, todo fue genial. La demostración de Pablo fue mucho más modesta, pero cumplió con las expectativas de Iván y el programa no falló en ningún momento. Claro,todo lo que enseñó lo había probado muchísimas veces antes gracias a que había automatizado las pruebas. Pablo hacía TDD, es decir, nunca escribía una línea de código sin antes tener una prueba que le indicara un error. Adrián no podía creer que Pablo hubiera gastado más de la mitad de su tiempo en aquellas pruebas que no hacían más que retrasarle a la hora de escribir las funcionalidades que había pedido Iván. El programa de Adrián tenía muchos botones y muchísimas opciones, probablemente muchas más de las que jamás serían necesarias para lo que había pedido Iván, pero tenía un aspecto "muy profesional".

Iván no supo qué hacer. La propuesta de Pablo era muy robusta y hacía justo lo que habían acordado. La propuesta de Adrián tenía cosillas que pulir, pero era muy prometedora. ¡Había hecho la demostración desde un móvil! Así que les propuso el siguiente trato: “Os pagaré un 50% más de lo que inicialmente habíamos presupuestado, pero sólo a aquel de los dos que me haga el mejor proyecto. Al otro no le daré nada.”. Era una oferta complicada porque, por un lado, el que ganaba se llevaba mucho más de lo previsto. Muy tentador. Pero, por el otro lado, corrían el riesgo de trabajar durante un mes completamente gratis. Mmmmm.
Adrián, tan impulsivo y arrogante como siempre, no dudó ni un instante. "¡Trato hecho!", dijo. Pablo explicó que aceptaría sólo si Iván se comprometía a colaborar como lo había hecho durante la primera semana. A Iván le pareció razonable y les convocó a ambos para que le enseñaran el resultado final en tres semanas.

Adrián se marchó pitando y llamó a su primo Sixto, que sabía mucho y le aseguraría la victoria, aunque tuviera que darle parte de las ganancias. Ambos se pusieron rápidamente manos a la obra. Mientras Adrián arreglaba los defectillos encontrados durante la demo, Sixto se encargó de diseñar una arquitectura que permitiera enviar mensajes desde el móvil hasta un webservice que permitía encolar cualquier operación para ser procesada en paralelo por varios servidores y así garantizar que el sistema estaría en disposición de dar servicio 24 horas al día los 7 días de la semana.

Mientras tanto, Pablo se reunió con Iván y Bernardo (el encargado del almacén) para ver cuáles deberían ser las siguientes funcionalidades a desarrollar. Les pidió que le explicaran, para cada petición, qué beneficio obtenía la granja con cada nueva funcionalidad. Y así, poco a poco, fueron elaborando una lista de funcionalidades priorizadas y resumidas en una serie de tarjetas. A continuación, Pablo fue, tarjeta a tarjeta, discutiendo con Iván y Bernardo cuánto tiempo podría tardar en terminarlas. De paso, aprovechó para anotar algunos criterios que luego servirían para considerar que esa funcionalidad estaría completamente terminada y eliminar alguna ambigüedad que fuera surgiendo.Cuando Pablo pensó que, por su experiencia, no podría hacer más trabajo que el que ya habían discutido, dio por concluida la reunión y se dispuso a trabajar. Antes que nada, resolvió un par de defectos que habían surgido durante la demostración y le pidió a Iván que lo validara. A continuación, se marchó a casa a descansar. Al día siguiente, cogió la primera de las tarjetas y, como ya había hecho durante la semana anterior, comenzó a automatizar los criterios de aceptación acordados con Iván y Bernardo. Y luego, fue escribiendo la parte del programa que hacía que se cumplieran esos criterios de aceptación. Pablo le había pedido ayuda a su amigo Hudson, un coyote vegetariano que había venido desde América a pasar el invierno. Hudson no sabía programar, pero era muy rápido haciendo cosas sencillas. Pablo le encargó que comprobara constantemente los criterios de aceptación que él había automatizado. Así, cada vez que Pablo hacía algún cambio en su programa, avisaba a Hudson y este hacía, una tras otra, todas las pruebas de aceptación que Pablo iba escribiendo. Y cada vez había más. ¡Este Hudson era realmente veloz e incansable!.

A medida que iba pasando el tiempo, Adrián y Sixto tenían cada vez más problemas. Terminaron culpando a todo el mundo. A Iván, porque no les había explicado detalles importantísimos para el éxito del proyecto. A la vaca Paca, porque había incluido una serie de cambios en el programa de la guardería que hacía que no pudieran reutilizar casi nada. A los inventores de los SMS y los webservices, porque no tenían ni idea de cómo funciona una granja. Eran tantos los frentes que tenían abiertos que tuvieron que prescindir del envío de SMS y buscaron un generador de páginas web que les permitiera dibujar el flujo de navegación en un gráfico y, a partir de ahí, generar el esqueleto de la aplicación. ¡Eso seguro que les ahorraría mucho tiempo! Al poco, Sixto, harto de ver que Adrián no valoraba sus aportaciones y que ya no se iban a usar sus ideas para enviar y recibir los SMS, decidió que se marchaba, aún renunciando a su parte de los beneficios. Total, él ya no creía que fueran a ser capaces de ganar la competición.

Mientras tanto, Pablo le pidió un par de veces a Iván y a Bernardo que le validaran si lo que llevaba hecho hasta aquel momento era de su agrado y les hizo un par de demostraciones durante aquellas 3 semanas, lo que sirvió para corregir algunos defectos y cambiar algunas prioridades. Iván y Bernardo estaban francamente contentos con el trabajo de Pablo. Sin embargo, entre ellos comentaron más de una vez: "¿Qué estará haciendo Adrián? ¿Cómo lo llevará?".

Cuando se acercaba la fecha final para entregar el programa, Adrián se quedó sin dormir un par de noches para así poder entregar su programa. Pero eran tantos los defectos que había ido acumulando que, cada vez que arreglaba una cosa, le fallaba otra. De hecho, cuando llegó la hora de la demostración, Adrián sólo pudo enseñar el programa instalado en su portátil (el único sitio donde, a duras penas, funcionaba) y fue todo un desastre: mensajes de error por todos sitios, comportamientos inesperados... y lo peor de todo: el programa no hacía lo que habían acordado con Iván.

Pablo, sin embargo, no tuvo ningún problema en enseñar lo que llevaba funcionando desde hacía mucho tiempo y que tantas veces había probado. Por si acaso, dos días antes de la entrega, Pablo había dejado de introducir nuevas características al programa porque quería centrarse en dar un buen manual de usuario, que Iván había olvidado mencionar en las primeras reuniones porque daba por sentado que se lo entregarían. Claro, Adrián no había tenido tiempo para nada de eso.

Moraleja:

Además de toda una serie de buenas prácticas y un proceso de desarrollo ágil, Pablo hizo algo que Adrián despreció: acordó con Iván (el cliente) y con Bernardo (el usuario) los criterios mediante los cuáles se comprobaría que cada una de las funcionalidades estaría bien acabada. A eso que solemos llamar "criterios de aceptación", Pablo le añadió la posibilidad de automatizar su ejecución e incorporarlos en un proceso de integración continua (que es lo que representa su amigo Hudson en este cuento). De esta manera, Pablo estaba siempre tranquilo de que no estaba estropeando nada viejo con cada nueva modificación. Al evitar volver a trabajar sobre asuntos ya acabados, Pablo era más eficiente. En el corto plazo, las diferencias entre ambos enfoques no parecen significativas, pero en el medio y largo plazo, es evidente que escribir las pruebas antes de desarrollar la solución es mucho más eficaz y eficiente.

Sitio Web: http://www.dirigidoportests.com

Descarga: http://www.dirigidoportests.com/wp-content/uploads/2010/02/disenoAgilConTdd_ebook.pdf

lunes, octubre 25, 2010

9 cosas que todo desarrollador debe saber

El libro 97 things every programmer should know contiene 97 pequeños consejos y prácticas que como desarrolladores deberíamos aplicar a diario en el desarrollo de software. En su blog, Brian Du Preez destaca 9 consejos en particular que le resultaron de interés. Veamos cuáles son...

1. La regla del Boy Scout (por Robert C. Martin, Uncle Bob)

"No es necesario hacer que cada módulo sea perfecto antes de subirlo al repositorio de código. Simplemente basta con hacer que sea un poquito mejor que cuando lo bajamos".

Nos resulta fácil decirnos cosas como "Ya estaba así", o "ese código horrible está así desde hace años, no voy a tocarlo", o "nunca tuvo pruebas". Si parte de nuestro proceso fuera hacer las cosas un poquito mejor (como borrar código que no se usa, o escribir una prueba unitaria), año tras año... lograríamos ahorrar mucho tiempo y dinero a muchas personas.

2. La belleza está en la simplicidad (por Jørn Ølmheim)

"Al final, el código hermoso es el código simple"

Con los años esto me resultó muy importante. Cuando empecé esta carrera, y especialmente cuando tenía que comenzar algo nuevo, me embarcaba en crear los mega-diseños. Era algo como "Bienvenido a la escuela de la sobre-ingeniería", todo sería una abstracción al décimo nivel, y habría patrones de patrones, interfaces para las abstracciones y enormes cantidades de código y componentes que se encargaban de cualquier "qué pasaría si" que podría existir, y que sólo yo comprendía. Todo esto llevaba a código muy "atractivo", y aumentaba mi ego, ¿pero a qué costo?

Sólo había un pequeño detalle: mantenerlo era una pesadilla. Desde entonces prefiero la implementación más simple para casi cualquier solución, incluso aunque no parezca la mejor implementación técnica. En el mundo del software, la mantenibilidad siempre debería pesar más que otros temas.

3. Detenete y automatizá, automatizá, automatizá (por Cay Hosrtmann)

Debemos automatizar todo lo posible: construcciones, despliegues, análisis de código, pruebas unitarias, pruebas funcionales, pruebas de integración. Nadie quiere mirar estas cosas todos los días y la automatización es la única forma de alejarnos de esto. No podemos automatizar demasiado. Automatizá, automatizá, automatizá.

4. Aprendizaje continua (por Clink Shank)

Este es un tema muy importante, estamos en una industria de constante crecimiento y cambio, y como programadores necesitamos estar aprendiendo y mejorando siempre que podamos. Es fácil caer en la zona de confort y descansar sobre los laureles. Algunas cosas que recomiendo:

  1. Lean libros.
  2. Usen Google Reader y agreguen blogs populares y feeds RSS de sitios web para temas específicos de su interés, además de agregar algunos otros temas que no sean de su interés particular.
  3. Creen un blog, y traten de publicar algo 1 -2 veces por semana, asegurándose que sea cosas nuevas que aprendieron.
  4. Únanse a alguna comunidad de software libre, en general no tenemos suficiente desarrollo "técnico" en los ambientes corporativos.

5. Antes de culpar a otros verificá tu código (por Allan Kelly)

Como dice el título, tendemos a buscar la culpa en cualquier cosa excepto nuestro código "perfecto". Desde el sistema operativo hasta la red, desde la base de datos hasta la JVM, desde librerías hasta las interfaces de otros equipos. Esto nos lleva a horas y horas de esfuerzo desperdiciado, o ignorar por completo el problema real que eventualmente volverá a molestarnos. La mayoría de nosotros puede recordar momentos en los que hicimos esto... y es tan frecuente que asusta.

6. El trabajo duro no vale la pena (por Olve Maudal)

"La verdad es que trabajando menos podemos lograr más"

"Si tratás de estar enfocado y "productivo" por más de 30 horas a la semana, seguramente estás trabajando demasiado"

Una gran frase de Olve Maudal. Muchos de nosotros ya pasamos por esto, gastamos días, semanas meses de trabajo, pero no solemos ver los efectos negativos que ocurren después de trabajar 50-70 horas por semana. Desde la lógica común hasta la motivación y la dinámica del equipo, todo esto sale por la ventana. Incluso aunque se logren los objetivos a corto plazo, a menudo las repercusiones a largo plazo son mucho peores. Nadie revisa porqué hay que re-escribir después de 4 años debido a que la arquitectura o el código nos sirven. Me encantaría saber cuántas de estas situaciones son por trabajar una cantidad ridícula de horas con tiempos imposibles. Puede haber alguna ocasión donde sea necesario un par de horas extras, pero debemos mantener esto al mínimo.

7. Comentar sólo lo que el código no dice (por Kevin Henney)

Lo que dice. No le contemos a otro programador lo que puede saber leyendo el código. Los comentarios tienen que explicar el motivo de negocio detrás de un algoritmo en particular, lo cual es mucho más útil que un //sumar 1

8. Conocer al IDE (por Heinz Kabutz)

Pasamos varias horas con nuestro IDE. Aprender los atajos, las características que tiene... usar el IDE con todo su potencial nos puede ahorrar incontables horas.

9. Aprender a estimar (por Giaovanni Asproni)

Si bien esto es algo que viene con la experiencia, podemos hacer cosas para mejorar esta habilidad. Algunos puntos para mejorar nuestras estimaciones:

  1. Sean honestos con ustedes mismos, digan lo que saben y admitan abiertamente lo que no.
  2. Tengan presente lo que hacen y cuánto les lleva, no necesariamente para el líder del proyecto sino para ustedes mismos. Sean honestos con ustedes mismos.
  3. No cuenten las estimaciones ni habilidades percibidas de otras personas. Sean honestos con ustedes mismos.

jueves, octubre 21, 2010

TDD y Unit Tests




Benefícios de Test-Driven Development

  • El conjunto de test unitarios proporciona contante retroalimentación de que cada uno de los componentes sigue funcionando.
  • Los test unitarios actuan como documentación que no se queda obsolet, al contrarío que otros tipos de documentación.
  • Cuando el test pasa y el código de producción es refactorizado para eliminar duplicidades, es claro que el código está terminado, y el desarrollador se puede mover a la siguiente tarea.
  • TDD fuerza un análisis y diseño crito porque el desarrollador no puede crear código de producción sin entender realmente cuales deberían ser los resultado deseados y como probarlos.
  • El software tiende a estar mejor diseñado, esto es, menos acoplado y más facilmente mantenible, porque el desarrollador es libre de hacer decisiones de diseño y refactorizar en cualquier momento con la confianza de que el software todavia funciona.
  • El conjunto de tests actua como una red de seguridad contra regresiones en los bugs: Si se encuentra un bug, el desarrollador debe crear un test que ponga de manifiesto el bug y despues modificar el código de producción para eliminar el bug. En sucesivas ejecuciones de los test, todas las correcciones de bugs son verificadas.
  • El tiempo de depuración se reduce.

Características de un buen unit test

  • Se ejecuta rápido, se ejecuta rápido, se ejecuta rápido. Si los test son lentos, no se ejecutaran a menudo.
  • Separa o simula dependencias ambientales como bases de datos, sistemas de archivos, redes, colas y demás. Los test que ejercitan estos no serán rápidos y los fallos no dan información significativa sobre cual es el problema realmente.
  • Es muy limitado en su alcance. Si el test falla, es obvio donde bucar el problema. Realiza pocas llamadas a la clase Assert de manera que el código que falla sea obvio. Es importante probar una única cosa en cada test.
  • Se ejecuta y pasa de manera independiente. Si los tests requieren establecer entorno especial o fallan inexperadamente, no son buenos tests unitarios. Cambialos por simplicidad y fiabilidad. Los teste deben ejecutarse y pasarse en cualquier máquina. La excusa "funciona en mi máquina" no sirve.
  • Usa a menudo stubs y mock objects. Si el código que está siendo probado llama a un base de datos o al sistema de archivos, estas dependencias deben ser simuladas. Esta dependencias habitualmente serán abstraidas usando interfaces.
  • Revela claramente su intención. Otro desarrollador puede ver el test y comprender que se espera que haga el código de producción.

Arquitectura SOA: Los Servicios. Introducción

Definición

En una arquitectura SOA la funcionalidad de la aplicación está expuesta a través de una colección de servicios. Estos servicios son independientes y encapsulan tanto la lógica de negocio como los datos asociados.

Desde una perspectiva empresarial, los servicios son activos independientes que se corresponden con actividades comerciales reconocibles o funciones comerciales del mundo real y que son accesibles de acuerdo con las políticas que se hayan establecido para los mismo.

Desde un punto de vista técnico podemos decir que se trata de componentes autónomos de grano grueso, con interfaces bien definidas (contratos de servicio) y con una clara separación entre su interface pública y su implementación privada interna.

Los servicios interactúan entre sí a través de mensajes, con un esquema que define su formato, un contrato para definir sus intercambios y la definición de una política de cómo deben ser intercambiados.

Aplicaciones como conjunto de Servicios.

El primer paso en cualquier proyecto de SOA es identificar claramente los problemas críticos para el negocio o desafíos.

Los servicios incluirán los procesos de negocio y serán publicados para su consumo por parte de usuarios, sistemas u otros servicios.

Los servicios pueden utilizar otros servicios para cumplir sus funciones, serán en este caso servicios compuestos de otros servicios.

La creación de grandes aplicaciones será un proceso iterativo de incluir nuevos servicios y publicarlos.

En la terminología SOA componer nuevos servicios basándonos en los ya existente se llama Orquestación (Orchestration) al igual que en una orquesta iremos combinando instrumentos para realizar tareas más complejas.

La importancia del contrato

Las aplicaciones SOA publican sus servicios y no saben quien los va a usar ni donde, estando

fuera del control de la aplicación. Publican un contrato (interface) que se mantendrá constante a lo largo del ciclo de vida del servicio. El ciclo de vida de un servicio diferencia entre los servicios en producción y en desarrollo, para los servicios en producción nunca se modificará su interface sino que en su lugar el servicio se marcará como en desuso y se notificará a sus consumidores que hay una nueva versión del servicio disponible que deberán usar.

Es fundamental la separación entre la interface y la implementación. El usuario de un servicio sólo necesita (y debe) conocer la interface. La implementación puede cambiar a lo largo del tiempo sin que para ello deba afectar a sus consumidores .

Servicios Web

Como comentamos antes, un error muy común es confundir servicios, componentes que forman una arquitectura SOA, con servicios web. Los servicios web son una forma de implementar estos servicios, pero no es obligatorio que los servicios estén implementados como servicios web aunque sí es lo más común.

En nuestro próximo artículo vamos a profundizar en los servicios web como forma más habitual de implementar los servicios de una arquitectura SOA, haciendo referencia a las dos formas más habituales de servicios web (SOAP y RESTFUL) y las principales diferencias entre ellas.

Breve Introducción a SOA

Si tu conocimiento sobre SOA se limita a la realización de algunos Web Services, pero te apetece conocer un poco más en profundidad la Arquitectura Orientada a Servicios.

En éste primero voy a enumerar 5 ideas fundamentales que debes conocer sobre SOA.

  1. SOA no son webservices. Los servicios web son una forma de implementar los servicios de SOA, la más conocida e implantada, pero incluso sin webservices podríamos tener SOA siempre que tengamos una forma estándar de comunicar los servicios entre sí. Digamos que los servicios web son los árboles y SOA va sobre el bosque entero.
  2. Los servicios en SOA representan procesos de negocio. Hay una relación directa entre los procesos de negocio de una empresa y los servicios que se van a implementar en SOA, de tal manera que un proceso de negocio estará formado por la llamada a varios servicios.
  3. SOA no tiene porque ser válido para todas las organizaciones, donde realmente tiene sentido es en grandes sistemas distribuidos y heterogéneos donde el bajo acoplamiento entre los distintos componentes es el factor más importante. Si nuestra empresa no tiene componentes distribuidos y además todo está bajo la misma plataforma probablemente SOA no nos aporte nada.
  4. Implantar SOA no significa cambiar todos nuestros sistemas por un nuevo (y carísimo) software basado en SOA, uno de los principios de SOA es aprovechar los sistemas heredados, realizando servicios que se encargarán de actuar como fachada entre estos sistemas y el resto de servicios.
  5. El Gobierno SOA es un factor fundamental en una arquitectura SOA y es el encargado de velar porque se cumplan los principios de la arquitectura.

Por último algunas siglas que deberías conocer:

  • ESB: Enterprise Service Bus o bus de servicio empresarial, es el encargado de facilitar la comunicación entre los servicios y puede ofrecer muchas funcionalidades de valor añadido como alta disponibilidad, enrutamiento inteligente, orquestación de procesos, monitorización, etc.
  • BPM: Business Process Management o gestión de procesos de negocio, es complementario a SOA, como los servicios representan procesos de negocio es factible que se puedan crear nuevos procesos de negocio en base a la combinación de los servicios ya existentes, con lo que dando de alta nuestros servicios en una herramienta BPM los podemos combinar incluyendo condiciones y utilizando para ello un lenguaje específico como BPEL (Business Process Execution Language)

martes, agosto 17, 2010

No escribo pruebas unitarias porque... (manual de excusas)

Siendo alguien que vive los beneficios de hacer TDD, creo profundamente en el desarrollo guiado por pruebas. Esta práctica agrega un nuevo nivel de calidad y madurez al desarrollo de software, y sin embargo todavía no es la técnica más usada en los proyectos de software. Cuando hay que elegir entre características, tiempo y calidad, siempre sufre la calidad. No queremos agregar tiempo extra para hacer pruebas, y tampoco queremos comprometer las características que vamos a entregar. Si no se pusieron como objetivo hacer TDD al iniciar el proeycto, es dificil hacerlo después.

Todos escuchamos excusas para no hacer TDD, pero nadie las juntó mejor que "Pragmatic Unit Testing in Java With JUnit", de la serie Pragmatic Bookshelf. Hace un par de años que leí ese libro, y desde entonces creo que no hay forma que un desarrollador responsable pueda leer este libro sin entender que las pruebas unitarias son uno de los aspectos más importantes del desarrollo de software.

La excusa más preocupante que escucho es que es demasiado dificil probar mi código. Esto puede ser por dos motivos. Uno es que el código sea principalmente de interfaces de usuario (UI), y automatizar las pruebas de UI es muy dificil. Entiendo que la automatización de UI son bastantes complejas (¡y no imposibles!), pero se debería dedicar todo el esfuerzo en automatizar lo más posible: piensen en las pruebas de regresión. Si tienen una suite de pruebas completamente automatizada, incluyendo el comportamiento del UI, podrán hacer cambios al código con total confianza de no romper nada.

El segundo motivo de que el código es demasiado dificil de probar es que hicieron desastre con el diseño. Quizás la lógica y el código de UI están muy acoplados. Es por esto que TDD ayuda a mantener un diseño limpio, siguiendo las mejores prácticas. Usar JUnit es simple, y si puedo ejecutar toda la capa lógica por tener un diseño limpio, entonces podré probar toda la lógica que el UI va a usar. ¿Qué les falta el modelo de datos? Entonces pueden usar objetos mocks - ¡hay muchos frameworks para esto!

Para quienes todavía no leyeron el libro, les dejo un breve resumen de las excusas para no hacer TDD:

Escribir pruebas lleva mucho tiempo

Este es el principal motivo que dan los desarrolladores, y creo que se debe a cómo nos enseñan a desarrollar software. En general, nos hacen creer que la estapa de pruebas ocurre al final del proceso, y no durante todo el desarrollo.

TDD fomenta el modelo "pagar a medida que se avanza", en donde escribimos las pruebas mientras desarrollamos, por lo que no tenemos que meter tiempo al final del proceso para escribir todas las pruebas que podamos.

Y de todas formas, si no estás escribiendo pruebas a medida que avanzás, ¿cómo comprobás que el código se comporte como esperás? ¿Lo ejecutás manualmente? ¿No tiene más sentido invertir algo de este tiempo de pruebas manuales en escribir una prueba JUnit para esto? Quiero decir, en algún momento vas a tener que ejecutar esa porción de código - no va a quedar sin tocar el resto de la vida del producto.

De hecho, ocurren muchas más penalizaciones de tiempo si no se escriben pruebas unitarias. Vas a tener que gastar tiempo haciendo debug del código intentando averiguar porque algo no funciona. O vas a hacer un refactor, y luego darte cuenta que nada funciona como antes del refactor. Si tuvieras las pruebas unitarias, tendrías una base segura.

Lleva mucho tiempo ejecutar las pruebas

Si, puede llevarse bastante tiempo ejecutar pruebas que involucran a entidades externas, o pruebas de la interfaz de usuario. Pero se supone que hay más de un nivel de pruebas. Las pruebas unitarias deberían ejecutarse rápido, y podría haber un nivel de integración que también corra sin mucho impacto de tiempo. Si hay pruebas de integración que toman mucho tiempo, será cuestión de correrlas con menos frecuencia - quizás de manera nocturna. Esto no quiere decir que debemos ignorar las pruebas unitarias. Estas siempre deberían correr lo suficientemente ráipdo como para ser parte natural del proceso de software.

Mi trabajo no es probar el código

Todavía no sé en qué momento un desarrollador de software decide que puede tirar código contra la pared así nomás. Si nuestro trabajo fuera de "Codificador" quizás ahí tendríamos una mejor excusa. Pero nuestro trabajo consiste en desarrollar código que funcione, y por lo tanto necesitamos alguna forma de mostrar que nuestro código es funcional. Si a la gente de QA les cuesta encontrar bugs en nuestro código, va a ser maravilloso para nuestra reputación.

En realidad no sé cómo funciona el código, por lo que no puedo probarlo

Esta es dificil de tomar sin ser incrédulos. Si no entendemos cómo debería funcionar el código, no deberíamos empezar a programar. Primero debemos entender el requerimiento.

El libro tiene un par de excusas más, pero estos son las principales. ¿Qué excusas escucharon ustedes para no escribir pruebas?

Fuente: DosIdeas