lunes, 25 de febrero de 2013

Arquitecturas para Domain-Driven Design - Parte IV

Ya queda poco para explicar los conceptos mas básicos de DDD y ponernos con la arquitectura. Quiero recordar a los lectores que el tema de DDD es un campo enorme y estos posts son simplemente orientativos para facilitar un punto de entrada sencilla a cualquiera que quiera documentarse y aprender a fondo DDD. Al finalizar esta lista de conceptos básicos agregare reseñas a la bibliografía y documentación de la cual he plagiado todo esto.

miércoles, 20 de febrero de 2013

Un proyecto en NetBeans de principio a fin (III). Diseño del modelo de datos

En esta emocionante tercera parte, nos centraremos en el modelado de datos; o dicho de otro modo, en el proceso de crear un modelo conceptual de nuestro sistema de almacenamiento mediante la identificación y definición de las entidades que requiere nuestro sistema, y de las relaciones entre esas entidades. El modelo de datos debe contener todos los parámetros del diseño lógico y físico necesarios para generar un script usando el Lenguaje de Definición de Datos (o DDL por sus siglas en inglés) que posteriormente usaremos para crear una base de datos.

domingo, 17 de febrero de 2013

Un proyecto en NetBeans de principio a fin (II). Configuración del entorno de desarrollo

No voy a extenderme demasiado en esta segunda parte. Voy a obviar algunos aspectos triviales como "encienda usted su ordenador" y "haga doble click en el icono de NetBeans"... (Vaya, al final no los he obviado). En una entrada anterior -Mis primeros pasos con NetBeans- Ya hablé algo sobre la plataforma y puse varios links de utilidad para descargar el software. Aunque este blog no es el Santo Grial de la Informática, presupondré cierto nivel de alfabetización digital a los eventuales lectores. Por ahora los tres o cuatro usuarios habituales están muy por encima de esos requerimientos mínimos, así que sigamos...

jueves, 14 de febrero de 2013

Un proyecto en NetBeans de principio a fin (I). Diseño de la aplicación

¡Vaya! Bonito pareado el del título... En fin. En este perseverante afán que me está llevando a convertirme en un ""experto"" en el desarrollo de aplicaciones java al abrigo de este Framework, me encontré con un completísimo tutorial que abarca la totalidad de los pasos del desarrollo de una pequeña, pero completamente funcional, aplicación web de e-commerce. Es un tutorial arduo que comienza con el escenario ficticio de una tienda de alimentación que pretende extender su negocio de productos orgánicos a Internet. Profundiza, basándose en requerimientos y reuniones figuradas con el cliente, en todo el proceso de desarrollo de una arquitectura orientada a servicios de cliente.

Mi intención no es otra que afianzar mis conocimientos a través de la repetición y el esfuerzo de sintetizar y contar todo el proceso con mis palabras (el original está en inglés). Adicionalmente esto me queda mucho más a mano para referencias puntuales en el futuro.

El tutorial original puede encontrarse AQUÍ.

Sin más preámbulos me meteré en situación e iré al asunto.

viernes, 8 de febrero de 2013

Arquitecturas para Domain-Driven Design - Parte III

Los dos conceptos que voy a explicar hoy son cruciales para el diseño de una arquitectura decente que cumpla el dominio.

En DDD los dos objetos de negocio principales son Entidades y Objetos de Valor.

Entidades 

La característica definitoria de una Entidad es que tiene una identidad, es única dentro del sistema, y ​​ninguna otra entidad, no importa cuán similar sea, es la misma entidad a menos que tenga la misma identidad.

La identidad puede ser representada de muchas maneras en una entidad. Podría ser un identificador numérico, podría ser un GUID o podría ser una clave natural formada por uno o más valores que, según el dominio, van a ser únicos en todo el ciclo de vida del sistema persistente.

Objetos de valor (VO) 

La característica definitoria de un objetos de valor es que no tiene identidad. La intención de un objeto de valor es representar algo por sus atributos únicos. Dos VO's pueden tener atributos idénticos, en cuyo caso son el mismo VO. Un VO debe ser inmutable y sus características no deben cambiar durante su ciclo de vida.

Aquí están las definiciones, ahora veamos como se traduce esto en la vida real del desarrollo de software.

La vida real 

Pongamos un supuesto, el sistema de información para una fabrica de coches.

Entidad 

Cada coche que se fabrica es único y tiene que seguir siendo único y él mismo siempre. No importa la similitud que tenga con otros coches o que sus características cambien. Su identidad viene definida en este caso por el número de bastidor. Un coche puede ser igual a otro en todo: marca, color, llantas, peso, número de puertas, etc. Pero cada uno es un coche diferente.

Si a un coche se le cambia el color o se le pone un motor más potente, sus características cambian, pero sigue siendo el mismo coche. Esto es una Entidad.

Objeto de valor 

En el sistema de fabricación de coches tenemos una serie de colores con los que pintamos los coches, Estos colores están representados en el sistema por un nombre y sus valores RGB. ("Celeste" [0, 170, 228])

