miércoles, 11 de diciembre de 2013

martes, 22 de octubre de 2013

Tell, Don't Ask

Si tienes clases con un conjunto de getters y setters planos para todos sus atributos lo estás haciendo mal.

jueves, 26 de septiembre de 2013

Una útil combinación de CROSS APPLY y FOR XML

De los numerosos problemas que pueden darse a la hora de presentar información de una base de datos a un cliente, quizás uno de los más recurrentes sea que quieran ver determinados datos agrupados -concatenados- en una única columna. Por ejemplo, supongamos que hay un concesionario de coches de lujo que sirve vehículos exclusivos a una serie de clientes. El caso es que el concesionario mantiene una tabla de clientes y una tabla de vehículos asociados a los clientes. Como son clientes con mucha pasta, cada uno puede tener un número indeterminado de coches (ya que pensamos un ejemplo no vamos a andarnos con miseras de supermercados ecológicos donde se compran calabacines y tomatitos cherry...). 

lunes, 12 de agosto de 2013

No borres nada de la base de datos... pero ni se te ocurra usar borrados lógicos.

Me encanta la cara que me ponen los programadores y analistas cuando les suelto esta frase. Se quedan quietos pensando en la frase e intentando comprender como puede no ser una paradoja imposible de cumplir lo que les acabo de soltar en tan pocas palabras.

La primera parte de la frase se entiende fácil y rápidamente. Unos de los requisitos del sistema es no perder la información original que se ha borrado o modificado para poder consultarla en un momento futuro. En el caso de las modificaciones o borrados permitidos, la solución mas sencilla que viene a la cabeza es una solución completamente válida, aceptable y con unos problemas inherentes asumibles: Tablas de auditoría. Con ellas podemos recuperar fácilmente los valores de una entidad en una fecha concreta.

jueves, 4 de julio de 2013

Arquitecturas para Domain-Driven Design - Parte VII

Diseño final

Bueno final final... queda muchísimo por hacer y definir para tener una arquitectura de verdad, pero sí que puedo crear un esqueleto muy básico que puede dar una idea a grandes rasgos.

Una vez definida la colaboración entre las distintas capas del sistema, voy a dejar fragmentos de código de ejemplo para que el lector se haga una idea del resultado final.

En estos ejemplos se utiliza un contenedor de inyección de dependencias para resolver los servicios de aplicación que se van a utilizar, esto nos ayuda a tener un ServiceLocator que además se encarga de montar toda la cascada de dependencias entre clases. Cosa muy buena para tener una arquitectura débilmente acoplada. 

lunes, 24 de junio de 2013

Conceptos básicos de CSS

Hace poco he hecho un breve resumen introductorio de CSS para una persona que está comenzando a aprender lo que es el HTML, el resultado es este artículo, que está dirigido a personas que no tienen una idea clara de lo que es el CSS. 

jueves, 13 de junio de 2013

Un proyecto en NetBeans de principio a fin (VI). Clases de entidad y beans de sesión

En esta parte del tutorial se presentan las tecnologías Enterprise JavaBeans y Java Persistence. Vamos a conocer a dos asistentes que nos facilitarán bastante la vida a la hora de desarrollar para Java EE:
  • El Asistente para Clases de Entidad de Base de Datos, crea una clase de entidad de la API de persistencia de Java completa para cada tabla seleccionada de la base de datos; con anotaciones de consultas con nombre, campos representando columnas y relaciones representado claves externas.
  • El Asistente de Beans de Sesión para Clases de Entidad crea una fachada EJB de sesión para cada clase de entidad, con métodos básicos de acceso. 

viernes, 31 de mayo de 2013

La fiesta de los bocazas. (Blowhard Jamboree)

Buscando en Internet los antipatrones para refrescarlos en mi mente y redactar el post anterior he caído en un antipatrón (título de este post) que aunque no es muy común en los ambientes que me muevo actualmente es muy fácil caer en ellos y además refleja la paradoja de que yo mismo soy un bocazas.

