How to Sliding Responsibility of Repository
When it comes to designing architecture of an application, everybody thinks of three layers at first: Presentation Layer, Business Layer, and Data Layer (for more information, see MSDN). In such systems, objects of business logic use repositories for extracting data from physical storage. Repositories return business entities instead of raw record sets. Often, it is justified by the fact that if we need to change the type of the physical storage (database, file, or service), we need to create an abstract repository class and implement a specific class for the required storage. It looks in the following way:
Descriptions of this division can be found in the article by Martin Fowler and in MSDN. As usual, description is just a simplified model. That is why, though it seems correct for a small project, the model is tricky when you try to transfer this pattern to a more complicated one. The existing ORM confuse even more since they implement many things out-of-the-box. But let’s imagine that a developer knows how to use Entity Framework (or other ORM) only for retrieving data. Where, for example, should it place the cache of the second level, or logging of all business operations? In the attempt to do this, it will try to divide modules by functionality in accordance with SPR from SOLID, and build a composition from them that may look as follows:
Does repository perform the same role as earlier? Obviously, the answer is ‘No’, since it does not extract data from a storage. This responsibility was passed to another object. And here we face the first discord between abstractionists and concretists.
If we presume that all terms must retain their values regardless of code modifications, it would be correct at the first stage not to call an object, that simply returns data, a repository. This is a genuine DAO pattern since its task is to hide a certain data access interface (ling, ADO.NET, or something else). At the same time, repository may not know of such peculiarities at all, and as a consequence, it assembles all data access subsystems into a single composition.