En nuestro sistema nunca tendremos dos "Celeste" que representen dos colores distintos. Si dos VO's son distintos tienen que tener características distintas. Si dos colores tienen el mismo RGB son el mismo color.

Los VO's son inmutables debido a que no puedo cambiar el código RGB de "Celeste" y que los nuevos números sigan representando al color de nombre "Celeste". Sería simplemente otro color. Esto es un VO.

Ahora bien. Es nuestra responsabilidad como arquitectos de software y desarrolladores el modelar las reglas de dominio que deben cumplir las entidades y los VO's.

Podemos poner como analogía las reglas de la física del macroverso (remarco macroverso por si alguno se me pone vacilón con los quarks y la antimateria). Según estas leyes, una entidad no puede estar en dos lugares a la vez al mismo tiempo, ni dos entidades pueden ocupar el mismo espacio al mismo tiempo.

Para ilustrar esto de modelar las reglas del universo que estamos creando, tengo que explicar la teoría de la creación por sustracción.

Como las fotos de tu boda

La mejor analogía que se me ocurre es poner el ejemplo de las diapositivas. Las máquinas de diapositivas crean imágenes en una pantalla. Pero no crean esa imagen añadiendo colores a la pantalla, la crean sustrayendo colores a la luz blanca.

En el supuesto de que tengamos ya modeladas la clase "Coche" y la clase "Color", nos ponemos delante nuestro editor de código favorito y ¿Qué podemos hacer con estas entidades? Pues como pequeños demiurgos del sistema que somos, lo podemos hacer todo. Podemos hacer que un coche esté en dos almacenes diferentes a la vez. Podemos hacer que el mismo coche este pintado con dos colores a la vez en la misma franja temporal. Podemos hacer que dos coches diferentes estén en la misma plaza de aparcamiento en el mismo instante. Si esto pasase en la física del macroverso de vez en cuando, de una forma cuasi aleatoria, diríamos que el sistema de nuestro universo tiene un Bug. ;)

Cuando estamos sentados delante de un editor de código en blanco y vamos a desarrollar algo, no creamos un sistema de la nada, creamos un sistema sustrayendo de un todo, tenemos que poner reglas y limitaciones a las infinitas posibilidades que existen delante de una pantalla vacía. Estas reglas y limitaciones son parte del dominio de nuestro sistema.

Vamos con la chicha 

El lector espabilado ya se habrá dado cuenta que esto está muy relacionado con "el pifostio de las referencias y los punteros". Al nivel de abstracción más bajo de nuestro sistema, tenemos objetos que apuntan a otros objetos, y con ellos podemos hacer lo que nos de la gana. Si tenemos un objeto "PlazadeAparcamiento" que apunta al coche que está ahora mismo ocupándola, podemos asignar un coche a esa plaza. Si asignamos otro coche a la misma plaza sin modelar ninguna regla, sería como si un coche "desapareciera" de la plaza y otro apareciera en su lugar de repente.

Hay que modelar un sistema que eleve el nivel de abstracción. A un nivel más alto no deberíamos tener que saber nada sobre punteros, instancias ni referencias a objetos. Deben ser los "cimientos" de la aplicación los que se encarguen de todo esto para que nosotros sólo nos tengamos que preocupar de "aparcar un coche en una plaza de aparcamiento". Si ésta se encuentra libre pues ya está hecho. Pero si está ocupada, dado que dos entidades no pueden ocupar el mismo espacio físico, el "aparca-coches" nos dirá que no puedo hacerlo, que la plaza está ocupada, o se encargará de mover el coche y ponerlo en otro lado para dejar la plaza libre.

Generación espontánea y teleportación 

Los coches no aparecen de la nada (PUF!!!). No se puede hacer un <new Coche()> por ahí, en cualquier lugar del código donde se necesite un coche nuevo. Los coches se fabrican, por lo que debemos tener una fábrica de coches. Esta fábrica podrá reconfigurarse para que fabrique coches con las características que le digamos. Si le cargamos un color a la fábrica, ésta creará coches pintados con ese color.

Otro ejemplo. Los clientes no se materializan en un negocio como teleportados por la Enterprise. Los clientes se dan de alta. Hay que proveer un modelo que se encargue de "fabricar" o "dar de alta" las entidades de nuestro sistema. Por supuesto, al nivel de abstracción más bajo, existen instrucciones para crear nuevas instancias de clases, pero estas instrucciones no salen de allí. No deberíamos ver un solo <new Entidad( )> fuera de su contexto (una fábrica, un proceso de alta, etc).

El gemelo malvado

