Convention over Configuration – what's the big deal?
January 29, 2009 CakePHP

While writing a little about jQuery and CakePHP (part 1 and part 2), which I promise I am not quite done with yet…

… another topic slowly entered my brain…

Why do we love CakePHP so much? (And why do others equally hate it for the same reason?)

Here’s what our dear wikipedia had to say about this:

Convention over Configuration (aka Coding by convention) is a software design paradigm which seeks to decrease the number of decisions that developers need to make, gaining simplicity, but not necessarily losing flexibility.

In other words, for those who are lazy, like me, Convention over Configuration can make life so much easier and all one has to do in exchange is to follow a few simple rules (AKA conventions).

So let’s take a look at a practical (albeit a very simple) example of how Convention over Configuration can make your code do all… those nice things that wikipedia talks about.

Without wasting anymore time, let’s take a look at this tiny code snippet that I often use in my views:

 $javascript->link('jquery/page_specific/beers_view_beer', false);

If you haven’t read the previous posts, let me briefly explain what’s happening. In using jQuery many of my pages require view or page-specific jQuery files to be loaded.

Now that’s all nice and well… but whoa… seems like a lot of typing to me. No?

Wouldn’t it be nicer if I could just do:

 $jsManager->myJs();

And it would automagically load the appropriate jQuery file for the given page?

Well, you’ve probably noticed that I do use a Convention in the way I name the JS files:

1. Controller name = “beers”
2. Underscore
3. Action name = “view_beer”

Now, I’m not forcing my conventions onto you, but simply pointing out that having some sort of convention for naming your JavaScript files could come in handy, and that’s not something that is talked about very often.

Following this convention I can write a tiny helper that will handle the file includes for me, rather than me having to type out an entire path (oh no!).

So, let’s make the little helper js_manager.php (in our app/views/helpers directory):

<?php

class JsManagerHelper extends AppHelper {

    var $helpers = array('Javascript');

    //where's our jQuery path relevant to CakePHP's JS dir?
    var $_jqueryPath = 'jquery';

    //where do we keep our page/view relevant scripts?
    var $_pageScriptPath = 'page_specific';

    function myJs() {
      return $this->Javascript->link($this->_jqueryPath . '/' .
                                     $this->_pageScriptPath .'/' .
                                     $this->params['controller'] . '_' .
                                     $this->params['action'], false);
    }

}

?>

And that’s all there is to it.

Whenever I use $jsManager->myJs();, the helper will find and include the file based on the Convention specified by the three simple rules listed above. I hope the code is simple enough so that you can see exactly how it works.

Of course, I did a lot more typing by writing a helper… but if I’ve got an app with 700 views, it might come in quite handy in the long run. Not to mention, if for whatever reason I decide to change the ‘page_specific’ path name to something else, the change will be a lot easier to handle.

Granted this is a very simple example, but I hope it provides some insight as to why so many developers have embraced the Convention over Configuration paradigm.

And to summarize: learn the conventions (or make your own) and in the long run make your life easier (just like wikipedia promised)!

Comments
  • skiedr

    Such function I prefer to call in beforeRender of jquery helper.
    Also usefull to load layout specific js file.

  • skiedr

    So you does not need to write nothing in each view if have helper included.

  • @skiedr

    Good point, makes it even easier.

  • I like the whole convention thing because it makes it easy to revisit old code or code done by other people. If it follows CakePHP’s conventions it’s a lot easier to figure out what is going on.

    Also, you don’t need to echo the return since you have the $inline param set to false.

    -Matt

  • @Matt Curry

    Good point on the $inline, param… old force of habit, I guess ;)
    (Another 4 chars saved!)

  • Damn, this is evil genious. You are becoming smarter and smarter… Thanks for the tip.

  • @Martin Bavio

    No worries, I consistently kill my brain cells on the weekends with plenty of beer, which conveniently keeps me from taking over the world :)

  • Also it would be interesting to add a condition to check if that JS file exists, if not then we don’t need to include a reference to that file.

  • @Erik Gyepes

    I definitely see at least three nice improvements to that code, but it was as meant to be really simple and to serve as food for thought for further ideas on extending by others ;)

  • ianmcn

    Probably a stupid question, but I’m new to jquery with Cake. If you need to use php variables in your javascript, how can you do this in any other way than within a codeblock? Is it possible to use the above technique, or indeed any convention that puts the javascript in external files?

  • @ianmcn

    Not sure what you are after exactly, but one way to interface with jQuery is to set some hidden fields in your DOM (page) to values of those PHP vars (see Part 1).
    If you are looking to actually use PHP vars in the client-side code (I hope you see the distinction), you need to parse the files on the server to output the proper JS, which, of course, creates all sorts of minor (or major, depending on your case) overhead issues.

  • ianmcn

    Hi Teknoid, thanks for the reply. It is the latter case that I am referring to (PHP in the client side code). As an example, on the project I am currently working on, I use the jquery ajax function to get data from a specified url and append it to a div element. That url has an ID parameter to it, which needs to be rendered as part of the jquery code. Not a problem if the code is embedded in the view, but I have no idea how I’d do it if the code was separate (which is how I’d prefer to do it). Much as I love your approach above, I can’t see how it would work in instances such as this?

    Sorry, this is probably beyond the scope of this article – I’m not just trying to get free help, just wondered if this was do-able using the conventions above, as they seem like a really nice way to keep things clean and easily maintainable.

  • @ianmcn

    No problemo, I can try to help if I can…
    I don’t quite understand why do you need to “render” the ID as part of the jQuery code. Wouldn’t be easier to pass the ID to the view and then grab it from some hidden field (for example) and attach it as part of the sent arguments to a given URL?

    Perhaps I’m not understanding the ultimate goal, but it’s kinda hard to do so in this format. You know you can find me on IRC to chat in more detail, or post to the google group as well.

    Generally speaking, I haven’t wrapped my brain around how to have cake produce interesting and useful jQuery code, but it’s definitely some food for thought for later ;)

  • Pingback: Links | Meat! Meat! Meat!()

*