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