Hace ya mucho tiempo que tenía ganas de escribir sobre este tema, por desgracia, entre unas cosas y otras no he tenido demasiadas oportunidades, pero bueno, por aquí empezamos el tema, el cual podremos continuar si veo la oportunidad. Los eventos, dentro de los modelos de dominio no es algo nuevo, de hecho ya hace mucho tiempo que hay definiciones y ejemplos de implementaciones como por ejemplo los de Udi Dahan, aquí y aquí, sin embargo, con la corriente de CQRS y sus elementos colaterales, se han puesto todavía más en boca, aunque en realidad en ocasiones hablamos sobre conceptos y terminologías diferentes. De lo que nosotros hablaremos es únicamente de eventos en dominio y de cuales son las ventajas que estos nos proporcionan. Lógicamente, antes de nada, vamos a poner algunas características que nos permitan entender que es un evento:
- Siempre definen algo que ha ocurrido, el pasado.
- Puesto que definen algo que ha ocurrido, estos no pueden modificarse, es decir, son inmutables aunque contienen información del hecho, parámetros por ejemplo.
Los eventos nos permiten comunicar agregados, por ejemplo que una “transacción” ha ocurrido, sin necesidad de romper los límites de consistencia entre el cluster de entidades que forma un agregado. El tratamiento de eventos simplifica mucho ciertos procesos puesto que nos permiten una orientación más naturar que el trabajo “procedimental” que haríamos con la ausencia de estos. Tal y como comentábamos en el primer párrafo hay muchos ejemplos de implementaciones, tanto de las guías de estas corrientes como en muchos fragmentos de código existentes que seguramente podrá revisar, nosotros, en este post haremos algo muy sencillo con caracter ilustrativo más que con fines de ejemplo de implementación.
El siguiente fragmento podría considerarse como un evento, que notifica que un usuario ha sido bloqueado, fíjese en el caracter de pasado y en la inmutabilidad del mismo.
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TheUserIsLocked |
1 |
{ |
1 |
<span style="color: #0000ff">string</span> _email; |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Email |
1 |
{ |
1 |
get |
1 |
{ |
1 |
<span style="color: #0000ff">return</span> _email; |
1 |
} |
1 |
} |
1 |
|
1 |
<span style="color: #0000ff">int</span> _userId; |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> UserId |
1 |
{ |
1 |
get |
1 |
{ |
1 |
<span style="color: #0000ff">return</span> _userId; |
1 |
} |
1 |
} |
1 |
|
1 |
<span style="color: #0000ff">public</span> TheUserIsLocked(<span style="color: #0000ff">int</span> userId, <span style="color: #0000ff">string</span> email) |
1 |
{ |
1 |
<span style="color: #0000ff">this</span>._userId = userId; |
1 |
<span style="color: #0000ff">this</span>._email = email; |
1 |
} |
1 |
} |
Ahora, dentro del proceso con un agregado, se puede notificar este hecho a cualquier parte interesada por ejemplo utilizando alguna implementación de un publicador.
1 |
var userIsLockedEvent = <span style="color: #0000ff">new</span> TheUserIsLocked(1, <span style="color: #006080">"unai@plainconcepts.com"</span>); |
1 |
|
1 |
_eventPublisher.Publish(userIsLockedEvent); |
Ahora, cualquiera de las partes interesadas ( consumidores ) podrían escribir un manejador para este suceso que por suspuesto, puede ( suele ) necesitar el trabajo con otro agregado,
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TheUserIsLockedEventConsumer |
1 |
:IConsumer<TheUserIsLocked> |
1 |
{ |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Handle(TheUserIsLocked @<span style="color: #0000ff">event</span>) |
1 |
{ |
1 |
<span style="color: #008000">//TODO</span> |
1 |
} |
Aunque esto, ha sido un ejemplo sencillo, repito que con fines únicamente ilustrativos, puede dar buena idea de los beneficios que los eventos de dominio pueden aportarnos a la hora de resolver un problema.
Saludos
Unai
Siempre me han gustado los DomainEvents al estilo Udi Dahan, incluso con (o sobre todo por) su fachada estática.
Me parecen una buena forma de evitar dependencias entre aggregate roots y servicios, y además acaba generando código bastante limpio.
Es una lástima que sea tan poco conocidos y discutidos, sobre todo comparados con otras ideas DDD como repositorios 😛
Juanma.
Estoy de acuerdo contigo juanma, me parece una pena que no se discutan más, sobre todo por aprender y ver mejores técnicas de implementación. Aunque cada vez lo veo más como por ejemplo en la referencia que he puesto en el blog de NopCommerce..
Unai
Bueno, un post pequeñito pequeñito, más que nada y para ser sincero, para cambiar un poco de tercio,