0

My question is about Udi's solution to domain events, particularly the class DomainEvents (see code below)

An excerpt from Udi's code. It lives domain model as a static class.

public static class DomainEvents
{ 
   [ThreadStatic] //so that each thread has its own callbacks
   private static List<Delegate> actions;

   public static IContainer Container { get; set; } //as before

   //Registers a callback for the given domain event
   public static void Register<T>(Action<T> callback) where T : IDomainEvent
   {
      if (actions == null)
         actions = new List<Delegate>();

      actions.Add(callback);
  }

  //Clears callbacks passed to Register on the current thread
  public static void ClearCallbacks ()
  { 
      actions = null;
  }

  //Raises the given domain event
  public static void Raise<T>(T args) where T : IDomainEvent
  {
     if (Container != null)
        foreach(var handler in Container.ResolveAll<Handles<T>>())
           handler.Handle(args);

     if (actions != null)
         foreach (var action in actions)
             if (action is Action<T>)
                 ((Action<T>)action)(args);
  }
} 

From the code above, the static member IContainer creates an ioc-container-dependency in the domain model. Though I am not really sure if Udi's IContainer is an interface or an actual IoC container.

I don't see anything like this in his sample:

public interface IContainer
{
    IEnumerable<T> ResolveAll<T>();
}

My 1st question is: What is this IContainer in the DomainEvents class? If it is truly an IoC container then doesn't it break the rule of "not having an infrastructure in the domain"? (Please correct me if I'm wrong)

Isn't the idea of DDD is about separating the infrastructure from the domain?

My 2nd question is: Does DomainEvents itself breaks the rule "ubiquitous language of DDD"? Because it's implementation does not pertain to any domain.

Yorro
  • 11,445
  • 4
  • 37
  • 47
  • Related: http://stackoverflow.com/questions/13015486/using-ninject-with-udi-dahans-domain-events/13026232#13026232 – Steven Dec 27 '13 at 13:45

1 Answers1

3

I agree, the domain must not know about infrastructure and, to a certain degree, Udi's solution provides that abstraction. Personally, I prefer the solution hinted at by Mark Seemann in the article's comments: inject the event aggregator via an interface. This way, events hold there place as first class domain model citizens, but via the loosest of coupling.

David Osborne
  • 6,436
  • 1
  • 21
  • 35
  • But isn't the `DomainEvents` class considered an infrastructure? Especially that it has IContainer. Please see my updated question. – Yorro Dec 27 '13 at 11:29
  • I would argue that the DomainEvents class conceals its dependencies on infrastructure-type components. I don't need to know that it's using Castle Windsor to raise a domain event. The coupling could be looser if the model classes only depended on an interface for raising events. However, I think both approaches are valid. – David Osborne Dec 27 '13 at 18:07