Eventos de Dominio

Publicada en Publicada en Código, Diseño de Software, Visual Studio

Compartelo con tus amigos!

Mantener un diseño orientado a dominio es bastante dificil cuando no se tiene la sufiente práctica y/o experiencia, como sea de que este enfoque se centra en objetos que representan la realidad colaborando unos con otros es dificil no mantener un dependencia entre los mismos, cuando esta dependencia se da a nivel de objetos del dominio esto no implica un error de concepto sin embargo cuando las dependencias comienzan a incrementarse es necesario buscar alternativas de implementación al momento de mantener baja la dependencia de clases; los evento de dominio son una herramienta muy importante y, hasta me atreveria a decir, imprescindible justamente para este fin,

Antes de entrar a detalle veamos una porción de codigo:


public class Almacen
{
  public void RegistrarIngreso(Movimiento ingreso)
  {
    Movimientos.Add(ingreso);
    foreach(var item in ingreso.Lineas)
    {
      item.Producto.IncrementaSaldo(item.Cantidad);
    }
  }
}

Esta porción de codigo es bastante sencilla y se entienden sin mayor explicación ahora supongamos existe las siguientes reglas de negocio: “por cada ingreso se debe enviar un correo a control interno”, “ademas que se debe enviar una notificación a contabilidad para que actualicen su kardex”; al implementar estas reglas de negocio nos quedaria de la siguiente forma:


public class Almacen
{
  public void RegistrarIngreso(Ingreso ingreso, IEmailHelper emailHelper, IKardexService kardexService)
  {
    Movimientos.Add(ingreso);
    foreach(var item in ingreso.Lineas)
    {
      item.Producto.IncrementaSaldo(item.Cantidad);
    }
    emailHelper.EnviarIngreso(ingreso);
    kardexService.Notificar(ingreso);
  }
}

Como pueden ver a persar de que no se ha incluido otras responsabilidades en la clase (como realizar la conversión del ingreso a un formato de mail), si se ha incrementando las dependencias del clas Almacen, y ahora debemos de pasarle como parametro los servicios necesarios, podriamos decir que en este punto esto esta bien; pero ¿que pasaría si necesitamos implementar mas reglas de negocio? las dependencias solo seguirian creciendo lo que resultaria en algo cada vez más dificil de manejar.

En estos casos los eventos de dominio cobran una importancia enorme ya que evita que las dependencias sigan creciendo al proporcionarnos una forma de ejecutar código en un entorno de ejecución diferente de (en este caso) la clase almacen.

Para ello lo primero es que debemos definir un evento:


public class IngresoRegistrado
{
  public IngresoRegistrado(Ingreso ingreso)
  {
    Ingreso = ingreso;
  }

  public Ingreso Ingreso { get; }
}

Ahora la clase almacen lo único que tiene que hacer es emitir el evento:


public class Almacen
{
  public void RegistrarIngreso(Movimiento ingreso)
  {
    Movimientos.Add(ingreso);
    foreach(var item in ingreso.Lineas)
    {
      item.Producto.IncrementaSaldo(item.Cantidad);
    }
    GestorEventos.Emitir(new IngresoRegistrado(ingreso));
  }
}

Ahora definiremos los manejadores que reaccionen antes este evento.


public interface IManejador<T>
{
  void Ejecutar(T evento);
}

public class EnviarMailIngresoRegistrado: IManejador<IngresoRegistrado>
{
  private IEmailHelper _emailHelper;

  public EnviarMailIngresoRegistrado(IEmailHelper emailHelper)
  {
    _emailHelper = emailHelper;
  }

  public void Ejecutar(IngresoRegistrado evento)
  {
    _emailHelper.EnviarIngreso(ingreso)
  }
}

public class NotificarContabilidadIngresoRegistrado: IManejador<IngresoRegistrado>
{
  private IKardexService _kardexService;

  public EnviarMailIngresoRegistrado(IKardexService kardexService)
  {
    _kardexService= kardexService;
  }

  public void Ejecutar(IngresoRegistrado evento)
  {
    _kardexService.Notificar(ingreso)
  }
}

Lo unico que nos falta es definir el gestor de eventos; en esta ocasión muestro una implementación usando Castle Windsor para resolver las dependencias de los manejadores; sin embargo, esta no es la única forma de implementar este gestor:


public static class GestorEventos
{
  public static IKernel Kernel { get; }

  public static void Inicializar(IKernel kernel)
  {
    Kernel = kernel;
  }

  public static void Emitir<T>(T evento)
  {
    var manejadores = Kernel.ResolveAll<IManejador<T>>();
    foreach(var manejador in manejadores) {
      manejador.Ejecutar(evento);
    }
  }
}

Ahora ya tenemos todo lo que necesitamos para implementar los eventos de dominio, esta es una tecnica que no solo permite reducir la dependencia sino que tambien nos puede permitir procesar los trabajos en paralelo, esto si implementamos los manejadores como Task.

Compartelo con tus amigos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *