Don’t Fucking Repeat Yourself
Posted in: Development, Codeigniter at Jul 28th, 2010
Too many times people write the same code over and over again. How many controllers do you have that share some functionality yet have these features defined in every controller instead of a base controller? I wrote this article because repeating yourself is simply bad. It isn’t a very in-depth article but it does cover the general concept of DRY in Codeigniter.
Base Controllers/Models
Base controllers and/or models are probably the easiest step towards a DRY friendly setup. For example, at work I’m currently working on the backend of a VOIP system. This system uses quite a lot of forms and to cut down the amount of code the decision was made to use a save() method to which all forms would send their data. This works at a basic level because a lot of forms share the same structure, however it still required us to define a save() method in every controller.
The solution to this was creating a save_post() method in our base controller. This method simply validates the form and inserts/updates certain data based on the associated model, ID and POST data. Even though most forms were able to use this method there were still a few that required their own method. This is perfectly fine. Not repeating yourself doesn’t mean you HAVE TO use the same method for everything. It just means you should reuse your code as much as possible.
The save_post method I talked about looks like the following:
protected function save_post($model, $id, $data)
{
if ( $this->form_validation->run() )
{
if ( $id === NULL )
{
if ( $this->{$model}->insert($data) !== FALSE )
{
$this->message->set('success', 'De gegevens zijn opgeslagen.');
}
else
{
$this->message->set('error', 'De gegevens konden niet worden opgeslagen.');
}
}
else
{
if ( $this->{$model}->update($id, $data) !== FALSE )
{
$this->message->set('success', 'De gegevens zijn gewijzigd.');
}
else
{
$this->message->set('error', 'De gegevens konden niet worden gewijzigd.');
}
}
}
}
Using a base model, for example Jamie’s MY_Model (or my own version) will also cut down the amount of code for all your models. There’s no need to write the same insert query over and over again when you can just call the insert() method of the base model.
Helpers
If you happen to write small amounts of code over and over, say a piece of code to convert a date, it might be a good idea to put it in a helper. Doing so will give you the ability to just call function X instead of having to rewrite the same lines of code. It also makes updating/changing the behaviour of the code easier. A good example is a MY_date_helper I wrote as we we’re dealing with ISO dates that had to be converted to Dutch dates. ISO dates have the format of YYYY-MM-DD whereas the Dutch format is DD-MM-YYYY. Instead of writing the following over and over again I simply put it in a function called iso_to_dutch():
echo date('d-m-y', strtotime($input['some_date_field']) );
Reusable Views
Reusing views is something that’s less common in Codeigniter projects. Sure, people might use a template library but they’re still loading multiple views that do almost the same. A good example is loading a view containing a form. When adding or editing data the form is the exactly the same yet people still tend to use a different view for both actions. It’s not that hard to use a single view instead. The combination of the if/else statement along with the isset() function is your best friend in this case. Check for the existence of certain variables in the value parameters of the form elements and output them if they exist. Don’t output anything if they don’t.
As simple as this may sound there are plenty of people who simply load 2 different views for adding/editing data. In some cases it might actually be required but even then there’s a good chance you can combine the views.
Libraries
If you intend on creating a set of features that need to be reused across models, controllers or views don’t put it in a base controller or model. Those are intended, as obvious as it may sound, for controllers/models only. Instead, use a library or helper (if it’s only a few functions). A good example of this are authentication libraries that handle the authorisation and validation of your users.
Conclusion
Just don’t fucking repeat yourself. You’ll spend way too much time writing the same crap over and over again while at the same time you could be writing kick ass applications. It’s really not that hard actually, in fact, it’s probably easier than copy-pasting the same code over and over.
Comments