Este antipatrón consiste en tomas decisiones y asumir cosas simplemente con la información salida de lo que ha publicado un señor cualquiera en un medio de comunicación. Por ejemplo, este blog.

En mi caso en concreto me ha pasado con "el lado oscuro" de los patrones de diseño.

Los antipatrones más comunes a los que me enfrento de forma diaria.

Como descanso a DDD y como forma de desahogo voy a poner una lista de los antipatrones de diseño que día tras día veo que se repiten una y otra vez sin que nadie que cuente con la capacidad decisoria para poder atajar el problema mueva un dedo al respecto.

lunes, 20 de mayo de 2013

Arquitecturas para Domain-Driven Design - Parte VI

Capa de Persistencia.
Esta capa sirve como puente entre la lógica de negocio (servicios y entidades) y el proveedor de datos. Históricamente es una capa que se usa para encapsular las especificaciones del proveedor de datos. Aunque esto sigue siendo, en cierta manera, así, gracias a nuevas tecnologías como los ORM (los cuales ya realizan una abstracción del proveedor de datos) su propósito puede llegar a ser el de abstraerse de los detalles de implementación del ORM y proporcionar mecanismos para la satisfacción de consultas utilizando el ORM escogido.

viernes, 26 de abril de 2013

Un uso para la función RAND() en SQL

Gran parte de mi trabajo transcurre con los ojos pegados al Server Management Studio de SQL. En ocasiones tengo que buscar soluciones a ciertos problemas, y a veces encuentro maneras (unas veces más elegantes que otras) de salvar el escollo. El caso es que cuando un año después me surge otro problema semejante me mata tener que buscar un fragmento de código entre cientos de procedimientos almacenados con más o menos líneas de Transact-SQL... Y como no todo el monte es NetBean o Arquitecturas DDD, voy a poner aquí una "breve" reseña sobre un uso de la función RAND() que he necesitado en un par de ocasiones y que, a buen seguro, volveré a necesitar.

lunes, 8 de abril de 2013

Un proyecto en NetBeans de principio a fin (V). Conexión con la base de datos

No es por desanimar, pero si la entrada anterior os pareció larga y cansina agarraros con ésta. Si estáis siguiendo este tutorial con tanto entusiasmo que no podéis parar de leer y enredar con NetBeans hasta llegar al final de cada post, más vale que vayáis a mear y a picar algo a la cocina... En esta ocasión vamos a centrarnos en la comunicación entre la base de datos y la aplicación. Añadiremos unos cuantos datos a la base de datos y examinaremos algunas de las características que proporciona el editor de SQL del IDE. Configuraremos el origen de datos y un pool de conexiones en el servidor GlassFish, y crearemos una página JSP para probar la conexión mediante alguna consulta simple a la base de datos.

martes, 2 de abril de 2013

Arquitecturas para Domain-Driven Design - Parte V

Overview de la Arquitectura 

Como ya comenté en un post anterior, DDD es el candidato perfecto para grandes y complejos sistemas que conllevan un buen montón de procesos; los cuales colaboran entre si siguiendo unas reglas para mantener la coherencia y consistencia del propio sistema al que pertenece.

Empecemos a dividir en capas las distintas partes para hacernos una idea.

martes, 12 de marzo de 2013

Referencias teoría DDD

Voy a dejar las referencias sobre DDD que suelo consultar y de las cuales he fusilado más contenido del que me gustaría por culpa de mi pereza.

Espero que esto sirva para que no me denuncien por plagio y que los autores reciban el reconocimiento que se merecen.




Guía de Arquitectura N- Capas Orientada al Dominio con .NET 4.0

Para lectores mas avanzados dejo una serie de documentos PDF que discute distintas formas de modelar  agregados junto con sus ventajas y desventajas:

Effective Aggregate Design

