miércoles, 17 de noviembre de 2010

La Técnica Pomodoro

En una profesión como es la informática, nuestro mayor aliado se convierte también en nuestro mayor enemigo. Nos pasamos horas programando delante del ordenador, y éste no es sólo nuestra herramienta de trabajo, sino también una tentación constante para la distracción.

Cuando uno trabaja en un tarea necesita estar centrado en ella para poder realizarla de la mejor manera posible. Esto no se consigue si interrumpimos la ejecución de dicha tarea cada dos por tres porque nos ha llegado un correo o se nos acaba de ocurrir qué mirar en Internet.

Tampoco es bueno realizar una tarea de forma ininterrumpida durante horas, puesto que la concentración del ser humano disminuye a medida que pasa el tiempo. Por ello, parece ser mejor intercalar periodos de esfuerzo relativamente cortos con pequeños descansos que sirvan a nuestra mente para asimilar el conocimiento que hemos adquirido, descansar y permitirnos afrontar el siguiente esfuerzo con energía.

La Técnica Pomodoro, desarrollada por Francesco Cirillo, trabaja en esta línea de forma que aprendamos a manejar los esfuerzos personales de una forma que nos permita centrarnos en lo que estamos haciendo, llegar a establecernos un ritmo de trabajo constante y sostenible, estructurar las actividades a realizar de forma incremental y hacernos capaces de realizar planificaciones razonables sobre ellas.

Implementar la Técnica Pomodoro es sencillo, puesto que las herramientas que se necesitan son muy básicas:
  • Un reloj.

  • Una hoja dónde registrar las actividades a realizar en el día. Existirá en ella una sección donde registrar actividades urgentes que no estaban planificadas y hayan ido apareciendo.

  • Una hoja de registro de las actividades pendientes.

  • Una hoja donde se muestre información de análisi de los datos registrados.

También se pueden usar herramientas más elaboradas como hojas de cálculo o aplicaciones con bases de datos. Sin embargo, se recomienda usar el método más simple posible para que las herramientas no supongan un impedimento a la técnica en sí.

La Técnica Pomodoro tiene los siguientes objetivos, que se pueden ir logrando de forma recursiva mediante su aplicación:

Primer objetivo: Descubrir cuánto esfuerzo requiere una actividad

Éste es el primer objetivo de la Técnica Pomodoro. El esfuerzo se mide en periodos de 30 minutos llamados pomodoros: 25 minutos de actividad y 5 de descanso.

Una vez priorizadas las tareas a realizar en el día de hoy, extraídas de la hoja de actividades pendientes, se comienzan a realizar respetando los tiempos del pomodoro. Cada vez que se cumple uno de estos periodos se registra en la hoja de actividades del día, junto a la actividad que se estaba ejecutando.

Se deben respetar los periodos de esfuerzo de 25 minutos, no pueden durar menos ni más. Si no se llegan a cumplir los 25 minutos realizando la tarea, este intervalo no se considera válido. Si se cumplen los 25 minutos se debe parar y descansar durante 5 minutos. Tras cada 4 pomodoros se debe parar durante un rato más largo de unos 30 minutos.

Al final del día podemos evaluar el número de pomodoros que nos ha llevado realizar cada actividad y, por tanto, el esfuerzo invertido.

Segundo objetivo: Reducir el número de interrupciones

El mayor problema para la ejecución efectiva de un pomodoro son las interrupciones. Por ello, se deben establecer estrategias para eliminar tanto las interrupciones externas cómo las internas.

Las interrupciones internas son las provocadas por nosotros mismos y por la falta de capacidad para concentrarnos. Debemos hacer visible el número de éste tipo de interrupciones y hacer lo posible por reducirlo.

Para ello, cada vez que tengamos la tentación de interrumpir la tarea que estamos realizando para hacer otra cosa, se marca la tarea con un apóstrofe (‘) y se añade una nueva en la lista de actividades urgentes o en la hoja de actividades pendientes, según su urgencia, para que sea realizada posteriormente. Tras esto, debemos volver a la tarea que estamos realizando.

Las interrupciones externas son las provocadas por otra gente. Debemos conseguir que ocurran cuando nosotros queramos, dentro de lo posible. Si alguien viene a pedirnos que hagamos algo, debemos tratar de posponerlo para después si es posible.

Para registrar estas interrupciones, se pone un guión en la actividad que estemos realizando (-) y se añade una nueva tarea en la lista de actividades urgentes o en la hoja de actividades pendientes, según su urgencia, para que sea realizada posteriormente. Tras esto, debemos volver a la tarea que estamos realizando.

Una vez que sabemos qué interrupciones sufrimos, se pueden buscar estrategias para reducirlas al mínimo.

Tercer objetivo: Estimar el esfuerzo necesario para realizar una actividad

Con la experiencia acumulada hasta el momento debemos tratar de estimar el esfuerzo que requiere una actividad, de forma que podamos usar estas estimaciones para planificar nuestro trabajo diario.

La estimación de una tarea no debe ser mayor de unos 7 pomodoros. Hay que mantener tareas no desmasiado grandes puesto que las tareas pequeñas facilitan su estimación. Tampoco debemos tener tareas con estimaciones inferiores a un pomodoro. Para lograr esto debemos agrupar o dividir tareas según sea necesario.

Una vez estimadas las tareas, si vemos que durante la ejecución llegamos al número de pomodoros estimados sin haberla terminado, debemos hacer una segunda estimación del esfuerzo restante y, si fuese necesario una tercera. Si hacen falta menos pomodoros de los estimados continuamos normalmente.

Al final del día, a la hora de registrar lo que ha pasado, debemos resaltar las diferencias entre las estimaciones y la realidad. El objetivo en posteriores pomodoros será tratar de reducir las terceras y las segundas estimaciones y, por último, tratar de acertar en la primera estimación.

Cuarto objetivo: Aumentar la efectividad del pomodoro

En este punto, y con la experiencia adquirida, podemos decidir organizar la estructura del pomodoro de la forma que más nos convenga. Puede ser interesante utilizar los primeros minutos de un pomodoro para repasar todo lo hecho hasta el momento, y los últimos 5 para repasar lo hecho en éste pomodoro.

También se pueden organizar los grupos de 4 pomodoros reservando alguno de los pomodoros para tareas específicas.

Quinto objetivo: Definir una agenda

El hecho de establecer uan agenda permite definir límites respecto a las tareas a realizar. Esto permite separar el tiempo de trabajo y el tiempo libre, entendiendo el tiempo libre como algo necesario y beneficioso para que la persona vuelva a reemprender las tareas productivas con energía y concentración.

Una agenda también permite comparar los resultados obtenidos y comprobar si se ajustan a lo esperado para, en caso de lo contrario, poder tomar medidas correctoras. El hecho de registrar el número de pomodoros que finalizamos cada día permite organizar nuestra agenda en función de ello, sin caer en planes demasiado optimistas que se alejen de la realidad del día a día.

Impresiones personales

No he hecho más que empezar a utilizar esta técnica y este post no es más que una forma de reforzar lo aprendido, puesto que he utilizado la Técnica Pomodoro para gestionar mi tiempo durante el estudio y redacción de dicho artículo.

Sin embargo, durante este poco tiempo he percibido las siguientes impresiones al respecto:
  • La motivación de usarla era tratar de reducir las interrupciones. El fijarme periodos de trabajo sin interrupciones no demasiado largos me ha permitido limitar las visitas a Twitter, Facebook, Gmail… a los tiempos entre pomodoros, cuando hasta hace poco era algo que hacía continuamente casi de forma compulsiva mientras realizaba otras tareas.

  • Por otra parte, en otras ocasiones me he autoexpuesto a periodos excesivamente largos de trabajo continuado, lo cual me ha llegado a producir agotamiento y dificultad para concentrarme en las horas finales de la jornada laboral. El hecho de parar sistemáticamente cada cierto tiempo para descansar o, por lo menos, separar lo ojos de la pantalla, me está resultando beneficioso y me permite mantenerme con energía hasta el final de la jornada.

  • La sensación de aburrimiento o monotonía ha disminuído, aunque esto no puedo decir con seguridad si es por el uso de la propia Técnica Pomodoro o por el hecho de estar inmerso en un nuevo tema de estudio interesante. Esto ya lo iré viendo durante los próximos días.

  • La Técnica Pomodoro me obliga a mantener un registro de las tareas que he realizado durante el día, lo cual me permite saber en qué he invertido realmente el tiempo y cuánto he malgastado. Esto me está permitiendo organizarme mejor para aprovechar el tiempo.

  • El conocer el esfuerzo de las tareas realizadas me permite hacer estimaciones más realistas sobre las tareas a desarrollar. Sé a qué me puedo comprometer y evito la frustración por no llegar a alcanzar los compromisos.

