Should Domain Entity Be Managed By IoC?

One question that has always been puzzling people when starting doing Domain Driven Design is how a domain entity can talk to repositories or services controlled by IoC. Particularly if those entities are (and usually they are) loaded from ORM like nHibernate. There are a lot of controversy in DDD of whether a domain entity should depend on repositories or services at first place. First, a logic that requires dependency to repositories or services indicates that it is cross-aggregate. And the basic principle is, a logic that crosses aggregate boundary should NOT live in domain entity. It should live in services, and no domain entity should be aware of it. However, in reality, most except the simplest domain logics require external services. For example, a Sales entity is responsible of calculating the payable price. And in order to do so, it needs to figure out the discount, which then involves a business-rule-engine. Hence dependency from Sales domain to BRE service. So I think the question should not be about whether an entity should depend on services. It is the fact that we have to accept that more often than not, domain entity will absolutely need services. Without it, you will most likely end up with Anemic Domain Model, which at extreme level can be very very bad based on my experience. Now back to the question: how the domain should get hold of the services, particularly if the creation is not within our control (e.g., from ORM)? Apparently this has been a regular topic in Alt.Net and DomainDrivenDesign discussions that is always brought up every 1 week or two. Some suggestions given to me by quite few people, like Alasdair Gilmour, Larry Chu, et al, have given me a new insight that I have never expected before. IoC is not only about Services. It’s also about domain entity. Out of various approaches that Larry pointed out, there are generally 2 viable solutions to solve the dependency of domain-entity without tying it up with infrastructure detail. The first approach is to leverage interceptor. If you use nHibernate, Billy McCafferty shows how we can inject DI container from nHibernate loader interceptor. My response to it, I don’t like the idea of injecting DI container to the entity. But the similar approach can be used to inject the dependencies (instead of the container) into the entity. Unity container has an elegant solution for this kind of scenario using BuildUp method. You simply have to register your *domain entity as one of IoC services*. Hence the title of this post. There is currently no similar functionality in Spring.Net or Castle Windsor. But it’s pretty straightforward to do it ourself. What we need is a custom Dependency attribute, and decorate entity’s properties with it to mark as injectable dependency:

public class Sale
{
private ICustomerRepository customerRepository;

[Dependency]
public ICustomerRepository CustomerRepository
{
set {this.customerRepository = value;}
}
}

And write the NHibernate interceptor to introspect entity’s properties that are marked with the attribute, and resolve it from IoC container:

public class DepdencyInterceptor : IInterceptor
{
public bool OnLoad(object entity, object id,

object[] state, string[] propertyNames, IType[] types)
{

// Use “setter injection” to give objects’s dependency
// for each property marked with Dependency attribute

foreach (PropertyInfo prop in entity.GetType().GetProperties())
{
if (prop.CanWrite &&
prop.GetCustomAttributes(typeof (DependencyAttribute), true) != null)
{
object dependency = IoC.Resolve(prop.DeclaringType);

prop.SetValue(entity, dependency, null);
}
}

// Even though we gave the object it’s dependency, return
// the fact that we didn’t modify the persistent properties
return false;
}

// … All other methods of IInterceptor
}

Last, register the interceptor into NHibernate session manager:

NHibernateSessionManager.Instance.RegisterInterceptor(new NHibernateDepdendencyInterceptor());

The main drawback of using nHibernate interceptor, is that it’s limited to inject dependency to entity that is publicly accessible by its aggregate root. But I personally am not too concerned about that. I will think twice if I need to push dependency to inaccessible entity of an aggregate at first place. Because, IMO, the dependency of entity in the aggregate is the dependency of the aggregate root as a whole, at least from TDD point of view. It will be difficult to test-drive the aggregate root otherwise, and if that is the case, IoC-ORM integration will be the last thing I am worried about. The second approach, particularly if you don’t use nHibernate, is by using bytecode instrumentation. For instance, using post-compilation AOP, like PostSharp, to mangle the entity’s constructor to resolve its depdendencies (decorated fields/properties) from the IoC. This is by far the most powerful solution that can solve all possible cases. It is also ORM agnostic. This approach applies with most kinds of ORM, Sql-mapper, or even without ORM. The drawback of this approach, or rather the drawback of code-mangling AOP in general, is that it involves too much dark magic that makes things less clear to follow, and can be very difficult to debug. For this reason, dynamic proxy AOP is generally favorable over code-mangling. Dynamic proxy, unfortunately for our purpose, is not an appropriate option. Many IoC containers, mostly in Java, support the second approach out of the box. But I am not aware of any similar functionality in Windsor, or most .Net IoC framework in general. So we will need to get our hand a little bit dirty with PostSharp.