viernes, 8 de marzo de 2013

Buddy classes en .NET

Las Buddy classes son una técnica para añadir metadatos a clases que son generadas automáticamente por herramientas, ya sean estas herramientas del Visual Studio o herramientas externas; también son útiles para la segregación de responsabilidades.

La introducción de clases parciales, que permiten ampliar los miembros de una clase creada por una herramienta sin que volver a crear la clase se machaque nuestra personalización, es una gran idea, pero tiene un problema a la hora de modificar un miembro ya declarado. Si en vez de añadir nuevos miembros a una clase queremos añadir un atributo a un miembro ya existente nos encontramos con un problema, puesto que el atributo añadido a un miembro de la clase se borraría al regenerar la clase de nuevo.

Para solventar este problema tenemos las buddy clases. Estas son clases que amplían los metadados de otra clase, pudiendo definir el miembro de la clase a modificar dentro de la buddy y añadiéndole el atributo que corresponda.

Imaginemos que tenemos la siguiente clase generada por una plantilla T4 en VS:

Partial Public Class Clasificacion

    Private _ID as String

    Private Descripcion as String



    Public Sub New(ByVal id As String)

    End Function



    Public Property ID() As String

    End Property



    Public Property Descripcion() As String

    End Property

End Class

Queremos añadir un atributo de validación a la propiedad Descripcion, por lo que debemos crear una Buddy Class con esa propiedad sin implementación y asociar esa Buddy Class a la extensión de la clase parcial utilizando el atributo MetadataType.

Public Class ClasificacionMetadata

<StringLength(50, ErrorMessage:="El campo descripcion de una Clasificacion no puede superar los 50 caracteres.")> _
    Public Property Descripcion() As String
        Get
        End Get
        Set
        End Set
    End Property
End Class

<MetadataType(GetType(ClasificacionMetadata))> _
Partial Public Class Clasificacion
    Public Function tieneDescricion As Boolean
        Return not String.IsNullOrEmpty(Me.Descripcion)
    End Function
End Class

Con esta definición, algunas tecnologías .NET recuperan el atributo MetadataType utilizando reflexión y obtendrán el atributo StringLengthAttribute de la Buddy Class cuando procesen la propiedad Descripcion de la clase generada.

Desgraciadamente, si nuestro código necesita procesar estos metadatos a través de la reflexión de tipos debemos programar explícitamente la posibilidad de que la clase parcial tenga asociado un MetadataType, recuperarlo y al procesar la clase parcial buscar en la clase Buddy su correspondencia para mirar si tiene algún atributo que extienda algún miembro. Esto es muy oscuro, aburrido y provoca que todo aquel que toque el codigo fuente de nuestro programa tenga conocimiento de la necesidad de este comportamiento. No me gusta.

Por suerte, .NET provee una manera de ampliar las descripciones de las clases administradas para que sean procesadas de forma transparente por el framework de reflexión de tipos.

domingo, 3 de marzo de 2013

Un proyecto en NetBeans de principio a fin (IV). Páginas y servlet del controlador

Me temo que esta cuarta entrega va a ser enorme... Tenemos mucho que hacer aquí. Nuestro objetivo es empezar a organizar el front-end de la aplicación, preparando las vistas de las páginas y a situándolas en la estructura apropiada del proyecto (usaremos HTML y CSS para esto). La idea es tener una maqueta, ahora con código fuente, de los esquemas que obtuvimos en la fase de diseño. Crearemos un pie y una cabecera que aplicaremos a todas las vistas, y configuraremos el servlet del controlador para las peticiones entrantes. Empecemos sin más preámbulos. 

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)

jueves, 31 de enero de 2013

Arquitecturas para Domain-Driven Design

