Your domain model isn’t in the Entity Relationship Diagram
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
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
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)
{
}
}
Also, the only reference to the EF is a picture where your choice of ORM is really a peripheral matter. Was there somthing else?
Well, one way to do it, of the top of my mind:
<order
{
BTW in regards to EF he could have used ORM then!
Santos
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))
Whenever (Something Interesting Happens)
The two are Orthogonal IMO.
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
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?
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
Ayende,
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
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
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?
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.
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
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."
Well, "John" in that case I was responding to Oren and I do not need a translator!
Thanks,
Santos
Santos,
I didn't mean to offend anyone.
I thought u might have missed it and just pointed it out.
chill out man ;)
John,
No problem man just a "small overreaction" :-)
Santos
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.
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
This should go to the castle mailing list
Comment preview