Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is the model in MVC

I'm slightly confused about what exactly the Model is limited to. I understand that it works with data from a database and such. Can it be used for anything else though? Take for example an authentication system that sends out an activation email to a user when they register. Where would be the most suitable place to put the code for the email? Would a model be appropriate... or is it better put in a view, controller, etc?

like image 568
Ian Burris Avatar asked Jul 24 '09 06:07

Ian Burris


2 Answers

Think of it like this. You're designing your application, and you know according to the roadmap that version 1 will have nothing but a text based command line interface. version 2 will have a web based interface, and version 3 will use some kind of gui api, such as the windows api, or cocoa, or some kind of cross platform toolkit. It doesn't matter.

The program will probably have to go across to different platforms too, so they will have different email subsystems they will need to work with.

The model is the portion of the program that does not change across these different versions. It forms the logical core that does the actual work of whatever special thing that the program does.

You can think of the controller as a message translator. it has interfaces on two sides, one faces towards the model, and one faces towards the view. When you make your different versions, the main activity will be rewriting the view, and altering one side of the controller to interface with the view.

You can put other platform/version specific things into the controller as well.

In essense, the job of the controller is to help you decouple the domain logic that's in the model, from whatever platform specific junk you dump into the view, or in other modules.

So to figure out whether something goes in the model or not, ask yourself the question "If I had to rewrite this application to work on platform X, would I have to rewrite that part?" If the answer is yes, keep it out of the model. If the answer is no, it may go into the model, if it's part of the essential logic of the program.

This answer might not be orthodox, but it's the only way I've ever found to think of the MVC paradigm that doesn't make my brain melt out of my ear from the meaningless theoretical mumbo jumbo that discussions about MVC are so full of.

like image 78
Breton Avatar answered Sep 22 '22 00:09

Breton


Great question. I've asked this same question many times in my early MVC days. It's a difficult question to answer succintly, but I'll do my best.

The model does generally represent the "data" of your application. This does not limit you to a database however. Your data could be an XML file, a web resource, or many other things. The model is what encapsulates and provides access to this data. In an OOP language, this is typically represented as an object, or a collection of objects.

I'll use the following simple example throughout this answer, I will refer to this type of object as an Entity:

<?php
class Person
{
    protected $_id;
    protected $_firstName;
    protected $_lastName;
    protected $_phoneNumber;
}

In the simplest of applications, say a phone book application, this Entity would represent a Person in the phone book. Your View/Controller (VC) code would use this Entity, and collections of these Entities to represent entries in your phone book. You may be wondering, "OK. So, how do I go about creating/populating these Entities?". A common MVC newbie mistake is to simply start writing data access logic directly in their controller methods to create, read, update, and delete (CRUD) these. This is rarely a good idea. The CRUD responsibilities for these Entities should reside in your Model. I must stress though: the Model is not just a representation of your data. All of the CRUD duties are part of your Model layer.

Data Access Logic

Two of the simpler patterns used to handle the CRUD are Table Data Gateway and Row Data Gateway. One common practice, which is generally "not a good idea", is to simply have your Entity objects extend your TDG or RDG directly. In simple cases, this works fine, but it bloats your Entities with unnecessary code that has nothing to do with the business logic of your application.

Another pattern, Active Record, puts all of this data access logic in the Entity by design. This is very convenient, and can help immensely with rapid development. This pattern is used extensively in Ruby on Rails.

My personal pattern of choice, and the most complex, is the Data Mapper. This provides a strict separation of data access logic and Entities. This makes for lean business-logic exclusive Entities. It's common for a Data Mapper implementation to use a TDG,RDG, or even Active Record pattern to provide the data access logic for the mapper object. It's a very good idea to implement an Identity Map to be used by your Data Mapper, to reduce the number of queries you are doing to your storage medium.

Domain Model

The Domain Model is an object model of your domain that incorporates behavior and data. In our simple phone book application this would be a very boring single Person class. We might need to add more objects to our domain though, such as Employer or Address Entities. These would become part of the Domain Model.

The Domain Model is perfect for pairing with the Data Mapper pattern. Your Controllers would simply use the Mapper(s) to CRUD the Entities needed by the View. This keeps your Controllers, Views, and Entities completely agnostic to the storage medium. This also allows for differing Mappers for the same Entity. For example, you could have a Person_Db_Mapper object and a Person_Xml_Mapper object; the Person_Db_Mapper would use your local DB as a data source to build Entities, and Person_Xml_Mapper could use an XML file that someone uploaded, or that you fetched with a remote SOAP/XML-RPC call.

Service Layer

The Service Layer pattern defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation. I think of it as an API to my Domain Model.

When using the Service Layer pattern, you're encapsulating the data access pattern (Active Record, TDG, RDG, Data Mapper) and the Domain Model into a convenient single access point. This Service Layer is used directly by your Controllers, and if well-implemented provides a convenient place to hook in other API interfaces such as XML-RPC/SOAP.

The Service Layer is also the appropriate place to put application logic. If you're wondering what the difference between application and business logic is, I will explain.

Business logic is your domain logic, the logic and behaviors required by your Domain Model to appropriately represent the domain. Here are some business logic examples:

  • Every Person must have an Address
  • No Person can have a phone number longer than 10 digits
  • When deleting a Person their Address should be deleted

Application logic is the logic that doesn't fit inside your Domain. It's typically things your application requires that don't make sense to put in the business logic. Some examples:

  • When a Person is deleted email the system administrator
  • Only show a maximum of 5 Persons per page

It doesn't make sense to add the logic to send email to our Domain Model. We'd end up coupling our Domain Model to whatever mailing class we're using. Nor would we want to limit our Data Mapper to fetch only 5 records at a time. Having this logic in the Service Layer allows our potentially different APIs to have their own logic. e.g. Web may only fetch 5, but XML-RPC may fetch 100.

In closing, a Service ayer is not always needed, and can be overkill for simple cases. Application logic would typically be put directly in your Controller or, less desirably, In your Domain Model (ew).

Resources

Every serious developer should have these books in his library:

  • Design Patterns: Elements of Reusable Object-Oriented Software
  • Patterns of Enterprise Application Architecture
  • Domain-Driven Design: Tackling Complexity in the Heart of Software
like image 37
hobodave Avatar answered Sep 24 '22 00:09

hobodave