Repositories.

A client needs a practical means of acquiring references to preexisting domain objects. If the infrastructure makes it easy to do so, the developer of the client may add more traversable associations, muddling the model. On the other hand, they may use queries to pull the exact data they need from the database, or to pull a few objects rather than navigating from the ‘Aggregate’ roots. Domain logic moves into queries and client code, and the Entities and Value Objects become mere data containers. The sheer technical complexity of applying most database access infrastructure quickly swamps the client code, which leads developers to dumb down the domain layer, which makes the model irrelevant.

Therefore, for each type of object that needs global access, create an object that can provide the illusion of an in memory collection of all objects of that type. Setup access through a well known global interface. Provide methods to add and remove objects, which will encapsulate the actual insertion and removal of data in the store. Provide methods that select objects based on some criteria and return fully instantiated objects of object whose attribute values meet the criteria, thereby encapsulating the actual storage and query technology. Keep the client focused on the model, delegating all object storage and access to the Repositories.