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.