Home > PHP, Programming > Keeping your code DRY is also in the details

Keeping your code DRY is also in the details

November 27th, 2009

What you should know already…

If you have been a developer for a while, chances are you’ll have come across the term DRY. It stands for Don’t Repeat Yourself, and it is actually a form of art. Keeping your code DRY ensures you have to think well before you start coding. Instead of randomly throwing code in your IDE, you should create the reflex of thinking how you can achieve what you want, without having to type too much code.

Not out of laziness, but because you’re smart. If you ever have to change your code, you’ll be glad you decided to write that particular bit only in that particular file. Sometimes it’s much easier to just copy/paste code from one class into another. But if you have to modify that piece of code, you’ll have to remember all the places that same code appears. Unless you kept it DRY of course.

Usually when an article talks about DRY, it will be in the context of Object Oriented Programming and model abstracts/inheritance/whatnot and making sure you don’t repeat the same code in different places. But the same principle can also be applied to other aspects of our code.

Other aspects that can be kept DRY

Use class constants

Not only does the DRY principle apply to OOP and methods in classes specificly. Other aspects of your classes should be kept DRY too. Recently, I’ve become a big fan of Class Constants in PHP. I use them to replace almost anything that is prone to change. I’ll just give you some examples:

Status checking

class MyClass {
    public function getStatus() {
        return "initialized";
    }
}
 
$object = new MyClass();
if ($object->getStatus() === "initialized") {
    // do some stuff
}

If it is decided that the status “initialized” should be renamed to “init”, then I have to change it everywhere I used that string literally.
Here’s how you could do it better:

class MyClass {
    const STATUS_INITIALIZED = "initialized";
 
    public function getStatus() {
        return self::STATUS_INITIALIZED;
    }
}
 
$object = new MyClass();
if ($object->getStatus() === MyClass::STATUS_INITIALIZED) {
    // do some stuff
}

If we now have to change “initialized” to “init”, then we only have to change the constant. All other code is left unchanged, and will still work. Now that is DRY.

Database metadata

In a database, the ENUM datatype is often used to restrict the content of a field to a specific set of data it can contain. Excellent examples are the status of the previous example, flags, … Basically, anything you want to have full control of what could be a possible entry in that field. Keep these values also in Class Constants. If you change the database, then the only other manual thing you have to do, is update the associated constant.

Configuration

Since I use the Zend Framework on a daily basis, here’s an example of how Zend Framework uses constants. First let’s see how it should not be done:

$translate = new Zend_Translate(
    'gettext',
    'my_it.mo',
    'auto',
    array('scan' => 'filename'));

Instead, they use constants:

$translate = new Zend_Translate(
    'gettext',
    'my_it.mo',
    'auto',
    array('scan' => Zend_Translate::LOCALE_FILENAME));

Keep your templates DRY

Not only is it important to keep your business logic DRY, the templates you write should benefit from the same principle. For your website basic, you won’t rewrite the entire HTML structure for each page on your site. Even if you don’t use PHP in an OOP way, you will probably still use includes to include parts on your site that will return on every page. Like the menu, or the header and footer. That’s DRY. But there’s more.

Use partials (in partials)

Partials is a term from Zend Framework. They are small templates that can be reused anywhere in your larger templates. Say you have a community site, with a messaging feature. Users can send each other messages, users can receive site notices, friend invitations, … In the inbox of a user, according to the type of message, a different partial can be shown:

foreach ($messagesList as $message) {
	$this->partial('/path/to/inbox_' . $message->__toString() . '.phtml',array('item' => $message));
}

For each messagetype that can be shown in the inbox, we create a new template. Inside that template, we do the markup for that specific message. Now in the inbox, we want to show the avatar and username of the person who sent you the message, or who invited you to become his friend. It is very tempting to write that part of the template once in inbox_message.phtml, and then copy/paste it in inbox_invitation.phtml and inbox_notice.phtml. It usually happens in a flurry of “yaaay it works !!”, and you’re so happy that you don’t care if your code becomes sloppy.

Of course, the avatar and username should be put in a new template. That new template is then used in each inbox_* template. Hence the partials inside partials. You also want to add the user ranking? No problem, only 1 file to update.

Conclusion

The DRY principle isn’t only reserved for the big chunks of your business logic. It is also an important part of the details. The small things that can easily lead to a search-and-replace rampage throughout your files. The templates are also often forgotten to be kept DRY.

As with many things: think before you act :)

Share and Enjoy:
  • DZone
  • del.icio.us
  • StumbleUpon
  • Digg
  • Ma.gnolia
  • Technorati
  • TwitThis

Tom PHP, Programming , ,

  1. No comments yet.
  1. No trackbacks yet.