tags:

views:

905

answers:

4

Should the model just be data structures? Where do the services (data access, business logic) sit in MVC?

Lets assume I have a view that shows a list of customer orders. I have a controller class that handles the clicks on the view controls (buttons, etc).

Should the controller kick off the data access code? Think button click, reload order query. Or should this go through the model layer at all?

Any example code would be great!

A: 

The View would relay what should happen on a click in the UI to the Control layer, which would contain ALL business logic, and would in turn call the Model layer which would only make database calls. Only the model layer should be making database calls, or you will defeat the purpose of the MVC design pattern.

Think about it this way. Let's say you change your database. You would want to limit the amount of code change required, and keep all those changes together without affecting other pieces of your application. So by keeping all data access in the Model layer, even the simple calls, you limit any changes required to the Model layer. If you were to bypass the Model layer for any reason, you would now have to extend any changes needed to any code that knows about the database, making such maintenance more complex than it should be.

Elie
+1  A: 

I like to keep the "contracts", or interfaces, for model persistence or service access in the domain (model) layer. I put implementations of data access or service calls in another layer.

The controllers are instantiated with constructors that take interfaces for the services, e.g. ISomeService, as parameters. The controllers themselves don't know how the service layers are implemented, but they can access them. Then I can easily substitute SqlSomeService or InMemorySomeService.

I've also been fairly happy with a concrete service implementation that takes a domain (model) layer repository as a parameter to its constructor.. For example: ICatalogRepository with SqlServerCatalogRepositry : ICatalogRepository is handed to CatalogService(ICatalogRepository, ISomeOtherDependency).

This kind of separation is easier with dependency injection frameworks.

JasonTrue
+4  A: 

Generally I implement MVC as follows:

View - Receives data from the controller and generates output. Generally only display logic should appear here. For example, if you wanted to take an existing site and produce a mobile/iPhone version of it, you should be able to do that just by replacing the views (assuming you wanted the same functionality).

Model - Wrap access to data in models. In my apps, all SQL lives in the Model layer, no direct data access is allowed in the Views or Controllers. As Elie points out in another answer, the idea here is to (at least partially) insulate your Controllers/Views from changes in database structure. Models are also a good place to implement logic such as updating a "last modified" date whenever a field changes. If a major data source for your application is an external web service, consider whether wrapping that in a model class.

Controllers - Used to glue Models and Views together. Implement application logic here, validate forms, transfer data from models to views, etc.

For example, in my apps, when a page is requested, the controller will fetch whatever data is required from the models, and pass it to a view to generate the page the user sees. If that page was a form, the form may then be submitted, the controller handles validation, creates the necessary model and uses it to save the data.

If you follow this method, Models end up being quite generic and reusable. Your controllers are of a manageable size and complexity because data access and display has been removed to Models and Views respectively, and your views should be simple enough that a designer (with a little training) could comprehend them.

Jim OHalloran
Think of a data access object or service injected in your controller, then your controller will not get affected from the changes in the database.
Adeel Ansari
what about pushing validation into the model? I was thinking of having the model validate and persist data, or invalidate, build up a list of violations (again within the model), fail on the save and return the model (via the controller) back to the view for correction - any suggestions?
markd
+1  A: 

I wouldn't put Data Access Code in the Controller.

To build on what has already been said, it's important to think of layering WITHIN the layers. For example, you will likely have multiple layers within the Model itself - a Data Access Layer which performs any ORM and Database access and a more abstract layer which represents the Business Objects (without any knowledge of HOW to access their data).

This will allow you to test the components of your system more easily, as it supports mocking.

Duncan