Este es el primer post de una serie que tratará, de forma introductoria, sobre Domain-Driven Design (DDD) -que en castellano sería algo como Diseño Guiado por el Dominio- y el diseño de una arquitectura subyacente que cumpla con los requisitos del dominio, manteniendo los principios SOLID en el diseño de las clases y un bajo acoplamiento de los módulos. La arquitectura esta orientada a grandes aplicaciones de gestión con complejas reglas de comportamiento. 

El objetivo de una arquitectura basada en Domain-Driven Design es conseguir un modelo orientado a objetos que refleje el conocimiento de un dominio dado y que sea completamente independiente de cualquier concepto de comunicación; ya sea con elementos de infraestructura como de interfaz gráfica, etc. Buscamos construir un modelo a través del cual podamos resolver problemas expresados como la colaboración de un conjunto de objetos.

Mi objetivo no es que se aprenda DDD en esta serie, si no aclarar como es traducido esto en la vida real. Yo me he encontrado muchas veces leyendo teoría muy bonita, con unos párrafos muy bien construidos, y he pensando: Buena exposición pero ¿Cómo llego, partiendo de esto, a tener una arquitectura y un código fuente decente?

Empezemos con el...

Lenguaje Ubicuo.

Cualquier modelo que construyamos debe representar de forma explícita los principales conceptos del dominio de conocimiento con el que trabaja nuestro sistema. Debemos fomentar la construcción de un lenguaje de uso común, tanto entre expertos del dominio y desarrolladores, como entre los propios desarrolladores, que contenga los principales conceptos del dominio de conocimiento, que además sea el lenguaje usado para expresar cómo se resuelven los distintos problemas y objetivos del sistema.

Como decía, un párrafo muy bonito, pero ¿A dónde se quiere llegar?. La principal consecuencia de utilizar un lenguaje común para el dominio es que se facilita la comprensión del dominio por parte de los desarrolladores y la comunicación entre todos los implicados en el desarrollo. Otra consecuencia menos obvia, pero igual de importante, es que los desarrolladores se esforzarán por diseñar un modelo cuyo nivel de abstracción sea lo suficientemente alto como para que un experto del dominio pueda leer el código fuente de una actividad del modelo y sea capaz de entenderlo.

Pongo un ejemplo de esto para que se entienda mejor:

Una de las actividades de nuestro sistema bancario es realizar transferencias entre cuentas corrientes. La información que tenemos del experto del dominio es la siguiente:
Para realizar una transferencia de cierta cantidad entre cuentas, la cantidad tendrá que ser mayor que 0. Se comprobará que la cuenta de origen no esté bloqueada. Si no está bloqueada se comprobará que en el balance tiene saldo positivo suficiente o que se permite saldo negativo hasta ese punto. En caso de cumplirse las condiciones anteriores, se sustraerá la cantidad de la cuenta origen y se agregará a la cuenta destino.
Al más alto nivel de abstracción de nuestro modelo de dominio deberíamos tener el siguiente código:

function TransferirSaldo(ctaOrigen, ctaDestino, cantidad)
{
    //no se puede transferir 0 o cantidad negativa
    If (cantidad < 1) {error, incumplimiento de reglas de dominio}

    //Si la ctaOrigen está bloqueada o no tiene saldo suficiente 
    //(ni crédito para llegar a los números rojos con los que
    //resultaría en caso de la transacción monetaria) la entidad ctaOrigen
    //lanzaria una exception de reglas de negocio que dejariamos fluir hacia
    //arriba.

    //Resta la cantidad del balance de ctaOrigen
    ctaOrigen.sustraer(cantidad)

    //Agregar la cantidad al balance de la ctaDestino
    ctaDestino.agregar(cantidad)

}

Si tienes un diagrama de flujo que representa esto te darás cuenta que es clavadito clavadito.

Millares de ventajas.