También debo decir que es la primera vez que estoy usando una de estas técnicas de gestión personal del tiempo, puesto que parece que la Técnica Pomodoro no es la única. No puedo decir si es mejor o peor que otras, pero sí parece que el uso de una ayuda a la eficiencia personal.

Para terminar, recomendo que si estáis interesados os leáis el libro de Francesco Cirillo donde explica la Técnica Pomodoro, disponible gratuitamente en PDF.

Recursos
The Pomodoro Technique
La Técnica Pomodoro en Wikipedia
Aumenta tu concentración con la Técnica Pomodoro
La técnica Pomodoro
No sabes nada de la Técnica Pomodoro
Técnica Pomodoro extrema

miércoles, 3 de noviembre de 2010

Patrones de diseño: Strategy

Este patrón permite que el algoritmo a ejecutarse se seleccione en tiempo de ejecución. Este algoritmo proporciona una familia de algoritmos, encapsula cada uno dentro de un objeto y los hace intercambiables. Esto permite que el algoritmo a ejecutarse varíe en función del cliente que lo use.

¿Qué ventajas proporciona el uso de éste patrón?

En primer lugar, es mucho más fácil comprender cada uno de los distintos comportamientos si su implementación está encapsulada en distintas clases, y no entrelazada en un único método. Esto permite de forma simple añadir nuevos comportamientos, y elminar o modificar los existentes.

En los casos en que existan varios objetos cuyo comportamiento sea parcticamente el mismo, esto se puede reducir a una única clase que haga uso de distintas estrategias. Esto reduce el uso de subclases y, por tanto, el acoplamiento entre ellas

¿Cómo se implementa este patrón?

Las posibles estrategias se ejecutan dentro de un objeto de contexto que se encarga de recuperar la estrategia apropiada para el cliente. Cada una de las estrategias implementa una interfaz que define la firma del método de la estrategia.

Vamo a ver un ejemplo que permita aclarar esto. Por ejemplo, en un banco existen distintos tipos de cuentas, para las cuáles se siguen distintos algoritmos a la hora de calcular sus rendimientos anuales. Un objeto encargado de calcular los rendimientos de las cuentas (en este ejemplo, éste sería el objeto de contexto) podría utilizar distintas estrategias para calcular el rendimiento de cada tipo de cuenta.

El siguiente diagrama representa el ejemplo anterior:

Si ahora se quisiese incluir un nuevo tipo de cuenta, por ejemplo una Cuenta Vivienda, simplemente habría que crear una nueva estrategia que implemente el algoritmo de cálculo de rendimiento y hacer que el objeto CalculadoraRendimiento relacione este tipo de cuenta con la estrategia adecuada.

De esta manera, se ha desacoplado el cálculo del rendimiento específico de cada tipo de cuenta, separando cada uno en una clase haciéndolos más claros de entender y más fácilmente modificables.

Referencias:
Strategy Pattern en Wikipedia
The Strategy Design Pattern
Patrón Strategy
Otros patrones de diseño

jueves, 28 de octubre de 2010

Patrones de diseño: Template Method

Estre patrón define el funcionamiento general de un algoritmo en una operación de una clase, delegando en otras clases, a través de herencia o dependencia entre clases, la implementación específica de cada uno de sus pasos. Permite que estas clases redefinan ciertos pasos del algoritmo sin cambiar su comportamiento general, adaptandose cada una de ellas a una necesidad específica.

Una implementación clásica de este patrón es la que aparece en el libro “Design Patterns” del GOF, que presenta una clase abstracta en la que se define el comportamiento general de una operación en un método concreto que llama a su vez a otros métodos abstractos en los que se definen comportamientos más específicos. Distintas subclases pueden heredar de esta clase y especificar comportamientos diferentes para los métodos abstractos, permitiendo varias implementaciones que se puedan ajustar a cada necesidad.

El siguiente diagrama UML presenta un ejemplo basado en esta forma de implementación del patrón Template Method:

En él, una clase Juego define en su método jugar() el comportamiento general de cualquier juego, el juego comienza y cada uno de los jugadores va haciendo su jugada hasta que se cumple una condición que da fin al juego y se muestra el resultado. Estas operaciones se indican mediante métodos abstractos que deben ser implementados por cada juego específico de forma apropiada, como pueden ser el Parchis o el Ajedrez.

Sin embargo, al ser la herencia la forma de acoplamiento más fuerte que existe entre clases, en busca de una mayor flexibilidad se propone una implementación alternativa basada en la dependencia entre clases en lugar de la herencia.

El siguiente diagrama muestra un ejemplo de implementación del patrón Template Method usando la dependencia entre clases:

En él se muestra una clase plantilla JuegoTemplate con un método jugar() que define el comportamiento general de cualquier juego. Igual que antes, el juego comienza y cada uno de los jugadores va haciendo su jugada hasta que se cumple una condición que da fin al juego y se muestra el resultado. Estas operaciones son llevadas a cabo por una instancia de una clase que implementa la interfaz Juego, interfaz que especifica los métodosque deben ser implementados por cada juego específico. Las clases Parchis y Ajedrez implementan la interfaz Juego y definen el comportamiento específico de estos juegos.

Esta forma de implementar el patrón Template Method es el usado en Spring para proporcionar, por ejemplo, soporte en el acceso a JDBC o Hibernate, a través de sus plantillas JDBCTemplate o HibernateTemplate, que usan una instancia de una clase que implementa la interfaz DataSource y que encapsula el comportamiento específico de acceso a una fuente de datos.

Referencias:
Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson, Hohn Vlissides)
Patrón Template Method en Wikipedia
Implementacion de pattern Template utilizando composición e inyección
The Template Design Pattern
Patrón Template Method
Otros patrones de diseño

martes, 28 de septiembre de 2010

Error extraño en Sonar con JFreeChart y Novell SecureLogin

Durante algún tiempo no he podido visualizar los gráficos de las estadísticas generados en Sonar a través de JFreeChart en mi equipo del trabajo.

Revisando los logs de Sonar encontré las siguientes trazas:

2010.09.23 11:57:21 ERROR org.mortbay.log Error for /chart
java.lang.NoClassDefFoundError:
Could not initialize class org.jfree.chart.JFreeChart
...
2010.09.23 11:57:21 ERROR org.mortbay.log Error for /chart
java.lang.UnsatisfiedLinkError:
no sljava in java.library.path
...

Al parecer, el error es debido a que no encontraba la librería sljava.dll en la ruta descrita por la propiedad java.library.path, definida en el archivo wrapper.conf de la configuración de Sonar.

Esta librería es una librería de Novell SecureLogin, que tengo configurado en mi equipo y parace que es la instalación de este producto lo que provoca el error.

La solución ha sido tan sencilla como llevar la librería sljava.dll a la ruta de java.library.path. Ahora bien, ni idea de qué está pasando...

martes, 31 de agosto de 2010

Patrones de diseño: Proxy

Según la Wikipedia, el patrón Proxy se utiliza como intermediario para acceder a un objeto, permitiendo controlar el acceso a él.

Este patrón es ampliamente utilizado en frameworks cómo Hibernate o Spring AOP, permitiendo capturar las llamadas a objetos POJO y permitiendo insertar en ellas capacidades de persistencia para el caso de Hibernate, u otro tipo de aspectos como gestión de seguridad o transacciones para Spring AOP.

A continuación mostramos el diagrama de clases del patrón Proxy:

En este patrón se identifica una interfaz Subject, un objeto RealSubject que es el objeto al que se accede a través del Proxy. El objeto Proxy mantiene una referencia al objeto RealSubject y controla el acceso a sus métodos, intruciendo las capacidades adicionales que fuesen necesarias. Tanto la clase RealSubject como la clase Proxy implementan la interfaz Subject.

En Java es fácil crear proxies dinámicos en tiempo de ejecución a partir de la clase java.lang.reflect.Proxy. Veámoslo a través de un ejemplo.

Creamos una interfaz:
package com.roldan.proxy;

public interface Lector {
public void leer();
}

Ahora creamos una implementación para esta interfaz:
package com.roldan.proxy;

public class LectorImpl implements Lector {

public void leer(){
System.out.println("Estamos leyendo...");
}
}

