Applying DDD to Northwind database
I would like to do some exercice and apply DDD to my Domain Model applied to Northwind database. Even if Northwind is an example I imagine that it was done to satisfy some " virtual business" requirements. So the goal is to have a Domain Model that respects DDD and the data is stored in Northiwnd database.
Consider this EF persistance model :
(source: developpeur.org)Notice that we have only the entities and two way relations. I would like to have a real DM which respects DDD. More, my DM model doesn't need to be the mirror of my database
How you would change des relations to have only one way relations or two ways when needed.
Are there any many-to-one or one-to-many relations that could be changed to one to one?
How would you model agregates ?
How about Values Objects, services and factories if needed ?
I know that probably I shoul look at business requirements and that look how the model shou开发者_高级运维ld change but would like to have your advaice on that.
Don't hesitate to ask for details if my question is not clear.
Thanks in advance.
In general I'm tempted to answer Mu (in the Zen sense), because the scenario is wrong from a DDD perspective. In DDD we start with business requirements and Domain experts and from those we derive a Domain Model.
Although it's a controversial point, the database is almost just an incidental artifact of the business requirements (that almost always state that Entities must be persisted).
That said, I'll try to do my best.
In most cases, an Order is a pretty important business object, and obviously we need to know about the order lines, including the Products in each line, so it would seem like we need the association from order line (Order_Detail) to Product.
However, when given a particular product, we rarely need to know in which orders it was included, so that suggests a one-way relationship right there. We can navigate from order line to product, but not from product to order lines.
However, the above analysis may turn out to be false on a deeper level. Imagine the following conversation between the developer and the domain expert:
Dev: We've created this association from orders to products so that we always know everything about the products in a particular order.
Exp: That sounds good, but what about the supplier?
Dev: That is included as well.
Exp: So what happens when we change the supplier for the product?
Dev: That will be implicitly reflected in the order data as well...
Exp: That's not what we want. We want the data to reflect the order at the time we shipped it.
In this case, it turns out that there's actually an error in the database schema. The problem may be caused by reporting, because business analysists may want to run reports on how different suppliers impact earnings (what do I know).
Such a case may suggest cutting the association from order lines to product altogether. Orders should hold historic (snapshot) product data, not current product data.
We may even entroduce a ProductSnapshot
Value Object that semantically mirrors a Product
Entity to model this in the Domain Model.
All in all, it seems more and more reasonable to model Order
as an aggregate of itself and order lines (with ProductSnapShots
), but what about the relationship between orders and customers?
As I currently understand associations and aggregates, associations define aggregates. Given an order, would we like to know about the customer? Most likely. Given a customer, would you like to know about the orders? Probably.
This suggests a two-way relationship, which makes Customer
the Aggregate Root. This means that you would have a CustomerRepository
, but no OrderRepository
. Every time you need an Order, you must get it via a Customer
.
In some cases this may make perfect sense, while this could be really clunky in other situations. It really depends on the business requirements...
You might consider creating an OrderRepository
as well, but that invades the Customer
Aggregate Root. If you do that, it becomes vague where the responsibility for the Order lies. What happens if you nagigate from Order to Customer? Customer
has a list of Orders, but are they all populated in memory if you read the Order from the OrderRepository
?
Probably not, but they are likely to be if you read the Customer from the CustomerRepository
. The point here is that analysis of Aggregate Roots is important, and once you have defined an Aggregate, you will have to stick with it and respect it.
That causes me to favor small aggregates over big aggregates, so in this example, I would constrain the aggregate to Order
and its order lines, and have no association between Order
and Customer
.
Not having a formal association between Order
and Customer
doesn't mean that we can't relate them at all, but we need explicit services to gives us all Orders for a given Customer. We can't just navigate from one to the other.
精彩评论