Ayende @ Rahien

Refunds available at head office

Your domain model isn’t in the Entity Relationship Diagram

image As usual, reading Udi’s articles is an interesting experience, and his latest one, Employing the Domain Model Pattern is no exception.

I am actually a proponent about thinking twice before approaching a domain model architecture, but not because I see it as a way to manage change. I see it as a way to manage complexity, and you need a fairly high threshold of complexity before the domain model pattern starts to justify itself. And I enthusiastically agree about the domain events model.

But probably the most important topic raised in the article is that when you sit down to think about your domain model, the last thing you should do is start drawing an Entity Relationship Diagram.

As a matter of fact, I would go a step further and say that if you are starting with the ERD, or even if you just think about your domain model mainly in terms of ERD, then you are working with an anemic domain model.

Now, take heart, as Udi mentioned, not every persistent object model is a domain model. I don’t have a problem with people mapping their persistence model using an ERD, for that matter, that is what it is for.

The problem starts when you try to use this as a domain model. And a domain model’s chief reason for existence is to incorporate both behavior and data. And you can’t do behaviors with ERD. You usually won’t notice that until it is too late, for that matter.

There are different ways to approach building different types of models. A persistence model vs. a domain model vs. transport model. All of them have their own requirements and needs. And while it is often possible to combine those needs into a single model when those needs are small, as the application grows larger, things are going to start creaking.

At that point, you’ll find that more and more you are going to put behaviors outside of the model, because it is too painful to add additional behavior inside.

This is part of the reason why I like the idea of domain events, the handlers for the domain events are part of the domain, since they form what is sure to be the most interesting (from business perspective) layer of the application.

Comments

Santos Ray Victorero, II
08/03/2009 03:29 AM by
Santos Ray Victorero, II

I liked the article and I like the idea of domain events but I wonder how much better it is than using DDD Specifications.

IMO if you submit the aggregate for persistence and apply the Specification to the returned persisted one it will work exactly the same.

Anyway they are to separate concerns.

Also I have some questions about the second part of the article. It looks to me like a kiss in the EF ass. :-)

Santos

Erik
08/03/2009 02:53 PM by
Erik

Specifications ??

How could you do the following from the article with specifications? I am not really seeing the connection?

public class CustomerBecamePreferredHandler : Handles <customerbecamepreferred
{

public void Handle(CustomerBecamePreferred args)

{

  // send email to args.Customer

}

}

Also, the only reference to the EF is a picture where your choice of ORM is really a peripheral matter. Was there somthing else?

Santos Ray Victorero, II
08/03/2009 04:10 PM by
Santos Ray Victorero, II

Well, one way to do it, of the top of my mind:

public class OrderService

{

    IOrderRepository mRepository;

    IMailService mMailService

    public OrderService(IOrderRepository repository, IMailService mailService)

    {

        if(repository == null)

            throw new ...

        if(mailService==null)

            throw new ...

        mRepository = repository;

        mMailService = mailService;

    }


    public void Submit(IOrder order)

    {

        order = mRepository.AddNew(order);

        if(order.PreferredSpecification.IsSatisfiedBy(order))

            mMailService.SendMail(order.Customer)

    }

} 



public class OrderPreferredSpecification : Specification

<order
{

    public override bool IsSatisfiedBy(Order order)

    {

        // Build your predicates here and return true/false

    }   

}



public class Order

{

    //...Other properties


    public PreferredSpecification { get; }

}

BTW in regards to EF he could have used ORM then!

Santos

Erik
08/03/2009 05:27 PM by
Erik

That would send the customer an order every time they submit an Order. Not just when they become preferred. Also, Assume that their are multiple ways that a customer may become preferred. The specification may tell you if a customer meets some criteria. But it won't tell you when that customer change happened.

Specification-- Does something Meet some criteria

Domain Event- Something Interesting Happened.

Usages

If (Specification.IsSatisfiedBy(something))

    Do Something 

Whenever (Something Interesting Happens)

  Do Something (1.Log it happened,2Publish It happened on a bus,3, Let some other object know it happened, etc...)