En este momento, creamos el proxy para la clase LectorImpl:
package com.roldan.proxy;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class LectorProxy
implements java.lang.reflect.InvocationHandler {

private Object obj;

public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new LectorProxy(obj));
}

private LectorProxy(Object obj) {
this.obj = obj;
}

public Object invoke(
Object proxy,
Method m,
Object[] args) throws Throwable {
Object result;
try {
System.out.println(
"Antes de llamar al metodo " + m.getName());
result = m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
System.out.println(
"Despues de llamar al metodo " + m.getName());
}
return result;
}
}

Esta clase, que usa el patrón singleton, crea dinámicamente un proxy para la instancia de la clase que se pasa a su método newInstance() gracias a las capacidades de la clase java.lang.reflect.Proxy.

El método invoke() de esta clase captura las invocaciones a este proxy y las redirige al objeto LectorImpl en lugar del que actúa, añadiéndolo funcionalidad adicional, que en este caso consiste en mostrar mensajes antes y después del método invocado.

Ahora podemos crear una instancia de este proxy y acceder a los métodos de la interfaz Lector que implementa:
package com.roldan.proxy;

public class PruebaLector {
public static void main(String[] args) {
Lector lector = (Lector)LectorProxy.newInstance(
new LectorImpl());
lector.leer();
}
}

Si ejecutamos la prueba, obtenemos la siguiente salida por la consola:
Antes de llamar al metodo leer
Estamos leyendo...
Despues de llamar al metodo leer


Vemos que la llamada al método leer() gestionada por el proxy ha sido adornada con los dos mensajes adicionales.

A pesar de la sencillez de este ejemplo, el uso de proxies dinámicos permite la ejecución de tareas avanzadas en frameworks de gran complejidad como Hibernate o Spring AOP.

Referencias:
Patrón de diseño Proxy en Wikipedia
¿Cuál es el problema que resuelve el patrón de diseño Proxy?
Patrón de diseño Proxy en Adictos al Trabajo
Dynamic Proxy Classes
Otros patrones de diseño

miércoles, 28 de julio de 2010

Kanban y Scrum – Obteniendo lo mejor de ambos

Tras un mes de vacaciones, volvemos a la carga con el blog. Voy a empezar por un libro cortito cuya lectura ya tenía en mente antes de ir de vacaciones y que continúa el tema de las metodologías ágiles, haciendo una introducción a Kanban en este caso.

Este libro es la traducción al castellano, realizada por el equipo de contenidos de Agile Spain del libro de Henrik Kniberg y Mattias Skarin “Kanban vs Scrum – a practical guide”.

En el prólogo de este libro, David Anderson expone que la idea principal de Kanban consiste en limitar el trabajo en progreso (WIP – Work In Progress), utilizando tarjetas (kanban) como indicadores de que nuevos bloques pueden ser incorporados en un paso del flujo de trabajo. Está basado en las ideas extraídas del sistema de producción de Toyota (TPS – Toyota Production System) y se engloba dentro de las metodologías ligeras (Lean).

También comenta que Kanban introduce una aproximación a la gestión del cambio. Se comienza a hacer Kanban comprendiendo el flijo de trabajo actual y estableciendo límites para el trabajo en curso en cada una de sus fases. El trabajo es arrastrado (pull) a través del sistema a partir de señales Kanban. Mostrando este avance del trabajo en un panel se hacen visibles las deficiencias en el proceso y permite su mejora y adaptación continua.

El propósito de este libro es introducirnos a lo que es Kanban, comparándolo con Scrum, y a cómo pueden ser útiles en nuestro entorno. Para ello, el libro se divide en dos partes, en la primera parte Henrik Kniberg compara Kanban y Scrum y en la segunda parte Mattias Skarin presenta un ejemplo práctico de aplicación de Kanban.

Como he dicho, en la primera parte, más teórica, se comparan Scrum y Kanban a través de los siguientes capítulos:
  1. Bueno, pero, al fin y al cabo, ¿qué son Scrum y Kanban?: En este capítulo se resume de forma breve lo que es cada una de estas dos metodologías. Ya conocemos Scrum, así que sólo me detendré en las ideas principales de Kanban: visualizar el flujo de trabajo, limitar el WIP y medir el tiempo de ciclo para hacer que sea lo más pequeño y predecible posible.

  2. Entonces, ¿cómo se relacionan Scrum y Kanban entre sí?: Scrum y Kanban son herramientas de proceso que porporcionan ciertas restricciones y directrices. Ambos son métodos ligeros menos restrictivos que los métodos tradicionales y muy adaptables, siendo Scrum algo más restrictivo que Kanban. Estas herramientas no son excluyentes y se pueden mezclar entre sí y con otras herramientas como algunas de las ideas de XP.

  3. Scrum prescribe roles: Mientras que Scrum prescribe los roles de dueño del producto, equipo y Scrum Master, Kanban no establece ningún rol. Pero existe libertad para añadir los roles que se consideren necesarios.

  4. Scrum prescribe iteraciones de tiempo fijo: Scrum está basado en iteraciones de tiempo fijo que determinan la cadencia del proyecto. En una iteración se combinan las actividades de planificación, mejora del proceso y entrega. En Kanaban no existen iteraciones, por lo que estas actividades se pueden realizar siguiendo cualquier estrategia.

  5. Kanban limita el WIP por estado en flujo de trabajo, Scrum limita el WIP por iteración: Kanban limita el número de elementos al mismo tiempo en un estado del flujo de trabajo. En Scrum, el límite es el número de elementos en la pila del producto.

  6. Ambos son empíricos: En Scrum y Kanban el proceso se puede controlar de forma indirecta a través de parámatros como el número de componentes del equipo, el límite de trabajo en curso, la existencia de iteraciones… Son empíricos en el sentido de que se espera que experimentes con el proceso y lo adaptes a tu entorno. A este proceso de mejora se le denomina “kaizen” en terminología Lean, y se trata de buscar una realimentación sobre el proceso que de información sobre cómo mejorarlo.

  7. Scrum se resiste a los cambios durante la iteración: Scrum no permite modificar la pila del sprint durante el mismo, permitiendo al equipo mantenerse enfocado durante un periodo de tiempo suficiente. Kanban, en cambio, permite cambiar los elementos en la entrada del flujo de trabajo siempre que se respete el límte del WIP establecido.

  8. El tablero sprint se limpia entre iteraciones: En Scrum, cuando finaliza un sprint, el tablero se limpia y todos los elementos son eliminados. En Kanban, el tablero no se limpia, los elementos simplemente van avanzando a través de las columnas.

  9. Scrum prescribe equipos multifuncionales: En Scrum, el tablero pertenece a un equipo, y un equipo tiene todo el conocimiento necesario para llevar a cabo una iteración. En Kanban el tablero está relacionado con un flujo de trabajo y puede pertenecer a varios equipos de distintas funcionalidades.

  10. Los elementos de la pila de producto deben caber en un sprint: En Scrum, si un problema es demasiado grande para caber en un sprint, éste se descompone. En Kanban, aunque es interesante tener elementos pequeños que minimicen el tiempo de entrega, no es obligatorio que estos se ajusten a un intervalo de tiempo específico.

  11. Scrum prescribe la estimación y la velocidad: En Scrum los equipos estiman el tamaño relativo de cada elemento al que se comprometen, y sumando el tamaño de cada elemento se obtiene la velocidad. En Kanban no es necesario estimar, pero algunos equipos lo hacen para poder garantizar el tiempo de entrega promedio.

  12. Ambos permiten trabajar en múltiples productos simultáneamente: En Scrum, la pila de producto podría completarse con elementos de varios proyectos. Esto mismo, se puede hacer también en Kanban.

  13. Ambos son Lean y Ágiles: Ambos son sistemas de optimización “pull”, basados en procesos de optimización continuos y que priorizan la respuesta al cambio frente al seguimiento de un plan, entre otras características.

  14. Diferencias menores: diferencias menos relevantes entre Scrum y Kanban son que Scrum prescribe una pila de producto priorizada, establece reuniones diarias y utiliza gráficos burndown. En Kanban se utilizan diagramas de flujo acumulativo que representan como el WIP afecta al plazode entrega.

  15. El tablero Scrum vs. El tablero Kanban – un ejemplo menos trivial: En este apartado se muestran casos de utilización de un tablero Kanban en distintas situaciones. También se dan directrices sobre cómo aplicar los límites Kanban.

  16. Resumen de Scrum vs. Kanban: En este apartado se resumen los parecidos y las diferencias entre ambos vistos en los capítulos anteriores.

