Last time, we continued a discussion around how to organize classes inside your domain model. We defined important domain model elements: Entities, aka Reference Objects, and looked at their relationships. This month, we will review the options for loading Entities into memory.
Potluck Principle of Getting Objects You Want
The Potluck Principle states that if you need to obtain a reference to an Entity in your code, you have the following three options:
- You may be able to create the Entity yourself
- You may be able to ask another object to give the Entity to you
- You may be able to reconstitute the Entity from a previously stored state
Choosing the right option
The option #1 is usually implemented via a constructor or a factory. It works well when you need to create a new entity object, not yet tracked by the application.
As we discussed last month, Entities span through long periods of time and run across multiple systems. Unless you are writing a data entry application, you are going to work with existing Entities a lot more often than with new ones. When you need to create an existing Entity, use the option #2 or the option #3.
Let us take a look at the last month's example: User logs in into the system to check the status of their loan applications. Assuming we have a Person loaded, how shall we obtain their Applications?
To enable the option #2, design the Person class with a method or property that returns the Person's Applications. I generally prefer to pass a qualifier, such as loan type or date, that would transform one-to-many relationship between Person and Application into one-to-one with a qualifier, but this is a topic for another conversation. For now, let us assume that the Person class defines the Applications property that returns a list of Applications. This requires you to either get the Applications when the Person object is loaded into memory or implement a lazy load mechanism to defer loading Applications until the Applications property is called.
To enable the option #3, design the ApplicationRepository class with a method that returns a list of Applications for a given Person: "IList FindByPerson(Person person)".
Domain Model Structure
My preference is to place repository interfaces in the model and move repository implementation into a separate Persistence library. Keeping repository interfaces in the model helps clients understand how entities are supposed to be loaded into memory. Having repository implementation separate from the model keeps the model free from infrastructural detail.
Happy coding! To be continued...