Should Repositories Only Return Aggregates?

October 6th, 2021

Robert Möstl sent me this question by e-mail. He wasn't sure how to return the number of hammers sold in a given month from a repository. According to Eric Evans' book on domain-driven design, repositories should operate on aggregates, but Robert did not want to execute unnecessary queries to return a list of orders. He felt at odds with the DDD rules.

This is a common observation that may stem from how people think about their domain. Let's compare two thought processes and their likely conclusions.

Starting at the Database

For the first, we begin our journey at the persistence layer, often a database. Say we have an order table. We then have an OrderRepository that would operate on that table, along with a few others. The repository would then most likely return Order objects. So now when we're asked to get statistics about orders, it makes no sense to return a huge list of Order objects and their associated items, just so that we could count them on the next lime.

The reality seems to not fit within the rules. The problem is when we start our thought process at the database, we can easily get lost in the technical details.

Starting at the Domain

For the second reasoning, we'll start our journey on the opposite side, as far away from the persistence layer as possible. We should ask ourselves what we want the user to do. We want them to get the number of hammers sold. Now, just because the number of hammers sold can be obtained through the order table doesn't mean that we need to use the Order aggregates. I can represent the same data using different aggregates.

It sounds like we actually want reporting, so our repository might be named SalesReportRepository and return SalesReport objects. That object could then contain the date range for the report, as well as the numbers we need. The repository can still operate on the same tables as OrderRepository, but the queries would be adapted to return just what we need. Now we're not breaking any rules, but also not performing unnecessary operations.

It may look simple in retrospect, but it's really easy to feel trapped by the DDD rules. I try to step back from the existing code and the data sources, and think about it from the user's side. What would a UI look like for them? The closer I start to the user and their needs, the better perspective I'll generally have on the problem.

I hope this helps someone. Happy coding!

Previous: Organizing Miscellaneous Utility Functions