La segunda parte es un ejemplo de cómo poner Kanban en práctica. Con ello, el libro es una introducción estupenda a Kanban, sobre todo para aquellos que ya han visto algo de Scrum y que se preguntan cuál es la diferencia entre ambas herramientas.

Referencias:
Blog de Henrik Kniberg
Página web de Navegapolis

jueves, 17 de junio de 2010

Conceptos principales de Scrum

Basándome en lo explicado en el libro de Henrik Kniberg “Scrum y XP desde las trincheras”, en este post lo que pretendo es recopilar y explicar brevemente los conceptos principales en los que se basa Scrum.

Vamos a separar por un lado las personas implicadas en un proyecto que sigue esta metodología y, por otro lado, los productos y tareas que hay que completar durante el proceso que Scrum propone.

En primer lugar las personas:
  • El cliente: Es la persona que solicita un proyecto de cara a satisfacer una necesidad propia o de su negocio.

  • El propietario del producto (Product Owner): Es la persona que hace de intermediario entre el cliente (no técnico) y el equipo y tiene capacidad de decisión sobre los requisitos a implementar.

  • El equipo: Es el personal técnico que se encargará de la realización del proyecto.

  • El Scrum Master: Es la persona conocedora del proceso Scrum que se encarga de orientar al equipo y al propietario del producto para que sigan el proceso determinado por Scrum. Si las personas involucradas en el proyecto ya conocen Scrum su labor puede no ser necesaria.

Y, en segundo lugar, los productos y tareas necesarias:
  • La pila de producto: Es una lista priorizada de requisitos o “historias” del cliente escritos usando su propia terminología, de forma no técnica.

  • Reunión de planificación del sprint: En esta reunión el equipo y el propietario del producto negocian sobre el alcance de cada sprint en base a las estimaciones y a la importancia de cada una de las historias de la pila del producto.

  • La pila de sprint: El la lista de historias sacadas de la pila del producto que conforman el alcance del sprint actual.

  • Reunión diaria de scrum: En esta reunión el equipo discute los problemas que se va encontrando a medida que el producto avanza y revisa sus estimaciones para poder llevar el seguimiento del avance del proyecto.

  • Demostración: Como colofón a cada sprint se debe presentar una demostración de aquello que se ha implementado, de cara a obtener retroalimentación sobre el proyecto por parte de los interesados que permita encaminar futuros sprints.

  • Retrospectiva: Al final de cada sprint se lleva a cabo una reunión que permite revisar qué se ha hecho bien y mal durante el sprint con el objetivo de mejorar el proceso.

Para terminar, resumiré de forma breve el proceso que define Scrum:
  • En primer lugar, el propietario del producto construye la pila del producto con las historias de usuario o requisitos del proyecto. La pila del producto no es algo invariable, será modificada a medida que avanza el proyecto y se clarifican los requisitos.

  • Antes de cada sprint, iteración de aproximadamente 3 o 4 semanas, el equipo y el propietario del producto se reunen para decidir que historias de la pila del producto se van a implementar en él. Estas historias a implementar forman la pila del sprint.

  • Durante el sprint, el equipo tendrá una reunión diaria de sprint, en la que se actualiza la evolución del proyecto y se tratan de resolver posibles problemas.

  • Al final del sprint, se lleva a cabo la demostración, en la que se exponen las nuevas funcionalidades implementadas durante el sprint.

  • Antes de comenzar un nuevo sprint, se lleva a cabo una retrospectiva que permite identificar posibles mejoras en la forma de trabajar.


Referencias:
Aplicando Scrum y XP
Metodologías ágiles
Qué es Scrum

martes, 15 de junio de 2010

Scrum y XP desde las trincheras

Aunque ya lo he leído hace algún tiempo, ahora mismo siento la necesidad de releer el libro de Henrik Kniberg “Scrum & XP from the trenches” (“Scrum y XP desde las trincheras” en su traducción al español ) en busca de ideas que aplicar para tratar de incorporarlas en las nuevos proyectos que voy a comenzar.

En este libro, disponible para su descarga gratuita, Henrik Kniberg cuenta sus propias experiencias durante la implantación de Scrum en la empresa en la que estaba trabajando. En él expone sus ideas acerca de cómo usar la metodología de desarrollo ágil Scrum.

El libro, con prólogos por parte de Jeff Sutherland y Mike Cohn, consta de los siguientes capítulos:
  1. Introducción: Según el propio creador de Scrum, Ken Schwaber, Scrum no es una metodología, sino un marco de trabajo y, por tanto, no dice exactamente qué es lo que hay que hacer. Sin embargo, en este libro, Henrik Kniberg sí que dice qué es exactamente lo que él hace para aplicar Scrum. A pesar de ello, previene de que Scrum es una metodología que debe adaptarse a la situación específica de cada proyecto.

  2. Cómo hacemos las pilas de producto: La pila de producto es una lista priorizada de requisitos o “historias” del cliente escritos usando su propia terminología, de forma no técnica.

  3. Cómo nos preparamos para la planificación de sprint: El propietario de la pila de producto debe tener ésta ya preparada para cuando se va a planificar un sprint. El propietario debe comprender todas las historias de usuario y asignarlas una importancia.

  4. Cómo hacemos la planificación de sprint: La reunión de planificación de sprint es la actividad más crítica de Scrum. La meta de esta reunión es definir un objetivo, la lista de miembros del equipo implicados, la lista de tareas que se desarrollarán, una fecha de demostración y un lugar y hora para la reunión de scrum diaria. En ellas, el propietario de producto y el equipo negocian sobre el alcance de cada sprint en base a las estimaciones y a la importancia de cada una de las historias.

  5. Cómo comunicamos los sprints: Es necesario informar a todo el mundo de qué está ocurriendo en cada sprint. Para ello, después de la reunión de planificación del sprint se debe redactar una hoja de información del sprint que recoja los objetivos que se han definido. Esta hoja debe publicarse para todo el mundo.

  6. Cómo hacemos las pilas de sprint: Después de la reunío de planificación de sprint y antes de la primera reunión de scrum diaria, el Scrum master debe crear la pila de sprint. La pila de sprint es la lista de tareas que se realizan durante el sprint, con gráficos de avance de estas tareas (burndown). La forma más efectiva de mostrar la pila de sprint es mediante un tablón en la pared.

  7. Cómo distribuímos la sala del equipo: Las discusiones más interesantes tienen lugar de forma espontánea delante de una pizarra donse se puedan pintar diagramas o gráficos de diseño. Los miembros del equipo se pueden reunir en frente de esta pizarra y discutir sobre el diseño en cualquier momento. También es importante que los miembros del equipo se sienten junto para fomentar la comunicación entre ellos. El propietario del producto no debe estar sentado con el equipo para que no sienta la tentación de medrar en los detalles, pero debe sí estar accesible para el equipo por si surge alguna duda y hay que preguntarle. El resto de la gente no debe interferir para nada con el equipo.

  8. Cómo hacemos los scrums diarios: El mejor sitio para el scrum diario es delante del tablón con la pila de scrum. Durante la reunión, que no debe durar mucho más de 15 minutos, se debe actualizar el tablón con los avances que el equipo ha realizado.

  9. Cómo hacemos la demo de sprint: El hecho de tener que hacer demostraciones al final de cada sprint fuerza al equipo a tener algo hecho que mostrar y fomenta lo comunicación sobre lo que se está haciendo dentro del equipo y con otros equipos que asistan a la demostración. Las demostraciones además permiten obtener realimentación sobre el proyecto por parte del cliente.

  10. Cómo hacemos las restrospectivas de sprint: La retrospectiva es la segunda tarea más importante, puesto que es la que premite mejorar. La restrospectiva es una reunión que tiene lugar al final de cada sprint donde el equipo expone sus ideas sobre qué cosas se pueden hacer mejor.

  11. Descansos entre sprints: Después de cada sprint, que pueden ser muy intensos, es necesario un tiempo de descanso que permita además asimilar nuevas ideas o información.

  12. Cómo hacemos la planificación de entregas y los contratos de precio fijo: En algunos casos, normalmente unidos a un contrato de precio fijo, es necesario planificar con antelación las entregas de varios sprints posteriores. Para ello el propietario del producto necesita estimaciones de las tareas incluidas en el contrato, que se deben haber realizado de forma conjunta con el equipo. En función de estas estimaciones y la velocidad del equipo se establece el plan de entregas a lo largo de los siguientes sprints. Este plan puede ser modificado a medida que surgen cambios según el proceso avanza.

  13. Cómo combinamos Scrum con XP: Scrum y XP se complementan a la perfección, puesto que Scrm se centra en la gestión y la organización del proyecto y XP se centra en las prácticas de programación. Algunas de las prácticas de XP son también parte inherente de Scrum, como el concepto de equipo, sentarse juntos, las historias de usuario y el juego de la planificación. Además, hay otras prácticas de XP que se complementan con Scrum, como la programación en parejas, el desarrollo guiado por pruebas (TDD), el diseño incremental, la integración continua, la propiedad colectiva del código y su estandarización y el trabajo a un ritmo enérgico pero sostenible.

  14. Cómo hacemos pruebas: Esta es la parte más difícil del desarrollo de software y la más variable entre distintas organizaciones. Es necsario realizar algún test de aceptación manual antes de dar un trabajo por realizado. Sin embargo, se puede reducir esta fase de test aumentando la calidad del código entregado y aumentando la eficiencia de las pruebas automáticas realizadas. O, incluso, incluir que algún miembro del equipo realice tareas de tester. El tester será la persona que certifique que una tarea está completamente terminada. Las pruebas de aceptación no encajan bien dentro del ciclo de un sprint, por lo que se definen ciclos de aceptación fuera del sprint.

  15. Cómo manejar múltiples equipos Scrum: Los equipos demasiado grandes no se adaptan bien a las prácticas de Scrum porque la comunicación entre todos los miembros es mucho más difícil. Es preferible tener varios equipos pequeños que uno grande, si el proyecto lo permite. El número ideal de personas parece estar entre 5 y 9 personas.

  16. Cómo gestionamos equipos distribuidos geográficamente: Aquí se discuten distintas formas de gesrionar equipos distribuídos, que pueden ser bien distintos equipos en localizaciones distintas o un mismo equipo con miembros distribuídos.

  17. Lista de comprobación del Scrum Master: Aquí se listan las tareas administrativas del Scrum Master, tareas que debe realizar al comienzo, durante y al final de cada sprint.

