Reputation: 680
I am starting to learn about DDD and am concerned about the performance implications of retrieving entity objects from persistence and then restructuring them in a viewmodel for the UI.
Let's say that I have two aggregate roots:
Person Orders
------ -------
personId orderId
name personId
Each aggregate root has its own repository in charge of basic CRUD operations for the entire aggregate.
Let's say that the UI requires the following columns:
viewmodel
---------
personName
numberOfOrders
I can think of two ways that I can populate this viewmodel:
Obviously, option 1 can be quite the expensive operation, as there can be multiple persons and multiple orders resulting in MULTIPLE database calls. Option 2 will require only one database call.
If Option 2 is the preferred (performant) option, where do I store this "viewmodel" and the so called "database call?" Is there a separate "data service layer" on top of the repositories that I can implement? Or is that an anti-pattern in regards to how DDD is generally implemented?
Basically, how do I reconcile complex DDD aggregates with custom UI Viewmodels keeping performance in mind?
Specifications / Query Object
In talks with a friend, he had suggested that a possible solution is some sort of specification/query object pattern. The only problem is that we will have to implement this on the repository-level, requiring me to combine the Persons and Orders into one large aggregate. This is something I generally avoid for transaction consistency reasons.
Upvotes: 7
Views: 1197
Reputation: 17350
You can introduce a dedicated value object and a repository that would return statistics for a given person:
// value object
class PersonStatistics {
String PersonName
Int NumberOfOrders
Money AverageOrderAmount
}
// repository
interface PersonStatisticsProvider {
PersonStatistics Get();
}
This is similar to a read-model pattern.
Upvotes: 6
Reputation: 14064
From a performance perspective, I'd choose option 2 but would probably keep the query that returns a person separated from the query that returns its number of orders.
You can make the order count available through something like OrderRepository.GetOrderCountByPerson(personId)
even if it does deviate a bit from your canonical definition of a repository.
Normally you derive ViewModels from your domain entities. It would seem odd to have a Service that queries the database directly so that it returns a data structure matching a ViewModel exactly.
Upvotes: 0