Esto lo lee el profano en programación que te ha contado como funciona el proceso de transferencias ente cuentas y lo entiende perfectamente (y puede corregirlo en caso de no ser correcto o completo). Nosotros, como desarrolladores, también podemos ver con mucha facilidad si hemos modelado la secuencia de actividades correctamente, si nos hemos saltado algún paso, si el orden no es correcto... etc. Un programador recién llegado puede montar un nuevo proceso leyendo la definición del proceso y utilizando los métodos de las entidades que, por sentido común, corresponden de una forma inequívoca a los pasos de la definición. Las responsabilidades están en su sitio y no es necesario repetir código. Si el estado binario de una cuenta ("bloqueado" o "no bloqueado") pasa a ser un enumerado (digamos "bloqueado", "bloqueado para sacar dinero" y "bloqueado para ingresar dinero") ¿Se imaginan ustedes si tenemos en 30 sitios desperdigados por el código una línea como ésta, en la que hay que cambiar un booleano por un enumerado? if (ctaCorriente.bloqueado = true)...  Se montó el belén...

En resumen, utilizar un leguaje ubicuo no sólo facilita la comunicación y la comprensión del dominio; además nos hace conscientes -a los desarrolladores- del nivel de abstracción y diseño de entidades y negocio al que debemos llegar, y nos da unos objetivos concretos que cumplir cuando empezemos a diseñar el sistema desde los cimientos.

viernes, 11 de enero de 2013

Mis primeros pasos con NetBeans

Como quiera que haya encontrado un poco de tiempo en el fondo de algún cajón, llevo unos días trasteando con el IDE de NetBeans -concretamente la versión 7.2.1-. Debido a mis orígenes informáticos entre cables y switches, mi experiencia seria en Desarrollo está bastante encasillada en el Framework de .NET y los lenguajes VB y ASP. Me gustaría cambiar esto. Java y el Framework de NetBeans me parecen una opción interesante, entre otras cosas por su gratuidad. Desde mi inexperiencia, NetBeans me parece muy potente y ampliamente extendido (lo que debería ayudarme en el aprendizaje). Dado que lo peor siempre han sido los comienzos (a menudo he "comenzado" varias veces con lo mismo), me ha parecido buena idea recoger aquí, con mis propias palabras, eso primeros pasos a través de los enlaces a varios de los tutoriales con los que he empezado.

La instalación de la plataforma no supone mayor problema. En la zona de descargas de NetBeans existe varios paquetes de descarga. Yo personalmente opté por la distribución de Java EE. Puesto que mi interés por ahora es Java, no veo necesario enfangarme con más cosas (aunque es bueno saber que C/C++ o PHP también tienen cabida en el IDE).

Adicionalmente, para realizar ejercicios de acceso a Bases de Datos, he instalado un servidor de MySQL. Yo he optado por el instalador MSI de la versión 5.5.29. Posteriormente encontré un tutorial para conectar con MySQL desde el IDE de NetBeans.

Muchas veces me enfrento a la frustrante sensación de que si tuviera que empezar a desarrollar una aplicación desde cero, sobre una nueva tecnología, no sabría ni por dónde empezar. Todos estos últimos años he estado trabajado en el ámbito de una aplicación monstruosa que ya está sólidamente (que no eficientemente) implantada, pero que aún crece de forma un tanto descontrolada, entre modificaciones y nuevos desarrollos. Por tanto, en general, yo he implementado módulos que debían encajar en una arquitectura preestablecida, alguna nueva funcionalidad y muchos parches. En este entorno me he encontrado muchas cosas hechas y he reutilizado bastante código. Sin embargo un buen número de cosas de la base me son completamente ajenas, como, por ejemplo, muchos de los entresijos de la configuración y el acceso a datos.