Este libro es una introducción estupenda a Scrum y permite comenzar a usar esta metodología siguiendo las ideas que en él se exponen. Luego, a través de la práctica, se pueden ir perfeccionando las prácticas en base a aquello que resulte realmente valioso.

Referencias:
Scrum & XP from the trenches
Scrum y XP desde las trincheras

jueves, 10 de junio de 2010

Patrones de diseño: Adapter

Este patrón convierte la interfaz de una clase en otra distinta que es la que esperan los clientes y permite que cooperen clases que de otra manera no podrían por tener interfaces incompatibles.

Se encarga de proporcionar a una clase cliente el interfaz que necesita para trabajar utilizando en su implementación una clase o clases que no cumplen con dicho interfaz.

La mejor forma de ver este patrón es a través de un ejemplo. Supongamos que tenemos una clase Cliente que realiza cálculos matemáticos complejos cuya realización se delegan en otra clase. Vamos a suponer a modo de ejemplo que estos cálculos complejos pueden ser una suma o una resta. La interfaz requerida por esta clase cliente para sus cálculos se define en la interfaz Calculadora:
package com.roldan.adapter;

public interface Calculadora {
public int suma(int operador1, int operador2);
public int resta(int operador1, int operador2);
}

Para la ejecución de estos complejos cálculos se dispone de la clase Procesador que los implementa:
package com.roldan.adapter;

public class Procesador {
public static final int SUMA = 1;
public static final int RESTA = 2;

public static int realizarOperacion(
int operador1,
int operador2,
int operacion) {
int resultado = 0;

switch(operacion) {
case SUMA:
resultado = operador1 + operador2;
break;
case RESTA:
resultado = operador1 - operador2;
break;
}

return resultado;
}
}

En este caso, a pesar de que la clase Procesador realiza las operaciones que necesita la clase Cliente, no implementa la interfaz que ésta necesita para poder usarla. Sin embargo, se puede crear una clase Adaptador que adapte la clase Procesador a la interfaz Calculadora:
package com.roldan.adapter;

public class Adaptador implements Calculadora {
public int suma(
int operador1,
int operador2) {
return Procesador.realizarOperacion(
operador1,
operador2,
Procesador.SUMA);
}

public int resta(
int operador1,
int operador2) {
return Procesador.realizarOperacion(
operador1,
operador2,
Procesador.RESTA);
}
}

De esta forma, la clase Cliente puede usar los cálculos realizados en la clse Procesador a través de la clase Adaptador, que la adecúa a la interfaz Calculadora que necesita la clase Cliente.

El siguiente diagrama UML refleja las relaciones entre dichas clases:

Adapter pattern en Wikipedia
Patrón Adaptador en Wikipedia
Design Patterns Uncovered: The Adapter Pattern en DZone
Adapter Pattern en OODesign.com
Otros patrones de diseño

viernes, 4 de junio de 2010

Consideraciones sobre el diseño

Este artículo está basado en el artículo de Martin Fowler “Is Design Dead?” y en su traducción al castellano realizada por Alejandro Sierra.

La verdad es que he descubierto en Martin Fowler una verdadera fuente de inspiración y de ideas sobre la ingeniería del software. En los últimos tiempos, basándome en sus artículos, estoy encontrando respuestas y reflexiones valiosas sobre los problemas que me afectan como desarrollador de software.

En este caso, llevo algún tiempo en conflicto entre la idea de realizar el diseño al principio del proyecto, paralizando todo desarrollo hasta tener una visión clara, o comenzar a desarrollar tan pronto como sea posible para tener algo que ofrecer como propugnan las metodologías ágiles, aunque esto implique rehacer lo ya hecho cuando las ideas se aclaran o varían.

En este artículo, Martin Fowler expone sus ideas sobre el diseño dentro de una metodología ágil como es XP que, aparentemente, no le da importancia.

Hay dos maneras de plantear el diseño, el diseño evolutivo y el diseño planeado:
  • Durante el diseño evolutivo el diseño se realiza a medida que el sistema evoluciona, formando parte de la programación. Esta forma de diseño suele acabar en desastre porque termina siendo una agregación de decisiones puntuales que complican el código y deterioran el diseño.
  • El diseño planeado se corresponde con la visión del diseño de cualquier ingeniería clásica, en donde se trata de anticipar los problemas de forma abstracta sin entrar en la codificación hasta haber terminado esta fase de diseño. Sin embargo, es difícil anticipar todos los problemas antes de comenzar con la programación, lo que hace aparecer tensiones entre programadores y diseñadores. También se pueden producir cambios en los requisitos que pueden deberse a cambios en el negocio y que, por tanto, son muy difíciles de preveer y de controlar sus efectos.

XP aboga por el diseño evolutivo. Sin embargo, para ello propugna una serie de prácticas que permiten controlar los efectos negativos de este tipo de diseño. Según la curva del cambio del software, el coste del cambio en programación aumenta exponencialmente a medida que avanza un proyecto, dificultando el diseño evolutivo. Pero esta curva se puede aplanar mediante una serie de prácticas que reducen el efecto de los cambios. Estas prácticas son:
  • Pruebas: permiten controlar el efecto de los cambios eviatndo la introducción de nuevos errores.
  • Integración continua: permite mantener el equipo en sincronía evitando que los cambios afecten a más gente.
  • Refactorización: permite limpiar el código y hacerlo más mantenible y fácil de modificar.

En el diseño evolutivo XP dice que “hay que hacer la cosa más simple que pueda funcionar” y que no lleve a cabo todo aquello que no sea necesario (principio YAGNI – “You Ain’t Gonna Need It”). Se trata de mantener el diseño lo más simple posible haciendo sólo aquello estructamente necesario. Para ello existen dos razones:
  • Si se hace algo que no es necesario ahora mismo se está comprometiendo el esfuerzo para quello que sí lo es. Además, se puede estar haciendo de forma incorrecta por falta de información, es mejor posponer su implementación hasta que se conozca con más detalle.
  • Un diseño complicado es más difícil de comprender e implementar que uno sencillo. Haciendo lo estrictamente necasio se tiene un diseño más sencillo y fácil de implementar.

Sin embargo, esta forma de mantener el diseño simple añadiendo posteriormente lo que se vaya convirtiendo en necesario sólo es factible si se están usando las prácticas anteriormente descritas para reducir el costo del cambio.

Como pautas de le lo que es un diseño simple, Kent Beck expone los siguientes cuatro criterios:
  • Correr todas la pruebas.
  • Revelar toda la intención del código haciendo que sea fácil de leer.
  • Evitar duplicación.
  • El menor número de clases y métodos.

