Patrones de diseño en DDD: Entidades

viernes, 7 de febrero de 2014


En el diseño orientado al dominio es habitual utilizar una serie de patrones, voy a escribir una seria de post relacionados con estos patrones. En esta primera entrega vamos a ver las entidades.

Las entidades es un tipo de clase dedicada a representar un modelo de dominio con una serie de características:
  • Tienen una identidad más allá de sus atributos, normalmente esta identidad es asignada con un identificador o Primary Key en base datos.
  • Dos objeto usuario con el mismo nombre no significa que sea el mismo usuario
  • Es mutable, puede cambiar. Se pueden cambiar valores de un usuario como su nombre, dirección.
  • como ejemplos de entidades pueden ser usuario, producto, pedido, factura.
Comportamiento en las Entidades
  • Las entidades en DDD deben tener comportamiento, el concepto es diferente a las entidades que generan por defecto las plantillas T4 donde en las propiedades tienen los descriptores de acceso get y set públicos para poder ser leído y modificado desde el exterior. 
  • Las entidades tienen métodos para modificar su estado, no se cambia a través de sus propiedades. Estos métodos son acorde al lenguaje de dominio, como por ejemplo ChangePassword.
  • Las entidades son las encargadas de las consistencia de sus datos, no el cliente consumidor de la entidad. Por ejemplo si dos propiedades deben mantener una sincronización debe ser la entidad la responsable de hacer que se cumpla.
  • Si una entidad no tiene comportamiento es un anti-patrón llamado modelo anémico http://bit.ly/1avBX2f
En ocasiones se interpreta entidades POCO como objeto con solo propiedades porque es lo que genera las plantillas T4 por defecto, pero POCO viene de POJO, que es Plain Old Java Object y en .Net es Plain Old CLR Objects, es decir, sin dependencia de ningún framework externo. Al principio las entidades de Entity Framework no eran POCO porque heredaban de Entity que era una clase de EF. Que las entidades sean POCO no quiere decir que no tengan comportamiento.

Este es un ejemplo de una entidad anémica donde se puede aprecia la falta de comportamiento.
public class AnemicUser
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string ShoppingCountry { get; set; }
    }
Ahora veamos un ejemplo de entidad más propia de un diseño orientado al dominio y que no es anémica.
public class User
    {
        public User(string userName, string password, string email, string shopingCountry)
        {           
            UserName = userName;
            Pwd = password;
            Email = email;
            ShoppingCountry = shopingCountry;
        }

        internal User()
        {           
        }

        public int UserId { get; private set; }

        public string UserName { get; private set; }

        public string Pwd { get; private set; }

        public string Email { get; private set; }

        public string ShoppingCountry { get; private set; }

        public void ChangePassword(string newPassword
        {
            //podría ser necesario validar historial de cambios
            //por el usuario porque no se puede repetir
            Pwd = newPassword;
        }

        public void ChangeUserName(string newUserName)
        {
            UserName = newUserName;

           //este cambio podría implicar cambiar más entidades o realizar alguna notificación 
           //de algún tipo. Al final se debe lanzar un evento de dominio
           //porque esto es importante y algo debe pasar
        }

        public void ChangeShoppingCountry(string shoppingCountry)
        {
            ShoppingCountry = shoppingCountry;

            //Lanzar evento de dominio indicando el cambio
            //porque esto es importante y algo debe pasar
         }
    }
En este ejemplo vemos que existen métodos para modificar el estado de la entidad, dando así un comportamiento a la entidad que puede ser validado con test unitarios. También se puede observar que las propiedades tienen el descriptor de acceso set privado, esto es debido a que si utilizamos un ORM como Entity Framework debe existir aunque sea privado para poder rellenar las propiedades al leer de base de datos, así como un constructor sin parámetros, este tampoco es necesario que sea público.

En los próximos post veremos más patrones de diseño en DDD.

Libros Relacionados

Domain-Driven Design: Tackling Complexity in the Heart of Software

Implementing Domain-Driven Design

No hay comentarios:

Publicar un comentario