Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC and the Repository Pattern: Roles of Controllers, Models, and Repositories?

So I've been studying the role of the repository pattern as a means of decoupling the persistence layer from my models in an MVC framework. Prior to this, I might have my UserModel calling active record methods directly in order to store/retrieve domain objects.

Here's a sketch of what I'm thinking in regards to the call stack in a request that should create a new User:

enter image description here

Here are my questions:

  1. Is this a correct implementation of the repository pattern?
  2. I understand that the controller should take the user's information from the request and pass it into the model. How does that usually happen? Should the controller create a User object and then pass that into the model? I sure as heck don't wanna just pass in an array of values into the model--nor do I want to pass in 15 arguments to the model method that creates a user.
  3. In order for this pattern to really work, it looks like to me I would need to have a domain object that is just a simple data structure with no behavior and then if I'm using an ORM, I would have an ORM object which will describe how the object is persisted. Initially I resisted this because it feels like duplicate code, but if I'm really separating persistence from the business logic, this would be needed right? For example, what if I went with an in-memory store? I would no longer use the ORM object.

Am I thinking correctly here? Is this acceptable. Please help me connect the dots in my head.

like image 558
Jesse Bunch Avatar asked Sep 09 '12 23:09

Jesse Bunch


People also ask

What are the responsibilities of a controller in the MVC pattern?

A controller is responsible for controlling the way that a user interacts with an MVC application. A controller contains the flow control logic for an ASP.NET MVC application. A controller determines what response to send back to a user when a user makes a browser request.

What is repository pattern in MVC?

The repository pattern is intended to create an abstraction layer between the data access layer and the business logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access.

Is repository a model or controller?

The repository interface itself is generally considered part of the model, though the domain objects shouldn't be saving themselves -- this should be done in the controller.

What is repository in repository pattern?

The Repository pattern. Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.


1 Answers

1. Is this a correct implementation of the repository pattern?

I'm not sure where you been doing that research, but you have got it wrong.

  • Repositories as for separating the domain objects from data mappers.

  • There no such thing as "models". Model in MVC design pattern is one of the to main layers: presentation layer and model layer.

  • And the repository pattern is incompatible with active record (anti)pattern, which combines domain and storage logic in single instance, thus causing a major SRP violation.

To use a real world example for, when and how to use a repository here is an example:

You are creating some document management tool, where said documents can come from several sources (for example: local SQL database, SOAP service and cache). In this situation you create a repository, which deals with the "routing" of storage. It is the part of application, that decides which data mapper to use for storing/retrieving each document.

The goal of repository is to separate the domain logic from the interaction with storage. For the system, that was described above, a repository would also let add new data sources, without need to rewrite large amounts of code (if any). You could just add another type of mapper for the document.

2. Should the controller create a User object and then pass that into the model?

To begin with, controller itself should not create anything. Instead your controller should use a factory for acquiring instance of the object that you need. This factory can be provided to the controller through constructor or some other method. This is called: Dependency Injection (to learn more about it, watch this lecture).

Also, as noted above, model is a layer, not any specific class or object. The responsibility of controller is to alter the state of model layer (by passing data to it). You could interact with domain objects and mappers (or repositories) directly in the controller, but it would mean leaking some of the business logic in the controller. It is recommended to instead use services, which then manipulates said domain objects and storage related structures.

As for the issue with 10+ parameter, that you would require for creation of new user account, let's assume you have action with following footprint:

public function postUser( Request $request )
{
    ....
}

If the action gets called with specific Request instance, you have two options how to deal with large amount of parameters:

  1. Wrap the instance in a decorator, which would let you call a single method for forming the data from request in a specific array. Then you pass this array to the service(s).

  2. Form the array inside the controller's action and pass it, where th data is required.

The former solution is more suited for large scale applications, where such formation of data would be required repeatedly though-out the code. But in a small/medium projects the second option is the common-sense approach.

Thing is, the job of the controller is to take the user's input, and distribute it to the model layer and current view. And formation of such array fits right-in with this mandate.

3. (..) main object that is just a simple data structure with no behavior and then (..)

No. Domain object is not "simple data". It is where most of the domain business logic resides in the application.

And forget about magical ORMs. First step for implementing a repository is to separate the domain and storage logic. Domain object handles the validation and business rules, mapper deals with persistence and data integrity (small example here).

Another thing that you must realize is that repositories for web application do not really interact with in-memory persistence (apart from cache). Instead your repository would be juggling mappers for different data sources.

like image 129
tereško Avatar answered Oct 21 '22 18:10

tereško