No es necesario perder demasiado tiempo buscando el diseño más simple. La refactorización permite irlo simplificando a medida que se va entendiendo. Tampoco es bueno usar patrones de diseño sin ton ni son, es mejor dejar que el diseño evolutivo te guíe hacia el uso de un patrón que introducirlo prematuramente.

Respecto al uso de diagramas y UML XP dice que se usen si son útiles, pero no es partidario de su uso. Los diagramas pueden ser útiles para la comunicación siempre y cuando se reduzcan a la mayor sencillez posible. Sin embargo, el uso de diagramas se complica cuando se producen cambios durante la evolución del proyecto, porque es difícil mantenerlos en sincronía con el código.

Algo importante en el diseño es evitar la irreversibilidad de las decisiones. De esta manera la toma de decisiones no es dramática porque las malas decisiones pueden ser deshechas. En este sentido es importante contar con sistemas de control del código que permitan garantizar la reversibilidad.

Es importante contar con gente involucrada en el diseño. Alguien debe ejecercer control sobre el proyecto vigilando el diseño del código y responsabilizándose de él. Estas personas deben actuar cuando se detecta que el diseño puede verse comprometido o hay alguna dificultad técnica durante el proyecto. Esta rol es el del líder técnico. No tiene sentido el rol de arquitecto, puesto que no puede existir el diseño por parte de alguien que luego se desentienda de la construcción del software.

El diseño de un proyecto se puede medir en función de la calidad del código base. Si la calidad del código base de un proyecto se deteriora y se vuelve más difícl trabajar, entonces el diseño es insuficiente. Éste es un criterio subjetivo, pero es la gente técnica la que primero sufre la dificultad de hacer cambios y a quienes se debe escuchar.

Según Martin Fowler, la naturaleza del sideño ha cambiado. Ahora se buscan las siguientes habilidades:
  • Mantener el código tan claro y simple como sea posible.
  • Ser capaz de refactorizar, haciendo mejoras en el diseño cuando sea necesario.
  • Conocer y reconocer patrones y cuándo evolucinar hacia ellos.
  • Saber comunicar el diseño mediante diagramas, código y comunicación directa con las demás personas.

Como resumen, Martin Fowler aboga por un diseño evolutivo que permita comenzar con el desarrollo de forma temprana. Pero esto no se puede hacer de cualquier manera, es necesario introducir prácticas que faciliten el cambio durante el desarrollo de forma que el diseño pueda mejorar y adaptarse a las nuevas necesidades que vayan apareciendo.

Esto va en contra de un diseño planeado que deja todo por sentado en un larga fase inicial y que es seguido por una fase de implemantación en que los cambios no se contemplan y que, cuando se incorporan porque terminan siendo absolutamente inevitables, son difíciles de incorporar, rompiendo el diseño previamente establecido e introduciendo una gran propensión a errores.

El diseño evolutivo delega gran cantidad de trabajo de diseño en los desarrolladores. No existe la figura de arquitecto como persona que realiza todo el trabajo de diseño, sino como alguien que supervisa el trabajo de estos. Se debe contar con un equipo capaz y comprometido para poder seguir esta forma de trabajo, de lo contrario, se hace inviable.

Referencias:
Is Desing Dead? - Por Martin Fowler
¿Ha muerto el diseño? - Traducción de Alejandro Sierra
Examining the Agile Cost of Change Curve

lunes, 12 de abril de 2010

UML2

Este libro de Anaya Multimedia es la traducción al castellano de “UML2 and the Unified Process”, escrito por Jim Arlow e Ila Neustadt. Este libro no sólo es una introducción al lenguaje de modelado UML en su versión 2, también presenta el flujo de trabajo el Proceso Unificado, que es el proceso de desarrollo de software creado por los autores de UML y utiliza UML como lenguaje de modelado.

El libro, nos sumerge en UML y UP a través de los siguientes capítulos:

  1. ¿Qué es UML?: Se presenta UML como un lenguaje de modelado visual. UML permite crear modelos de la arquitectura de los objetos de un sistema, capturando la estructura estática y el comportamiento dinámico del mismo a través de diagramas, compuestos de elementos y relaciones. Se presentan los mecanismos de especificación, adornos, divisiones comunes y extensibilidad que se utilizan en UML para construir el modelo.

  2. ¿Qué es el proceso unificado?: Es un proceso de ingeniería del software de los mismos autores que UML. Es un proceso dirigido por riesgo y requisitos, centrado en la arquitectura, iterativo e incremental. Cada iteración realiza los workflows de requisitos, análisis, diseño, implementación y prueba. Separa la vida del proyecto en las fases de comienzo, elaboración, construcción y transición.

  3. El workflow de requisitos: El workflow de requisitos se desarrolla principalmente durante las fases de comienzo y elaboración y recoge y organiza los requisitos funcionales y no funcionales. Se presentan técnicas que ayudan a encontrar requisitos, como las entrevistas, cuestionarios y workshops.

  4. Modelado del caso de uso: Los casos de uso son funciones que el sistema realiza en nombre de actores específicos. Se dan pautas sobre cómo encontrar estos casos de uso y define una especificación de caso de uso que los describe. Se indica la necesidad de crear una matriz de trazabilidad de requisitos que relacione los requisitos funcionales y los casos de uso.

  5. Modelado avanzado de caso de uso: En este capítulo se explica la generalización de actores y la generalización, inclusión y extensión de casos de uso. Se dan sugerencias para escribir casos de uso.

  6. El workflow de análisis: Se presenta el workflow de análisis, que trata de crear modelos que capturen los requisitos esenciales y las características del sistema deseado. Se presentan las características del modelo de análisis y los artefactos y actividades del workflow de análisis. Se dan reglas generales para el análisis.

  7. Objetos y clases: Se presentan que son los objetos y las clases y su notación en UML.

  8. Encontrar clases de análisis: Se presenta la actividad de análisis de un caso de uso, centrándose en la obtención de clases de análisis. Se definen las propiedades de estas clases de análisis y se dan reglas generales sobre sus propiedades. Se presentan las técnicas para encontrar estas clases, como el análisis nombre/verbo, el análisis CRC y los estereotipos RUP.

  9. Relaciones: Se analizan las relaciones, conexiones semánticas entre los elementos de un modelo que son equivalentes a que una clase tenga un pseudoatributo que pueda albergar instancias de la otra clase. Las conexiones entre objetos son los vínculos, y las asociaciones son las conexiones entre clases. Las asociaciones pueden estar definidas por un nombre de asociación, nombres de roles, multiplicidad y navegabilidad. Se presentan las clases de asociación y las asociaciones cualificadas. Las dependencias son relaciones en que un cambio en el proveedor afecta al cliente. Las dependencias pueden ser de uso, de abstracción o de permiso.

  10. Herencia y polimorfismo: La herencia de clase es una relación de generalización entre clases. La subclase puede añadir nuevas características o anular operaciones heredadas. Las clases abstractas tienen alguna operación abstracta y no se pueden heredar. El polimorfismo permite que una operación tenga distintas implementaciones según su clase. Se presentan los conjuntos de generalización y los powertypes.

  11. Paquetes de análisis: El paquete es el mecanismo de agrupación de UML. Todo elemento del modelo está contenido en un paquete. Un paquete define un conjunto de nombres encapsulado. Existen varias relaciones de dependencia entre paquetes: use, import, access, trace, merge. El análisis de la arquitectura de un sistema trata de dividir conjuntos cohesivos de clases de análisis en paquetes de análisis. Es importante maximizar la cohesión dentro de los paquetes y minimizar las dependencias de otros paquetes.

  12. Realización de casos de uso: Las realizaciones de casos de uso muestran cómo las instancias de clases de análisis interactúan para realizar los requisitos funcionales especificados por los casos de uso. Las interacciones están representadas por las líneas de vida de los participantes y los mensajes que se envían entre ellos para comunicarse. Las interacciones se expresan mediante diagramas de interacción, que pueden ser principalmente de secuencia o de comunicación.

  13. Realización avanzada de casos de uso: Se muestran características avanzadas de los diagramas de interacción, como las ocurrencias de interacción, que pueden hacer uso de parámetros o puertas, y las continuaciones.

  14. Diagramas de actividad: Son diagramas de flujo orientados a objeto que se utilizan para modelar todo tipo de procesos. Tienen semántica de Redes de Petri. Las actividades son redes de nodos conectadas por extremos. Se presenta la notación de los diagramas de actividad.

  15. Diagramas avanzado de actividad: Se presentan características avanzadas de diagramas de actividad, como regiones de actividad interrumpibles, pins de excepción, nodos protegidos, nodos de expansión, envío y recepción de señales y conjuntos de parámetros.

  16. Workflow de diseño: En esta actividad se trata de determinar como se implementará la funcionalidad especificada en el modelo de análisis. Es la principal actividad de la última parte de la fase de elaboración y de la primera parte de la fase de construcción. Se discute la conveniencia de mantener modelos aparte de análisis y diseño.

  17. Diseñar clases: Las clases de diseño son clases cuyas especificaciones se han completado hasta un nivel que se puede implementar. Proceden tanto del ámbito del problema como del de la solución. Tienen especificaciones completas y presentan las características de ser completas, suficientes, sencillas, altamente cohesionadas y poco acopladas. Las clases de diseño hacen uso de la herencia y la realización de interfaz.

  18. Mejorar relaciones de análisis: Convertir relaciones de análisis en relaciones de diseño implica convertir asociaciones en agregación o composición, implementar clases de asociación, implementar asociaciones uno a muchos, muchos a uno, muchos a muchos, bidireccionales, añadir navegabilidad, añadir multiplicidad, añadir nombres de rol a los extremos y utilizar clasificadores estructurados.

  19. Interfaces y componentes: Las interacciones entre subsistemas están mediadas por interfaces, que especifican un conjunto de características públicas. Diseñar mediante interfaces permite hacer las cosas más flexibles a costa de mayor complejidad. Los componentes son partes modulares del sistema y que encapsulan contenidos, siendo éstos componentes reemplazables. Un subsistema es un componente que actúa como una unidad de descomposición para un sistema más amplio. Se utilizan interfaces para ocultar los detalles de implementación de los subsistemas.

  20. Realización de un caso de uso: diseño: La realización de un caso de uso en diseño es una extensión de la realización de un caso de uso en análisis y se encarga de encontrar las clases de diseño, interfaces y componentes que interactúan para proporcionar el comportamiento de un caso de uso. La realización de un caso de uso se muestra en diagramas de interacción de diseño y diagramas de clase de diseño. Se utilizan clases activas para modelar concurrencia, diagramas de interacción de subsistema para mostrar interacciones entre sus partes y diagramas de tiempo para modelar restricciones de tiempo.

  21. Máquinas de estado: Las máquinas de estado se basan en el trabajo de Harel y modelan comportamiento dinámico de un objeto reactivo. Las máquinas de estado pueden ser de comportamiento o de protocolo. Los diagramas de estado se componen de acciones, actividades, estados, transiciones y eventos.

  22. Máquinas de estado avanzadas: Los estados compuestos pueden tener una o más submáquinas anidadas. Un estado compuesto secuencial tiene una submáquina anidada, un estado compuesto concurrente contiene dos o más submáquinas anidadas que se ejecutan concurrentemente. La historia (superficial o profunda) permite que un superestado recuerde el último subestado antes de una transición de salida.

  23. El workflow de implementación: Es el foco principal de la fase de construcción y trata sobre la transformación de un modelo de diseño en código ejecutable.

  24. Despliegue: Los diagramas de despliegue permiten modelar la distribución de un sistema de software sobre hardware físico. Un diagrama de despliegue está formado por nodos, relaciones y componentes.