Advertisements

11 thoughts on “Should Domain Entity Be Managed By IoC?

  1. This is a topic which has sparked heated discussions in my project. I too came to the same conclusion as you that DI’ing an entity is not bad. However I don’t agree with your view that injecting the container into entity is bad, since if you have a large number of entities and each entity needs multiple repositories/services injected into them, then the interceptor code would become too large with lots of conditionals. I have around 35 entities. Is there any elegant way to handle this ?

    I wrote a post on some general rules for entities at http://stochastyk.blogspot.com/2008/05/entities-in-ddd.html . Have a look.

  2. @Kaushik
    Sorry, I just realized that it seems WordPress somehow believed that your comment was a spam….. 5 months ago! ^.^’
    Anyway, Postsharp has a very elegant solution to this. Check it out here http://forum.springframework.net/showthread.php?t=3473.
    Without PostSharp or AOP trick, in the snippet above, there is no if-else conditions. It communicates with IoC container, and let the container to manage the dependency for you. Both Spring.Net and Unity supports configuration over an existing instance (as instantiated by nHibernate).
    Or alternatively, you can intercept nHibernate’s Instantiate method, and ask your IoC container for the instance.

  3. Why not do something like this:


    public class DomainObject where TRepository : class
    {
    public long ID { get; private set; }

    protected TRepository Repository
    {
    get
    {
    return RepositoryFactory.GetRepository();
    }
    }
    }


    public class Blog : DomainObject
    {
    public string Name { get; private set; }
    public DateTime Date { get; set; }
    public IList Entries { get; private set; }
    public string Owner { get; set; }

    public int EntryCount
    {
    get
    {
    return this.Repository.EntryCount(this.ID);
    }
    }
    }

    The RepositoryFactory.GetRepository() static method still calls the DI Container (in my case Spring) to get the respository (in my case it is a Singleton per Web Application)

    Here is an example of a Repository Implementation:

    public class BlogRepository : Repository
    {
    public int EntryCount(long blogId)
    {
    var q = from blog in db.Entities()
    from entry in blog.Entries
    where blog.ID == blogId
    select entry;

    return this.db.Execute(() =>
    {
    return q.Count();
    });
    }
    ….
    }

    Yes I’m testint Linq for NHibernarte within Spring.NET.

  4. Yes, service locator can be used to resolve dependencies in difficult-to-reach places. In fact, I am also using service-locator within the interceptor code above. It’s just a matter of pull vs push from entity’s perspective.
    And I personally prefer not to have domain entities to have direct or indirect reference to IoC container. Leaving domain-entities as POCO as possible allows me to unit-test them without touching IoC container (or its API).

  5. But wouldn’t the interceptor intercept any object pulled by NHibernate and look for the attribute on every property?

    If so IMHO it’s unecessary performance penalty.

    By the way Spring.NET as a configure method so you could do something like this instead you for each statement:

    if (IoC.ContainsObject, object.Type.FullName)
    {
    IoC.ConfigureObject(entity, object.Type.FullName);
    }

    This would resolve the injection to your domain objects according to an XML Config simular to Castle if a resolution exist.

    Furthermore it would “elegantly” solve this situation:

    “if you have a large number of entities and each entity needs multiple repositories/services injected into them”

    Nuno Lopes
    PS: Sorry to bother you but I just started experimenting NHibernate e Spring.NET (have tried Castle already).

  6. I agree. Custom attribute here is only to get around the limitation of Windsor container (despite being subject to performance penalty, caching makes the impact insignificant). But Unity and Spring.Net provide a much cleaner way of injecting services to a live instance which is really useful in entity injection situations like this.
    In the absence of such feature in many IoC products, one thing that I found useful is to override nHibernate instantiation strategy (in lieau of intercepting OnLoad) and pull the entities out from IoC… given that most of our entities are managed by IoC container.

  7. “In the absence of such feature in many IoC products, one thing that I found useful is to override nHibernate instantiation strategy”

    That is nice sice facilities injected by an IoC would work on domain objects.

    I’m really a noob around NHibernate and IoC. Can you provide a simple and usable example of such overload?

    Thanks.

  8. Just another comment around this subject. I do think that domain objects can call whatever they need to do they job properly and as fast as possibile. That includes calling Repositories and Services.

    I for one use one Repository per persistant Domain Objects. For example:

    class Customers : Repository

    Semantically we can argue that Customers (as a generic concept encompassing all companies) is part of the Domain. Something like the Yellow Pages for Customers 🙂

    Other people argue that is not a domain object becouse it is there just to encapsulate persistance (or an ORM system).

    I argue that it does not matter at all ones interpretation on this subject. Let me explain.

    “First rule of OO is that if you want an object to do something you as the object to do it for you.”

    “The second rule is that in a collaboration the most sepecic should direct”

    Using this best practices let’s say you have an instance of Blog with thousands of entries if not millions. So if you want to list thet last n entries you do:

    IList[Entry] entries = aBlog.GetLastEntries(5);

    While implementing GetLastEntries one faces a decision.

    Internally either it iterates over its list of entries (aBlog.Entries[i]) (slow since it would load all entries first from a database an then get lookup for the last five,

    Or

    Ask something else to do it for him. Let’s say the, Blogs: Repository[Blog] (faster since it directely access the ObjectBroker or DAO that in turn used Database Services). No matter how many layers you put in to it, access to services of a lower layer be needed.

    Example:

    IList GetLastEntries(int lastn)
    {
    return this.Blogs.GetLastEntries(lastn)
    }

    Blogs could in turn get another repository (such as EntryRepository). Or the aBlog could call directely the EntryRepository (better IMHO).

    With the advent of Linq to NHibernate (Linq is a standard in C#)) one may even question the need for Repositories. Let’s say your ORM is a Meta Repository of all persistant domain objects.

    So one could do simple something like the following in the domain object:

    IList[Entries] GetLastEntries(int lastn)
    {
    var q = (from entry in OB.Entities() where entry.Blog.ID == blogId select entry).Take(lastn);
    return q.ToList();
    }

    One can argue that this is a query to the Domain Model, as such any domain object can use it. Or you can view it as a query to a persistant system and as such should not be part of it as in ones view the Domain Object would contain “impurities” (less POCO).

    But purities aside. In the end of the day you want to decouple queries such as this from a domain object so it can be reused by several domain objects (The pragamatic programmer). As such the Repository is the place to go, and a good abstraction to deal with such concerns!

    Now a case for calling Business Services instead of other domain objects(a Layer) by a Domain Object.

    Say you have the domain object CreditCard and you to pay a certain ammount of money using it. We know that an external service will be needed (Plugin).

    Again if using the first rule of OOP and OOM you think of:

    aCreditCard.Credit(685,82, Currency.Euros).

    The Credit method would then call a service say:

    try
    {
    this.PaymentService.Credit(this.Owner.Name, this.Owner.Address, this.Number, this.Code, this.ExpriryDate, ammount)
    }
    catch (PaymentService.PaymentException ex)
    {

    }

    You may argue that CreditCard should not be payment aware but that is not what the first and the second rule state. You want to pay by CreditCard, there is nothing more specific then that.

    Then say you want to pay an Order using a CreditCard, you would do.

    aOrder.Pay(aCreditCard);

    that would then

    aCreditCard.Credit(this.CalculateAmmount);

    You want to pay an order by credit card. The most specific is the Order since the credit card ca be used to pay several orders. You may think that this is abstract thought, but think about the following.

    The Pay method of the Order would actually check if it could fulfill the order, if the customer as a plafond, calculate the ammount to be payed (promotional discounts etc etc, if it could pay by credit card etc etc. Most probably using Buyer (roles of customer) and Product business services.

    This is to say, that most people that think this is impure and that is not due to architecture concerns in the case of Domain Object basically they are fighting against the first rule of good OOM (Object Oriented Programming and Modeling).

    This rule if often broken mainely due to systemic reasons using layers of Business Services as first order objects (mega services that are complex to manage). Enterprise Beans (Java), DAO based systems that are built to cope more with the relation model of things then OO model are architectures that impose this kinds of layers and first order Mega Business Services.

    Indeed the great thing about using using ORM is that it allows these basic rules of OOP to be respected within the context of persistance and transaction, as such allowing a system to be better built and easily managed.

    A wonderfull book presenting a solid foundation for understanding OOP and best practices is “Streamlined Object Modeling” within the context of Domain Modeling and development. It does not deal with Repositories, Services Layers and other architecture concerns but teaches one to think in OO terms.

    This book needs to be read with a pinch of salt, since some practices are not possible due to architecture. For instance, if one is using DAO and DTO (a form of Entities) then it’s no use. But if one is using an ORM such as NHibernate it is a eye opener.

    Nuno Lopes
    PS: Sorry for this long post.

  9. “Can you provide a simple and usable example of such overload?”

    public class Interceptor: IInterceptor
    {
    public object Instantiate(Type type, object id)
    {
    return IoC.Resolve(type);
    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s