Hendry Luk — Sheep in Fence

July 29, 2008

Unity vs Anemic Domain Model

Filed under: Software Development — Hendry Luk @ 3:45 am
Tags: ,

It’s so unfortunate that one of the most important features of a DI container that leads to good design can hardly be found on DI products (.Net) today. And the only major one that does support it, is ironically one that is widely considered most inferior in the competition: Microsoft Unity Application Block.

The feature I am talking about is post-instantiation configuration. Or BuildUp() method in Unity. That is, the ability to resolve dependencies of instantiated object. This is the only single feature that stands out as the most interesting aspect I can find from Unity. And by the way, the good design I am talking about, is avoiding Anemic Domain Model.

A class in object-orientation by definition should have both structure and behavior. EJB decided to srew this up by introducing seperation between Session Beans and Entity Beans. Entity beans were fetched from DB, containing only getters and setters, then passed around like cargo between services layers (Session Beans) where all business operations happened.

Dependency Injection came to rescue. Suddenly POJO was becoming the hottest buzzword of the days. Now instead of orderSubmissionService.Submit(order), people found new love to cleaner order.Submit(). Some people even take it further with fluent interface: order.Submit().From(thisStore).NotifyProgressTo(customerEmail).And(agentEmail);

So ideally, the domain object would contain behavior to deal with its own processing and persistence. If domain objects offer such behavior, the service layer will deal with them in object-oriented fashion. Thus, instead of telling OrderSubmissionService to submit an order, the application layer will tell the Order to submit itself.

This makes the code cleaner and easier to maintain. There might still be OrderSubmissionService though, sitting below the skin of Order.Submit(). And we expect DI container to make this OrderSubmissionService accessible for Order instance. Unfortunately, this is where DI containers and ORM today fall short.

Even after the the collapse of EJB era, and with Domain-Driven-Design gaining its fame, the way people architect entities has not changed that much. Today’s DI containers do not even make it easy for an entity to do their job.

Entities are typically instantiated by tools like Hibernate, and thus most DI containers do not support to resolve dependencies for these objects. Preventing our Order entity to do its job. People then end up switching back to the old way by placing business logic in DI-able service layers.

The fact is, this single feature is very easy to implement. My post shows that it won’t take more than few lines of code to make it happens. And I think the Microsoft PnP team has made a really good decision to bring this trivial but important feature.

9 Comments »

  1. [...] We no longer own the class. Now the entity class turns into Anemic Model. A dumb data cargo; same problem that I had before. It’s just CLR version of databse table. Then one will need to explain why it’s still called [...]

    Pingback by Code Generation in ORM « Hendry Luk — Sheep in Fence — July 29, 2008 @ 5:19 am | Reply

  2. Is not the IApplicationContext.ConfigureObject(in spring.net) does the same?

    Comment by Nik — August 5, 2008 @ 7:04 am | Reply

  3. I’m not a big user of Spring.Net, but the only IApplicationContext.ConfigureObject that I know is managing the lifecycle (instantiation) of the configured object itself. Thus, we can’t pass in an “alive” instance and ask Spring.Net to configure it (i.e., post-instantiation configuration).
    I know Spring (Java) has supported this feature since 2.0 (which became one of the hottest new features on that day) with its @SpringConfigured annotation using AOP from AspectJ.
    I might be missing something, but I’m not aware of similar functionality in Spring.Net.

    Comment by hendryluk — August 5, 2008 @ 11:43 pm | Reply

  4. If you use nHibernate, you can just implement your own IInterceptor:Instantiate(Type, object) method to let IoC container manage the instantiation.
    But if your ORM doesn’t give you any control over instantiation, IoC contaier’s support for post-instantiation configuration can be very handy :)

    Comment by hendryluk — August 6, 2008 @ 9:53 pm | Reply

  5. From method documentation:

    Injects dependencies into the supplied instance
    using the named object definition.

    Comment by Nik — August 11, 2008 @ 11:38 am | Reply

  6. In my code, it looks like:
    public class ComplexEntityInterceptor : IInterceptor
    {
    public bool OnLoad(object entity, object id, object[] state, string[] propertyNames, IType[] types)
    {
    if (entity as IComplexEntity !=null )
    {
    IApplicationContext ctx=ContextRegistry.GetContext();
    ctx.ConfigureObject(entity, entity.GetType().Name);
    }

    return false;
    }

    Comment by Nik — August 11, 2008 @ 11:41 am | Reply

  7. ConfigureObjects creates a new instance that wraps around the target (as a proxy), and return it to us. But I seemed to miss the nature of IoC itself, that the target will obviously get their dependency injected too. So I think you’re right Nik. Thanks for clarifying

    Comment by hendryluk — August 17, 2008 @ 6:19 am | Reply

  8. I love the simplicity of being able to do order.Submit(), rather than OrderRepository.Submit(order);
    In the .net world, Castle Project Active record provide this behavior. And because it relies on NHibernate, it supports the normal stuff like cascading save, delete, etc.

    I though most IoC containers support injecting live instance? in asp.net webform environment this is a crucial behavior to have to make it work with the webform as it is automatically instantiated. UnityContainer and StructureMap have buildup(), albeit structuremap support only came recently.

    Comment by Ronald Widha — May 8, 2009 @ 9:31 am | Reply

  9. AR pattern greatly helps productivity, particularly on small form-over-data applications, but it’s not something I quite fancy in domain-driven application. Database access is not exactly what I intended to inject for order.Submit();
    Order.Submit() would simply change its internal status and perhaps finalize several monetary values associated with submission of an order.
    However to do this task, order will need to consult to many different concerns that are not available within its aggregate boundary. For instance, it needs to calculate the tax.

    public class Order
    {
    private ITaxCalculator taxCalculator;
    public void Submit() {}
    }

    TaxCalculator therefore requires dependency-injection. Many argue that this kind of logics should belong to domain-service.
    E.g.

    public class OrderSubmissionService
    {
    public void SubmitOrder(Order order)
    {
    Money tax = taxCalculator.CalculateTax(….);
    order.SetTax(tax);
    order.Submit();
    }
    }

    The order.Submit() becomes more anemic. And as the domain logic grows and requires more and more external services, we start to extract more and more logic from domain entity out to domain service. The domain entity becomes more and more anemic. Afterall, in many real world applications, very few logic can be performed without external information. If all should live in domain-service, anemic-domain-model is unavoidable.
    This is not to say that we no longer extract some logic out to domain-service. Domain-service is still the perfect place to host any operation that involves multiple aggregate roots.
    Another approach would be injection through method parameter:

    public class Order
    {
    public void Submit(ITaxCalculator taxCalculator) {}
    }

    I use this in many cases. But in other cases, it feels clunky. Order entity screams for its privacy. Abstraction is gone, everybody now needs to know what dependency needed to perform Submit(). And every single time we are to call Submit(), we’ll need to somehow spawn all required dependencies. That can feel a bit too much sometimes.

    Comment by Hendry Luk — May 9, 2009 @ 2:27 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.