Oh-keeey.
What you are getting wrong about Model ..
You have to understand, that "Model" in MVC is not a concrete object or a class. Instead it is one of two major layer in application:
- model layer contains the "business logic", it's where most of the 'interesting parts' are located
- presentation layer deals with the interface through which user can interact with this "business logic"
Note: as you might already notice, it is perfectly alright to have several presentation layers in parallel. Though it's rare "in the wild".
Your presentation layer (which consists of views and controllers) interacts with model layer though services. Said services contain the interaction between domain objects and data mappers. That part goes by the name "application logic".
For example: if you had a service Library
, it manipulate and the exchange between User
and Book
instance and pass them to different data mappers for persistence. The service doesn't really care how the isValid()
method works internally for for the User
instance. Neither does it cares where the user is saved, when you call mapper.store(user)
.
The domain objects in the model layer are the code representation of 'Domain Model' (to learn what it is, see this book). Basically, they will contain all the business rules, conditions and ideas on which the application is based upon.
And the third major group of structures within model layer are usually data mappers. The are dealing with persistence logic goes. It's where your CRUD code actually exists. And part of persistence logic is the data integrity checks. If, when inserting new email address in the some table, you get an exception regarding UNIQUE
constraint violation, data mappers is where you handle it. Whether you do it by setting an error state on the domain object which you where manipulating or you kick up/return an error code to service, it's your preference (I like the former approach).
Note: mappers can persist data in any medium that like: sql, nosql, files, remote rest api, /dev/null or crystalline fairy dust. And, if you make sure that the all have same public interface, you can use multiple data mappers on the same domain object. That would let you populate the infamous User
instance from sql, cache and session. Simply by passing it to three different mappers with mapper->fetch(user)
calls
So .. where are Controllers in all this
The controllers, according to MVC pattern, have a very specific responsibility: altering the state of model layer and (in rare cases) current view. That it.
Controllers do not know anything about CRUD. Controllers do not get data from model layer. Controllers do not initialize or render views. None of it.
Note: there are edge cases, where in desktop applications (or in situations when, within application's lifetime, there are multiple users interacting with it ... not applicable to web) the controller can observe model layer for changes. And, based on specific change, unlock additional functionality for same user's interaction. I have never seen it in practice.
This also means that your views must be real objects and not just dumb templates, because, since controller isn't pulling any data from model layer, views have to decide, what information they need and request it themselves.
Such fully-implemented views will usually be juggling multiple templates/layouts and presentation objects. From high orbit the will kinda resemble services, because manipulation of templates and presentation objects will vaguely resemble interaction between data mappers and domain objects.
my 2 cents