Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reconciling DDD, viewmodels, and performance

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:

  1. Eagerly load all person entities, eagerly load all orders based on personId, restructure loaded entities into the viewmodel.
  2. create a JOIN/COUNT(orderId) stored procedure and have the database return data in the same structure as the 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?

UPDATES

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.

like image 731
t0nyh0 Avatar asked Aug 21 '12 06:08

t0nyh0


1 Answers

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.

like image 196
Dmitry Avatar answered Oct 18 '22 01:10

Dmitry