Joomla forum had an interesting conversation about the MVC framework used. In this context, Nicholas Tues Dionysopoulos summed up what what is it for:

 

Hi guys,

As with all things programming, there is no "right" or "wrong". I can tell you, however, what is the Model 2 paradigm followed by Joomla!’s MVC implementation. Joomla! is following the paradigm of "thin controller-fat model". The exact opposite is perfectly possible; neither one is The Absolute Truth, but since we’re developing for Joomla! we can at least follow Joomla!’s paradigm.

So, what are the three components of the MVC (Model-View-Controller) architecture supposed to do?

The Controller is the manager in the office. Its business is to instanciate the Model and set the model state based on the input parameters. In the current incarnation of Joomla!’s MVC implementation, this essentially means that the Controller will instanciate the Model and populate its state based on the request parameters. Since Joomla! is using a single view, multiple model approach, you may have more than one model objects instanciated by the controller. Then, the Controller instanciates the View, passes the model object(s) to it and asks the view to render itself.

The Model is the worker. It does all the heavy lifting. Based on its state (which was set by the Controller), the model performs some task. IMPORTANT! The common stupid mistake -which I have done many times in the past- is to decide what to do in the model based on request parameters. DON’T DO THAT! It’s wrong. The model should rely on its state and nothing but its state. If it needs to pass back information, it can either return them as return values of its methods, or modify its own state. Also, never EVER have the model render the data in a specific format. The model only deals with raw data. Making them pretty is the View’s responsibility.

The View is the user service department. Its only preoccupation is how to get the raw data from the model and render them into something useful, be it an HTML document, a JSON snippet or a CSV file. The View should get all of the data it needs from the model. A typical mistake -which I do a lot- is having the View fetch data directly from the request. Nope. Don’t do that, it’s wrong. The View only renders data, it doesn’t take decisions based on request data.

I should note that when talking MVC, we are usually referring to "triads". A triad of a controller, model and view can be seen as a standalone thing. It’s something which knows what to do (controller), how to do it (model) and how to present it (view). Take one of the components out and you have something unusable. However, if you want to make yourself a huge favour, the three components of an MVC triad should be completely decoupled, meaning that one should not be aware of how the other two work. The controller should have no "insider" knowledge about how the model and the view work; it just shifts data around. The model shouldn’t know how the controller or view work; it just acts on its state. The view should not know how the controller and model work; it just kindly requests data from the model based on the model state and displays it in an appropriate representation. Having the three components of the triad completely decoupled allows you to perform changes easily. You must be able to, for instance, modify how a model works -while maintaining the same public API- and neither the controller nor the view should require any changes at all. Or, you could add one more view -e.g. a JSON view of your data- without requiring any changes to your controller and/or model. You get the idea. Make stuff reusable and decoupled. Just like a roller bearing always works the same and doesn’t care if it’s used in a bicycle, motorbike or boat, your classes shouldn’t give a dime where they are used in and should perform always the same.

Further to the three foundation components of the MVC architecture, Joomla! also has two more strange beasts, called Tables and Helpers.

The Table is a strange animal in the Joomla! world. Conceptually, it’s a cross-breeed between a controller, a model and a data layer. In theory, a Table should be nothing more than a stupid adapter, a simple contraption to allow the model to request data from the database in an agnostic manner. The Joomla! implementation of a Table goes beyond that, and provides data manipulation methods (like hit() or publish()) which really belong to the model. Hence we have the strange case where the model calls a method in the table to do something as simple as publish or reorder records instead of the model itself modifying the relevant records.

The Helpers are the MVC purist’s worst nightmare. For us common mortals, however, the Helpers are our way to provide quick and dirty solutions which will come back to haunt us later on. The Helpers are supposed to be static classes, i.e. classes with nothing but static methods. They are commonly used to store reusable code which is required across a number of views, e.g. a combo box rendering the list of categories in a content management components. A very common mistake is to use the helper to hold some code which should better be put in a component, model, or view. Don’t do that. It’s code smell. Keep your Helpers lean and mean, with nothing but standalone static methods.

One thing missing from Joomla! –actually not missing, just never spelled out– is the Dispatcher.