El libro termina con material adicional, como una referencia al Lenguaje de Restricción de Objetos (OCL – Object Constraint Language).

Es un libro que me ha resultado fácil de leer y que creo que hace una buena introducción al modelado de sistemas en análisis y diseño, proporcionando técnicas útiles y buenos consejos.

viernes, 9 de abril de 2010

JBoss Drools

Según la Wikipedia: "Las reglas de negocio describen las políticas, normas, operaciones, definiciones y restricciones presentes en una organización y que son de vital importancia para alcanzar sus objetivos. Las reglas de negocio especifican en detalle lo que una organización puede hacer."

Ejemplos de reglas de negocio podrían ser:
  • "A una persona que ingresa más de 20.000 euros al año Hacienda le retiene el 15%"
  • "A los clientes que gasten más de 1.000 euros se les hace un descuento del 5%"

Como se ve en los ejemplos, las reglas de negocio tienen una semántica if/then, si se cumple una determinada condición se debe realizar una determinada acción.

Cuando un negocio dispone de muchas reglas que se deben aplicar, las aplicaciones que las gestionan se convierten en una maraña de código formado por estructuras if/else anidadas, que dificultan enormemente la comprensión y mantenibilidad del código.

Si las reglas de negocio se aíslan del resto del código, se está separando la verdadera inteligencia sobre el negocio (las reglas) del resto del programa. Los sistemas de gestión de reglas de negocio (BRMS – Bussiness Rule Management System) permiten gestionar de forma independiente las reglas de negocio. Facilitan la modificación o inclusión de nuevas reglas en tiempo de ejecución.

Dentro de los sistemas de gestión de reglas de negocio en Java más populares hoy en día encontramos Drools. Drools es un BRMS de JBoss que implementa la Java Rule Engine API (JSR 94) y utiliza una implementación mejorada del algoritmo de Rete para la ejecución de reglas.

A continuación voy a mostrar un ejemplo simple de cómo utilizar Drools y cómo permite parametrizar las reglas del negocio de forma externa a la aplicación que las utiliza. Antes de comenzar, recomiendo haber instalado JBoss Tools en Eclipse, puesto que nos ofrecerá herramientas que facilitan el desarrollo de apicaciones que usan Drools.

El caso de uso que vamos a implementar en el ejemplo será el de una tienda online. En esta tienda hay dos tipos de clientes, aquellos que se han registrado previamente y los que no. Para todos los clientes que gasten más de 1.000 euros se les hace un descuento del 5%. A los que se han registrado, se les ofrece un descuento adicional del 5% en todas su compras, independientemente del importe. Vamos a hacer una aplicación que calcule el descuento que corresponde a cada usuario.

En primer lugar creamos un proyecto Drools en Eclipse, lo que es posible gracias a las utilidades instaladas en JBoss Tools:

El nuevo proyecto se va a llamar CalculadorDescuento:

El asistente nos permite crear ejemplos de uso de Drools:

Es necesario especificar el runtime de Drools, es decir, la carpeta donde se encuentran las librerías de Drools:


Ahora, creamos una clase Cliente que refleje los datos del cliente, su nombre, si está registrado, el gasto que ha realizado y el descuento que se le aplica:
package com.roldan.drools;

public class Cliente {
String nombre;
boolean registrado;
float gasto;
float descuento;

// Getters y setters...
}