The two are Orthogonal IMO.

Erik
08/03/2009 05:32 PM by
Erik

Wow, I really should proofread prior to hitting submit especially if typing while having another conversation.

Corrections:

send the customer an email every time they submit an order

assume that there

criteria, but

meet some criteria?

----All the really weird capitalization

Erik

Ayende Rahien
08/03/2009 06:16 PM by
Ayende Rahien

Santos,

That looks really bad. Imagine that we have 10 such conditions.

Are you going to have 10 if statements? Or would you rather have it in the a more loosely coupled way?

Santos Ray Victorero, II
08/03/2009 06:40 PM by
Santos Ray Victorero, II

Oren,

In that case you could encapsulate all the other predicates in the IsSatisfiedBy in a more general/composite specification. But usually those conditions are within the Aggregate or are accessible from the specification.

If there is a better way I am open to use it!

Santos

Erik
08/03/2009 06:45 PM by
Erik

Ayende,

Yeah the thing I really like about it is that it allows you to be much more OCP with your Domain Model and services while still adding Interesting behavior to Domain Event Handlers.  The number of reasons for both your service class and Domain classes to change just reduced considerably when you follow his guidance in the article.

This coupled with the way he does different models for different bounded contexts (or no model at all in some bounded contexts if it is not justified) likely reduces the urge to move domain behavior out of your models.

Erik

Ayende Rahien
08/04/2009 06:10 AM by
Ayende Rahien

Santos,

As Erik pointed out, this is not something that can track state changes, which is what we are interested in here.

Second, this means that now you have to manage specifications, that is ugly. I don't want to have lots of if statements all of over the place.

Domain events make all of that complexity just go away

Tim Ross
08/04/2009 07:49 AM by
Tim Ross

I often hear that you should only use the domain model pattern for complex scenarios. What is a good pattern for the "simple" cases? How do you know if you have a domain model or just a persistant object model? I find encapsulating business rules in "domain" objects to be beneficial even in simple cases. Am I missing something here?

Dinesh Gajjar
08/04/2009 08:54 AM by
Dinesh Gajjar

While I agree with all of your article, still DDD is not the only way to go. My only point is while for DB apps : DDD is great for managing complexity, still there are other cases to not use DDD.

Santos Ray Victorero, II
08/06/2009 04:59 AM by
Santos Ray Victorero, II

Oren,

Specifications have worked fine for me but I don't know too much about Domain Events yet. As I as said in my first post I just wonder how much better it is than using Specifications. As soon as I have a chance I'll give it a try. For now I just take your word for it.

Santos

John
08/06/2009 05:24 AM by
John

I think Erik has clearly mentioned above the difference between Specification and Domain Event:

"Specification-- Does something Meet some criteria

Domain Event- Something Interesting Happened."

Santos Ray Victorero, II
08/06/2009 06:09 PM by
Santos Ray Victorero, II

Well, "John" in that case I was responding to Oren and I do not need a translator!

Thanks,

Santos

John
08/06/2009 11:19 PM by
John

Santos,

I didn't mean to offend anyone.

I thought u might have missed it and just pointed it out.

chill out man ;)

Ayende Rahien
08/08/2009 01:55 PM by
Ayende Rahien

Tim,

The difference between having a smart persistence model and a domain model are quite large. It is more related to structuring of the application and the code than just how you handle persistence.

Gauthier Segay
08/13/2009 02:33 AM by
Gauthier Segay

Ayende, (as you are officially known to master Castle MK/Windsor ;),

could you point or elaborate on how Event Registration Facility may help to wire such design without friction?

I've not used it yet but thinking of triggering all components satisfying IEventHappeningListener <tevent,> seems interresting.

But there are some rules to think about such as ordering of the handlers, being atomic or compounded, etc.

So this look like a tricky issue when dealing with larger than sample code but still my aim for "project+1", just because the provided decoupling is great for evolutivity/maintability

Ayende Rahien
08/13/2009 03:29 AM by
Ayende Rahien

This should go to the castle mailing list

Comments have been closed on this topic.