Big Blue Series — 18 — Repositories Save and Recall Those Organisms

John Connolly
Domain Intelligence Today
6 min readOct 3, 2022
Photo by Niklas Ohlrogge on Unsplash

When I look at modeling a Domain, I see it as an exercise of secluding one idea from another and building interactions between those ideas by design to make the system bits all work together. In software this is called the Single Responsibility Principle. The act of saving and retrieving a bit of data is something not to be included in the Domain Model but needs to be attached to it. When we talked about Factories in the previous article, the Factory was a tad more integral to the model in that it had some policies and procedures for producing Aggregates. Those policies and procedures were rules from the domain. Even still, I like to have Factories well labeled as such so that we know they generate domain organisms and are not the same as the domain organism itself. Similarly to how robots build cars where the pieces of those robots should not make it into the car. If they do, we have a problem!

Today we take a look at another part of Chapter 6 in Blue (Evans, 2004) and it is all about this repository. This is where we save and retrieve data and even where we respond to, but don’t manage complex transactions. Let’s take a look.

Save This for Later

Repositories should also be a separate concern attached to, but not in the Model, nor in the storage space. Repositories are like a broker. They take a command from the Model to save a bit of data, and then it works internally to figure out what the most logical place would be to save that data, and then executes. The Model never knows where that data was saved. It does not care. It trusts the repository to do right by the Domain Model and just save that data for later.

Get That Information Back Now

Repositories are also going to get the data from wherever it lives. The Domain Model need not know about the locale. It just knows, “Hey, I need this data Mr. Repository, can I have it now?!”

That is known as a query in software. So, the only thing the repository will do in the case of a query request is to find where that data is and return it to the model. This is the only way the Model should get information back that was stored earlier.

Repository Poses like a Factory

The great thing about aggregates, is they don’t really know how they were born; they were just brought out of nothing and are operating as a living thing. A factory can create them, and a call to a repository that pulls back all the data also creates them. In fact, there may be rules that both the Factory and Repository may need to share, so don’t blend them, but help them utilize Domain policies in a reusable manner.

All of this is like when you go to a formal event in the winter. You take your coat, hat and gloves off and there is an attendant there to store your coat along with all the other coats, hats and gloves from all the other guests. The attendant situates your coat in slot 27 and gives you a ticket with the number 27 on it. There is no magic to this, except that you just trusted a stranger to store your coat for you in exchange for a ticket with the number 27 on it. Two hours later, you come back with the ticket and the attendant knows right where number 27 is. You don’t. You have no idea where in the world your coat is other than it is tied to a ticket and that ticket is well known and managed by the attendant.

Separate the Command from the Query

The Command Query Separation Principle is just simply one step further. If your coat is stored by one attendant who is good at storing coats and with that focus does not retrieve coats, then there is another attendant that retrieves all the coats. Communication is more streamlined as the attendants work on only one step of the process.

You want your Repository separate from the Domain Model, but near it, because they work together. You want your commands, and your queries separate inside for efficiency’s sake. This means don’t save and return something at the same time. If you need to turn in a coat and get someone else’s coat, then do them in 2 steps each with the appropriate attendant. That way, the attendants remain efficient. And you want your command and queries related to each other, to be separate but close to each other, to make it a little easier to find things. Stay organized in this in whatever way you find, and life gets a little bit easier.

Plug and Play Adaptability

Another concern in the Repository is the half that works with the Domain Model and the other half that works with the database, file storage or any other storage location. It is generally best to keep those disconnected but communicating with one another. The reason is you may just decide to go from one database technology to a completely different one. If so, there is less code to concern ourselves with when we want to plug in one data storage brand to another.

Three Saves is One Transaction

Imagine getting three tickets. One for your hat, one for your gloves and one for your coat. Not a horrible idea, but generally a customer is only going to want one ticket for all three.

It often happens in financial institutions and many other industries that one business transaction is made up of two or more save operations to the database. Again, separation of concerns is at play here. You would manage the transaction in the place that knows about those details. That place is almost always in the domain model. Let the repository just know how to save one thing at a time and take instructions on when a transaction is starting and is completed so it can either commit to all the data saves or, if there is an issue, rollback all the saves to let the Model try it again later.

Translation Services Required

The other great thing about the Repository is that it acts as a translator between the Domain Model code and the database. For many, those two technologies will not have the same modeling capabilities. The repository can take an object model and morph it to a relational database structure and then reverse that translation when recalling the data from database. A new database type would just require a new translation module.

Conclusion

The separation of concerns is a principle that should help us understand when and where to put things. It was always tempting to just build a lot of functionality into very few places thinking it would be more accessible or maybe just out of naïve views on software modeling and development.

Database separation is a must in enterprise architecture.

Up Next, well I am not sure where I will go next on this DDD Journey. Do know we will get into modeling paradigms and more. So stay tuned and let me know how your DDD is going. I hope any of this helped you!

Until Next Time…

Photo by Mark Duffel on Unsplash

References

Evans, E. (2004). Domain-Driven Design: Tackling Complexity in the heart of software. Addison-Wesley Professional

--

--

John Connolly
Domain Intelligence Today

Domain-Driven Design Consultant. Passionately helping domain experts, architects and developers understand domain models improving product delivery.