En la clase CalculadorDescuento se crea el siguiente método, que lee las reglas que se han definido en el fichero Descuentos.drl:
private static KnowledgeBase readKnowledgeBase()
throws Exception {
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(
ResourceFactory.newClassPathResource("Descuentos.drl"),
ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}

El método main de esta clase crea una sesión de Drools y crea también varios clientes que introduce en esta sesión a los que se aplican las reglas que se definen en el fichero Descuentos.drl:
public static void main(String[] args) {
try {
// Cargar las reglas
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

// Cliente no registrado que gasta más de 1.000 euros
Cliente cliente1 = new Cliente();
cliente1.setNombre("Cliente 1");
cliente1.setRegistrado(false);
cliente1.setGasto(1200);
ksession.insert(cliente1);

// Cliente registrado que gasta menos de 1.000 euros
Cliente cliente2 = new Cliente();
cliente2.setNombre("Cliente 2");
cliente2.setRegistrado(true);
cliente2.setGasto(800);
ksession.insert(cliente2);

// Cliente registrado que gasta más de 1.000 euros
Cliente cliente3 = new Cliente();
cliente3.setNombre("Cliente 3");
cliente3.setRegistrado(true);
cliente3.setGasto(1600);
ksession.insert(cliente3);

ksession.fireAllRules();
logger.close();

System.out.println("El cliente 1 tiene un descuento de "
+ cliente1.getDescuento() + " euros.");
System.out.println("El cliente 2 tiene un descuento de "
+ cliente2.getDescuento() + " euros.");
System.out.println("El cliente 3 tiene un descuento de "
+ cliente3.getDescuento() + " euros.");

} catch (Throwable t) {
t.printStackTrace();
}
}

Ahora vamos a ver cómo se definen las reglas anteriormente descritas en el fichero Descuentos.drl:
package com.roldan.drools

rule "Gastos superior a 1.000 euros"
when
cliente : Cliente( gasto > 1000 )
then
System.out.println("El cliente "
+ cliente.getNombre() + " ha gastado más de 1.000 euros.");
cliente.setDescuento(
cliente.getDescuento() + cliente.getGasto()*5/100);
end

rule "Cliente registrado"
when
cliente : Cliente( registrado == true )
then
System.out.println("El cliente "
+ cliente.getNombre() + " está registrado.");
cliente.setDescuento(
cliente.getDescuento() + cliente.getGasto()*5/100);
end

Al ejecutar la clase principal, obtenemos la siguiente salida que nos informa sobre lo que ha pasado:
El cliente Cliente 3 está registrado.
El cliente Cliente 3 ha gastado más de 1.000 euros.
El cliente Cliente 2 está registrado.
El cliente Cliente 1 ha gastado más de 1.000 euros.

El cliente 1 tiene un descuento de 60.0 euros.
El cliente 2 tiene un descuento de 40.0 euros.
El cliente 3 tiene un descuento de 160.0 euros.

En esta traza vemos qué condiciones ha cumplido cada uno de los clientes y el resultado final de aplicarles todos los descuentos a los que tienen derecho según su condición.

Aunque este es un ejemplo muy sencillo, se puede apreciar que ahora, si se quisiese variar el descuento aplicado para cada uno de estos casos o aplicar un nuevo descuento según otra condición distinta, no haría falta manipular el código de la aplicación. Bastaría con modificar las reglas definidas de forma separada en el fichero Descuentos.drl.

Esto no es más que una sencilla aplicación de lo que ofrece Drools, aunque este BRMS es mucho más potente que esto y ofrece mucha más funcionalidad que ya iremos viendo.

Referencias:
Does Your Project Need a Rule Engine
Primeros pasos con Drools
Drools en Wikipedia
Bussiness rule en Wikipedia
Implement business logic with the Drools rules engine
Open Source BRE/BRMS JSR-94 compliant
Getting Started With the Java Rule Engine API (JSR 94): Toward Rule-Based Applications

lunes, 29 de marzo de 2010

Los Métodos Ágiles

Entre finales de la década pasada y principios de la actual surgieron una serie de métodos de desarrollo de software contrapuestos a la visión clásica de la ingeniería del software. Estos métodos se postulan en contra del control de los proyectos de software basado en la predictibilidad de las tareas a desarrollar, y proponen una orientación de estos que facilite su adaptabilidad de forma continua a las condiciones cambiantes de dichos proyectos.

En su artículo “The New Metodology, Martin Fowler hace una exposición de estos métodos, llamados métodos ágiles. Voy a hacer un pequeño repaso a este artículo a través de la traducción al castellano realizada por Alejandro Sierra.

Según Martin Fowler, la forma más habitual de trabajar en un proyecto de desarrollo de software es a través de la prueba y error con un mínimo plan inicial, y completando el diseño con decisiones a corto plazo. Esto funciona bien para proyectos pequeños pero no para proyectos más grandes, que necesitan de largas fases de prueba a posteriores que desbordan toda planificación.

Para remediar esta situación se dispone de metodologías de desarrollo, que imponen un proceso disciplinado que trata de convertir el desarrollo de software en algo predecible y eficiente, similar a otras ingerierías. Sin embargo, estos métodos introducen mucha burocracia en los proyectos, retrasando su avance.

En opocición a estas metodologías, surgen los métodos ágiles, que se sitúan en medio de las metodologías tradicionales y la falta de metodología. Están más orientados a producir código que documentación debido a sus dos características principales:
  • Son adaptables en lugar de predictivos. En vez de planear todos los aspectos del proyecto tratan de adaptarse en los cambios que se producen durante la ejecución del proyecto.
  • Son orientados a la gente en lugar de al proceso. Tratan de apoyar el equipo de desarrollo en su trabajo, en vez de forzar al equipo a trabajar de una forma estricta.

Las ingenierías tradicionales enfatizan en que hay que planear antes de construir. En ellas, el plan define de forma exacta cómo se llevará a cabo la construcción. La realización del plan es una actividad mucho más exigente que la ejecución, y requiere de personal especializado. La ejecución es algo más mecánico que puede ser llevado a cabo por personal de nivel bajo.

Sin embargo, en desarrollo de software, no es fácil diseñar un plan que convierta el desarrollo en una actividad de construcción predecible. Un diseño en UML no suele ser todo lo completo que sería necesario y suele variar con respecto a la implementación. En estos casos el costo del esfuerzo del plan es mucho mas cercano a la implementación que en proyectos de ingenierías tradicionales.

Por tanto, se observa que en el desarrollo de software la construcción es barata ya que casi todo el esfuerzo está en el diseño, que es un proceso creativo. Como los procesos creativos no se planean fácilmente, la previsibilidad es una meta difícil de alcanzar.

Además, en los proyectos de desarrollo de software, los cambios en los requisitos son habituales, debido a las condiciones cambiantes en las que se dearrollan los proyectos. Además, ya que el desarrollo de software es una actividad de diseño, esta es difícil de planear y cuantificar, por lo que la estimación de los requisitos es difícil, y con ello la posibilidad de obtener un plan predecible.

Es por ello que en desarrollo de software es necesario un proceso que controle esta imprevisibilidad mediante adaptabilidad. Esto se logra mediante el desarrollo iterativo, que permite obtener retralimentación sobre la situación del proyecto en intervalos frecuentes.

De esta forma, se hace evidente tanto la situación actual del proyecto como posibles fallos de entendimiento del mismo o bugs.

Sin embargo, este tipo de desarrollo necesita un tipo de cliente distinto al tradicional. El cliente debe estar involucrado con el equipo, revisando el resultado de las iteraciones y proporcionando información sobre el proyecto de forma constante. Además, el contrato de precio fijo deja de tener sentido.

Ya que no se puede fijar tiempo, precio y alcance, lo normal es fijar precio y tiempo y permitir que el alcance varie de manera controlada. Gracias a las iteraciones, el cliente tiene control a escala fina sobre la evolución del proyecto, pudiendo fijar la dirección del proyecto de acuerdo a sus prioridades. Esta visibilidad sobre el proyecto que otorgan las iteraciones permite controlar también el riesgo.

En un proceso de este tipo se requiere de un equipo eficaz de desarrolladores. Las personas involucradas en un proyecto ya no son recursos reemplazables, debido a que el trabajo que se realiza es algo creativo y en este tipo de trabajo hay grandes diferencias entre las personas. Además, si las personas trabajan en equipo, se establecen sinergias que hacen que el equipo sea más que la suma de sus miembros.

También hay que reconocer a los profesionales de software como profesionales competentes capaces de dirigir su trabajo técnico. La labor de la gerencia será favorecer este trabajo con la menor interferencia posible.

Las metodologías ágiles tambien rechazan las métricas como herramienta de control del rendimiento de las personas, puesto que no se han encontrado métricas fiables en este sentido. Por ello favorecen la gestión delegatoria, donde los que finalmente hacen el trabajo deciden sobre cómo hacerlo.

Pero para llevar esto a cabo no se puede confiar sólo en la parte técnica. Es necesario que los expertos de negocio estén accesibles y pueden resolver las dudas que surjan a medida que el proyecto avanza. Se favorece la comunicación interdisciplinar.

Además, el propio proceso de desarrollo debe evaluarse y someterse a modificaciones que permitan mejorarlo.

Varias metodologías comparten estas bases. Entre ellas, podemos citar:
  • XP.
  • Scrum.
  • Crystal.
  • FDD (Feature Driven Development).
  • DSDM (Dynamic System Development Method).
  • Lean.
  • Etc.

A pesar de todo, es importante resaltar que el uso de estas metodologías no es apropiado para todos los casos. Hay que considerar la naturaleza de cada proyecto y evaluar si encajaría con estos principios o no.

Factores que sugieren un proceso adaptable:
  • Requisitos inciertos.
  • Desarrolladores responsables.
  • Clientes implicados.

Factores que sugieren un proceso predictivo:
  • Equipos grandes.
  • Contratos con alcance y precio fijo.

Sin embargo, no todo son parabienes para estos métodos y su aparición ha suscitado amplios debates entre sus defensores y los defensores de las metodologías tradicionales. Como ejemplo, este artículo de Miguel Ángel Abián y el debate que suscitó dentro de la comunidad JavaHispano.

Referencias:
The New Metodology por Martin Fowler
Traducción al castellano del artículo The New Metodology por Martin Fowler realizada por Alejandro Sierra
Artículo de Miguel Ángel Abián sobre las Metodologías Agiles
Discusión en JavaHispano en torno al artículo de Miguel Ángel Abián
La Falacia de la Ingeniería del Software por Samuel Zarza
Waterfall vs. Agile: Can they be Friends?