Así pues, mi objetivo era conocer los pasos elementales para crear una pequeña aplicación web que accediera a bases de datos. Para eso seguí este tutorial, donde se desarrolla un ejemplo completo y funcional de un modelo elemental de Cliente-Servidor. Se usa la API JDBC (Java DataBase Connectivity) para la comunicación directa de la aplicación con la base de datos. En esencia, se crean dos páginas JSP que usan código JSTL (JSTL es un conjunto de librerías de etiquetas estándar que encapsulan funcionalidades para escribir páginas JSP) para implementar la lógica que consulta directamente a la base de datos y recupera la información. Se le añaden unas sencillas reglas de estilo con las herramientas de construcción y testeo de CSS que proporciona el IDE. Y se prepara y configura la comunicación entre aplicación y base de datos mediante un pool de conexiones (todo perfectamente detallado, lo que para mi ha sido un alivio).

El servidor GlassFish (que viene con la instalación del IDE) contiene librerías DBCP (DateBase Connection Pooling) que proporcionan funcionalidad para pooling de conexiones de forma transparente para el desarrollador. Sólo hay que configurar el data source y las referencias correspondientes (lo que también viene bien descrito).

Finalmente se explica ampliamente como añadir la lógica dinámica mediante la implementación del código JSTL en las páginas de la aplicación. El resultado es una pequeñísima aplicación web, corriendo con todo, en sólo un rato.

Cosa distinta es cómo me enfrentaré a todo lo anterior el día que tenga que hacer algo parecido sin tan inestimable sustento, pero bueno, empezar he empezado (otra vez).

miércoles, 2 de enero de 2013

R-Studio. Un nombre para recordar en recuperación de datos.

Aunque la informática forense no es mi área de actuación, me parece un campo muy interesante (hace algunos años asistí a un curso en Madrid sobre este tema y me quede con ganas de más...). Dentro de la categoría de "amigo informático que trabaja gratis", me he enfrentado a varios pequeños desaguisados en los que he tenido que recuperar información de ciertos dispositivos de almacenamiento que habían sufrido las inclemencias de un mal uso o de inevitables accidentes eléctricos. Pero hasta hace un par de meses la cosa no era mucho más compleja que ejecutar un Scandisk o un Chkdsk, recuperar sectores de arranque con una restauración del sistema, o conectar un disco primario que no arrancaba como esclavo para poder acceder al contenido.

Entonces, sin saber muy bien cómo, llegó a mis manos un disco duro del hermano de una amiga de mi querida esposa (malditas cadenas de favores...). El disco estaba bastante frito. Sonaba con ese ronroneo particular de quiero pero no puedo. Los escaneos de superficie se atascaban y fue imposible acceder al contenido porque el explorador de archivos era incapaz de abrir el directorio, y cuando ocasionalmente lograba mostrarme algo (tras minutos y minutos de eterna espera) eran particiones vacías o un par de archivos corruptos...

Indagando sobre software de recuperación de datos, encontré varias herramientas gratuitas, pero finalmente un compañero me recomendó R-Studio. Esta no es gratuita pero por alguna casualidad una copia cayó en mis manos y pude probarla (total, tampoco me iba a lucrar con este trabajo). En mi defensa debo decir que si en algún momento obtengo beneficio económico de mi actividad como informático forense, R-Studio será mi primera inversión.

Tengo que decir que sólo he trabajado con esta suite muy superficialmente, pero me ha parecido un paquete muy potente. Enredando un poco con las opciones de recuperación y configuración conseguí salvar más de 200 GB de datos útiles y la estructura completa de nombres y directorios (posteriormente he averiguado que eso suponía la totalidad de los datos perdidos, más una buena cantidad de datos borrados conscientemente con anterioridad al incidente...).

R-Studio puede antojarse algo complicado a priori (por la cantidad de posibilidades). Además hay aplicaciones gratuitas que pueden proporcionar una recuperación satisfactoria en muchos casos. Sin embargo me parece una interesante herramienta de peritaje con posibilidades muy atractivas, como recuperación de datos a través de red, reconstrucción de RAID, editor hexadecimal con interpretación de patrones de datos... Y dada mi mala cabeza no está de más dejar su nombre apuntado en algún sitio.