Tenemos que limitar nuestro universo para que no existan dopplegängers. Que existan gemelos malvados en un universo nunca da buenos resultados. En un sistema se podría dar la situación en la que tenemos un coche asociado a un conductor, lo que se traduce en que una clase "Conductor" tenga un puntero a una instancia de un coche en memoria. Y ese coche está en un taller, por lo que la clase "Taller" también debe tener un puntero a esa misma instancia del coche en memoria. Si permitiésemos que lo que hay en el taller sea un dopplegänger (otra instancia de ese mismo coche en otra posición de memoria), cuando el taller pintase el coche de otro color, el coche del "Conductor" seguiría manteniendo su color antiguo, puesto que el color habría sido cambiado al gemelo malvado. Esto produciría una paradoja espacio-temporal que haría implosionar el pequeño universo que estamos modelando entre gritos de clientes, gestores con ceño fruncido, una horda de programadores corriendo por los pasillos como pollos descabezados y esa GPU tan molona que te acabas de comprar (a mi no me engañas, se que eres una graphic whore) echando humo.

¿Son iguales, son el mismo o es el gemelo malvado? 

En ciertas ocasiones es inevitable que, con la comunicación entre dos sistemas con una integración muy débil, se nos de el caso de encontrarnos con algún dopplegänger. Para estos caso (y para otros menesteres) debemos proporcionar mecanismos que nos permitan comparar entidades y poderlas identificar.

Hay 3 maneras de comparar entidades.

Se puede necesitar saber si dos entidades son iguales (que no la misma). Esto significa comparar si las características de un coche son las mismas que la de otro coche. Comparar el color, la cilindrada, la marca, el modelo, etc. Y si todo coincide es que esos dos coches, a pesar de ser distintos coches, son iguales.

También debemos proporcionar un mecanismo pasa descubrir cuándo dos coches son el mismo. En el caso del ejemplo con coches, nos bastaría con comparar los números de bastidor.

Y nos queda la última. La de determinar si dos referencias apuntan a la misma entidad. (dos punteros referencian la misma posición en memoria). Con ésta podemos desenmascarar a los gemelos malvados.

La combinación de estos tres mecanismos nos da la base para poder trabajar con las entidades y modelar sus leyes universales.

Cada entidad debe implementar internamente estos mecanismos de comparación, por lo que cuando trabajemos con las entidades ya no tenemos que saber nada de punteros, referencias o que características identifican a una entidad.

lunes, 4 de febrero de 2013

Arquitecturas para Domain-Driven Design - Parte II

En esta entrada sobre Arquitecturas para DDD voy a hablar sobre...

Bounded Contexts

En un sistema grande y muy complejo es muy fácil que dos personas tengan interpretaciones distintas de un mismo concepto, o que repliquen dicho concepto en algún objeto por no saber que éste ya ha sido implementado en otra clase. La solución a esto pasa por definir contextos dentro de los cuales los modelos tiene una validez.

Los modelos grandes los vamos a separar en varios modelos de menor tamaño, estableciendo que, dado un elemento determinado de nuestro sistema, éste sólo tiene sentido dentro del contexto donde está definido. Nos centraremos en mantener la coherencia dentro de estos contextos y trataremos aparte las relaciones entre contextos.

Es fundamental definir, simultáneamente a los contextos, un mapa de los mismos, donde se establecen claramente los distintos contextos existentes en el sistema y las relaciones entre ellos. De esta forma obtenemos las ventajas de coherencia y cohesión que nos ofrecen los contextos y preservamos la visión global del sistema, estableciendo claramente las relaciones entre aquellos.

Esto, en definitiva, es fácil de ver si tenemos, por ejemplo, un sistema en el que podemos gestionar clientes y otro sistema que gestiona cuentas bancarias. Es más que obvio que debemos tener dos contextos diferentes: El modulo de gestión de clientes, con todas las operaciones aplicables a los clientes y el modulo bancario con toda la gestión de cuentas.

Una vez definidos esos contextos, con sus fronteras estrictamente establecidas, es fácil para cualquier desarrollador implementar un proceso del sistema sin caer en ambigüedades o reimplementar conceptos ya modelados. Si, por ejemplo, el proceso implica acciones contra cuentas corrientes y clientes, es trivial referirse al modulo bancario y al de clientes, y mirar las funcionalidades que expone cada uno. Si todo está correctamente modelado (incluidas las relaciones entre módulos), debería ser la cosa más sencilla del mundo coordinar esas funcionalidades para modelar cualquier proceso.

viernes, 1 de febrero de 2013

Anexo a la "Primera Entrada"

Parece que la presentación de la Primera entrada ha quedado un tanto obsoleta. Se me ocurrió, después de hablar con algunos amigos, que esto podría tener mucho más brío si fuera un blog abierto a colaboradores de la profesión. No esperaba tan buena y rápida acogida entre un par de camaradas, pero mira por donde... Sigo sin querer nada pretencioso, pero ya no tiene caso hablar de "mis inquietudes, experiencias y modestos logros profesionales". Y desde luego ahora promete ser mucho más interesante. Ya, ya se que no he descubierto la América de los blogs colaborativos, pero espero que éste sea el nuestro... Así que hala, a darle caña que para finales de año tenemos que ser referencia mundial... (:P)