The Dispatcher is responsible for doing pre-flight events, like loading language files and doing sanity checks, selecting a controller and running it – and, finally, processing any redirection requested by the controller. Joomla! gets away with having a split personality disorder when it comes to dispatchers. Half of the dispatcher’s code is implemented in the core, called when the application is routing itself. The other half of the dispatcher’s code exists outside of any class, in the entry point files of your components. For example, the dispatcher of the back-end part of com_example would be administrators/components/com_example/example.php (in Joomla! 1.0 it would be admin.example.php, making the naming convention even more funky).

With this knowledge in mind I think that you should never have to ask anybody else a question like "where am I supposed to put the code that does X". Think what your code does and you’ll see where it belongs.

Have I followed this approach with all of my components? Hell, no! Tons of my code dates back before I had enough theoretical background to consider proper architecture. Some of my components have gotten better over time and now that I’m rewriting Akeeba Subscriptions using the Joomla! framework I try to abide by these rules as much as practically possible. And here is my Uncertainty Clause: sometimes, following those rules may require you to write a bit more complex code than you would, which needs a little more time than you have. In those cases of uncertainty and doubt, you will end up doing a quick hack and get done with it. That’s perfectly possible. But beware! Those quick hacks will come back to haunt you. After you do such a hack and release your code, do take some time to refactor it to better architecture. The benefits will start being apparent when, after six months or so, you try to modify that code. Trust me on that, that’s the time when quick hacks come back to haunt you and they do it with extreme prejudice.

Keep on coding,

Well, yeah, but helpers should really be called "template helpers" and used only for this kind of reusable GUI code. If you have cross-component reusable code which doesn’t fit into an MVC component or a Table class, you’re probably talking about something which could be spun off as a Library instead.

The Tables, as I said, are a strange beast. They are not data layer adapters (which they should be), they are not controllers (even though they include some bits of controller code) and they are not models (even though they act like they are). IMHO, that’s the rough spot in Joomla!’s architecture. ORM is a nice workaround, but not not necessarily the ideal one for all cases 🙂 I would rather have something like Nooku’s Table/RowSet/Row collection for database accessor classes. After all, a Table belongs to the data layer, unlike what Joomla! does.

Regarding your rating, I would give 3/5 for MVC implementation, due to two issues:
– The Table thing, which violates the otherwise beautiful MVC implementation
– The, in my opinion, erroneous execution of MVC in the default JController code. Instead of hinting the developer that you should actually change the state of a single model object instance to be attached to a single view object instance, the way getModel and getView are coded make you believe the opposite. This kept me confused for years, as I don’t have any CS background. It took a Nooku presentation by Johan Janssens to finally understand how MVC is supposed to work.

 

If you take a look at JController::display() you will see that it’s doing something right. It creates a model and a view model, assigns the model to the view and asks the view to render itself. However, the getView() and getModel() methods do not return a Singleton instance of those objects. Every time you call them, they return a new object. This means that you can’t do something like:

$model = $this->getModel();
// Do something with the model
$this->display()

to create a new controller task. You are left wondering what you should do, with a cryptic comment in the docblock of display() stating that developers should override this method with their implementation. What it really means, is that all tasks should actually copy this code, but this is an overkill. Who wants to copy the same code over and over again for each task, on each controller of every MVC triad he creates? It also leads to a gross misunderstanding, that the model and view objects are "disposable" and that the controller is responsible for getting the data off the model and push it into the view. This is wrong. It couples the three objects. The controller should only tell the view "here is your model, go render yourself; you guys talk to each other". If you take a look at the code of the most popular component on JED, you’ll see this misunderstanding going on a lot (I was guilty of doing that, too, up until a few versions ago in my software).

If you want to see an example of how things could be to make things easier for a developer, just take a look at the default.php controller in Admin Tools Core or Akeeba Release System. Take a look at getThisModel(), getThisView() and display(). Still, it’s not a perfect solution (the multi-model, single view case is a bit of a kludge), but it’s better than the default JController implementation. To the core developers’ credit, this was partially fixed in the Joomla! Platform with the introduction of the specialised controller class, i.e. JControllerAdmin. Even that is still not a perfect solution, as the task methods are still huge black boxes, but at least Joomla!’s MVC implementation is becoming more intuitive to new developers.

 

More : According to MVC archetecture should Add, Edit and Remove Record functions be in the model or the controller?

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük

*