Unity vs Anemic Domain Model

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.

Advertisements

10 thoughts on “Unity vs Anemic Domain Model

  1. 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.

  2. 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 🙂

  3. 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;
    }

  4. 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

  5. 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.

  6. 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.

  7. Asserting that it breaks the rule of Object Orientation in order to have an object with out methods is like saying that one should never write helper classes. An object may have either data, operations, or both.

    Just because one can inject persistence layer strategy into a domain object does not mean that one should. Does apple.Eat() make sense? It breaks separation of concerns and complicates what would otherwise be a straightforward domain model.

    Entities should be composed of system primitives from your meta model; that is to say that rather than using ints and floats to represent concepts such as Age or Weight one should use Age and Weight types defined in your domain meta-model.

    public class Patient
    {
    THeight Height;
    TWeight Weight;
    }

    It would be well known, well defined, and well understood from your domain meta model that THeight must be constrained to be > 0 and whether or not it is nullable; the same may be said of TWeight (T = user defined “meta” or “domain” type)

    Then one can send a message having a Patient instance and it may be deserialized on the other end maintaining domain type safety rules – presumably to a CacheManager.Save(Patient) operation.

    Having Domain Entities with behaviour is absurd if the related Domain concepts do not exhibit the defined behaviour – does Apple.Eat() make sense?

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