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 should 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
ProductSnapshotValue Object that semantically mirrors aProductEntity to model this in the Domain Model.All in all, it seems more and more reasonable to model
Orderas an aggregate of itself and order lines (withProductSnapShots), 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
Customerthe Aggregate Root. This means that you would have aCustomerRepository, but noOrderRepository. Every time you need an Order, you must get it via aCustomer.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
OrderRepositoryas well, but that invades theCustomerAggregate Root. If you do that, it becomes vague where the responsibility for the Order lies. What happens if you nagigate from Order to Customer?Customerhas a list of Orders, but are they all populated in memory if you read the Order from theOrderRepository?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
Orderand its order lines, and have no association betweenOrderandCustomer.Not having a formal association between
OrderandCustomerdoesn’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.