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.



Vista

Es la interfaz del usuario del sistema. Como ejemplo se puede poner un formulario de escritorio, una página web, etc. La vista es algo muy dependiente de la tecnología que se está utilizando por lo que en estos post no voy a profundizar en ellas, ya que quiero mantenerme lo más independiente posible de cualquier tecnología en concreto.

Baste decir que a través de diferentes técnicas y patrones como Controladores, Presentadores, Comandos, Modelos de vista y Data Transfer Objects, se deben montar vistas que sean totalmente desacopladas del resto del sistema. A la vista le debe llegar lo que se quiere mostrar al usuario, no se debe tener conocimiento de entidades, lógica de negocio, seguridad, ni nada por el estilo en este nivel. Esto permitiría disponer de diferentes vistas (web o app de escritorio) para la misma aplicación sin tener que reescribir nada excepto la nueva vista.

Si se hace un esfuerzo organizativo, según qué tecnologías, es incluso posible independizar la vista pura y dura de su controlador/presentador.

Un ejemplo de esto lo podemos encontrar en vistas para .NET Framework y el patrón Modelo-Vista-Presentador. Si un presentador utiliza una interfaz para interactuar con un formulario windows, no sería difícil hacer que una página ASP.NET implementase esa misma interfaz con diferente código (lógicamente), con lo que podríamos reutilizar el mismo presentador para la aplicación web.

Aplicación

La capa de aplicación es, como su nombre indica, la que realiza las labores que debe hacer nuestra aplicación como elemento de valor añadido al proceso. Es una de las razones de por qué desarrollamos una aplicación en vez de seguir utilizando un archivador, lápiz, papel, calculadora y gente con mucho cuidado participando en un proceso.

Un ejemplo aclara el párrafo anterior.
Existe un proceso en nuestras oficinas para mantener y consultar los proveedores de donuts para las pausas del café  Todo el mundo puede consultar la lista de proveedores para poder llamarlos y hacer pedidos pero sólo un trabajador es responsable de añadir un proveedor o modificar los datos de uno ya existente en nuestra lista. También se debe dejar registro de la fecha y la hora de modificación de los datos de un proveedor.
Todos podríamos imaginarnos cómo se haría esto si tuviéramos que hacerlo con papel, lápiz y una carpeta de cartón, pero para mejorar la productividad en horas de pausa para el café se decide desarrollar una aplicación.

Queremos desarrollar una aplicación que se encargue de gestionar una lista de proveedores (dominio) para su mantenimiento y consulta (acceso a la persistencia de datos), que controle que sólo el usuario especial tiene permisos para modificar los datos de los proveedores (seguridad), que mantenga un log con las modificaciones (trazabilidad) y que no permita modificar un proveedor en caso de no poder hacer el apunte sobre quién lo modificó (transaccionalidad).

Pues esto es la capa de aplicación. Accede a los repositorios de persistencia (capa de acceso a datos), utiliza la capa de dominio para aplicar las reglas que debe seguir el proceso, utiliza la seguirdad, realiza las trazas y los logs, y controla las transacciones. Todas las funcionalidades (exceptuando la capa de dominio) que me hacen la vida más fácil a la hora de trabajar con el proceso (la razón del desarrollo de la aplicación es hacer mas fácil trabajar con el proceso pertinente) están coordinadas por la capa de aplicación.

Dominio

Son las reglas del proceso. En este nivel se encuentran modelados las Entidades (no olvidéis que los Agregados Raíces también son entidades), los Objetos de valor (VO) y los servicios de dominio.

Las Entidades y los VO's mantienen y aplican las reglas y restricciones que les conciernen a ellos mismos. Las entidades que son agregados raíces mantienen además las reglas y restricciones que conciernen a sus agregados para su propia coherencia. Los servicios mantienen las reglas y restricciones ajenas al comportamiento de las entidades.

Esto, básicamente, es aplicar un buen diseño orientado a objetos.

Otro ejemplo para entendernos mejor:
Supongamos un sistema de noticias y comentarios insertados por usuarios del sistema.
La entidad Noticia podría tener una regla que limite el número de caracteres que puede tener el título de la noticia a 200 caracteres y que no permita palabras ofensivas. Esto supondría que al realizar la operación Noticia.SetTitulo(tituloNoticia) el código interno de esta función realizaría la comprobación del número de caracteres y si tiene alguna palabrota; con más de 200 caracteres el título se cortaría, y se sustituirían las palabrotas por asteriscos.
El Agregado Raiz Noticia puede tener asociados una serie de comentarios insertados por otros usuarios, con un máximo de 10 comentarios. Si el número de comentarios ya existentes fuese 10, al realizar la operación Noticia.AddComentario(nuevoComentario) se reemplazaría el comentario más antiguo.
El servicio de dominio NoticiasService puede obligar a que un usuario tenga que esperar 5 minutos para ingresar una nueva noticia. En la operación NoticiasService.PostNoticia(listaNoticias, nuevaNoticia, Usuario) se comprobaría la hora del último post de la Entidad usuario, Usuario.GetFechaUltimoPost(), y en caso de haber pasado más de 5 minutos, se añadiría la noticia a la lista y se actualizaría la fecha del último post del usuario, Usuario.SetFechaUltimoPost(Time.Now).
En el próximo post hablaré sobre la capa de acceso a datos y explicaré cómo se coordinan estas capas entre si.

No hay comentarios:

Publicar un comentario