Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a model class represent an entity or return it

I'm designing a web application with CodeIgniter (but I think the question applies generally to the MVC pattern in web applications).

When I design the model class for some database entity (say, a BlogEntry for illustration), I basically have two choices:

The "classic OOP" approach would be, to let the class represent the entity, i.e. one instance of the class is a BlogEntry. In CodeIgniter, this would lead to code like

class Blogentry extends CI_Model {
    function load($id) {
      // Access database
      $this->id = $dbresult.id;
      $this->title = $dbresult.title;
      $this->author = $dbresult.author;
    }
}

To get access to some blog entry, I would do a $this->load->model('blogentry');, call $this->blogentry->load($id) and then work with the model class instance.

The other approach, which I've seen frequently in the wild, is to let the model return the entity in some data structure. In code:

class Blogentry extends CI_Model {
  function get_entry($id) {
    // Access database, yielding $dbresult
    return $dbresult;
}

With this I would write

$this->load->model('blogentry');
$the_entry = $this->blogentry->get_entry($id);

in the controller and work with $the_entry. In this second case, the class is more like a factory or builder class.

Is any of these two approaches considered the "right way" of doing M in MVC? I think, I've seen the second approach more often, but I didn't look at that many MVC-Webapps. Any thoughts of why the first or the second approach might be more appropriate?

like image 913
MartinStettner Avatar asked Aug 06 '12 17:08

MartinStettner


1 Answers

First and foremost, CodeIgniter is not an MVC framework. The paradigm that fits best is probably MVP or something like ORM-Template-Adapter. So let me break down my answer based on that naming fallacy:

In Classical/traditional MVC (not what frameworks claim is MVC), a model is not a class or a single file, but rather a layer that contains all of the domain business logic, and usually are only made of of things like Domain Objects, Data Mappers, and something to handle the interface between the calling entity and the domain logic, as to keep such code out of the controller (in MVC, for example). Tereško names them "services", which is good enough for a quasi-official name.

So in traditional MVC, requests to the model layer com in through "services," which in turn interact with the domain objects and data mappers.

Obviously all of that has little relevance to what CodeIgniter and other frameworks call "MVC." In this design pattern (I'll call it "CIMVC" for short), a Model is a class that is called and manipulated by the Controller, and interacts with the database directly. Storing data in member variables within the model doesn't make a whole lot of semantic sense, but if you're interested in something similar, check out any of the ORM plugins/libraries written in CIMVC. (Though ORM solutions wouldn't be any better at conforming to traditional MVC...)

As for common practices, most of the CI applications I've seen return "raw" database data back to the controller for handling; This keeps the domain business logic within the model. My personal preference in CIMVC is to minimize/eliminate anything but domain business logic in the models.

tl;dr - "Traditional/proper" MVC in CodeIgniter is basically impossible, so trying to force your CI code to conform to traditional MVC paradigms is silly (and will likely drive you to insanity)

edit: To clarify some earlier confusion about business logic in the Model layer, yes, you should have all of the business logic in the model layer. However if there is extra data processing going on (sorting, manipulation, etc), now we move into dangerous territory for DRY and SRP violations; You want the model to be reusable, so be wary of adding so much or such specialized logic that it becomes unusable in other parts of the application.

like image 193
orourkek Avatar answered Oct 12 '22 21:10

orourkek