Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

Your domain model isn’t in the Entity Relationship Diagram

time to read 3 min | 417 words

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.


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. :-)



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

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


            throw new ...

        mRepository = repository;

        mMailService = mailService;


    public void Submit(IOrder order)


        order = mRepository.AddNew(order);





public class OrderPreferredSpecification : Specification


    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!



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.


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.


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


send the customer an email every time they submit an order

assume that there

criteria, but

meet some criteria?

----All the really weird capitalization


Ayende Rahien


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


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!




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.


Ayende Rahien


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

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

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


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.



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

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





I didn't mean to offend anyone.

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

chill out man ;)

Ayende Rahien


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

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

This should go to the castle mailing list

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats