4 minutes reading time (827 words)

Lessons in Good Coding Practices: Don't Repeat Yourself

Lessons in Good Coding Practices: Don't Repeat Yourself

I'm a parent. That tends to sound a bit like a confession. But most people who know me also know that I love kids. I have three children right now, and hope to add more in the near future. I've learned many things from being a parent. I learned there is a strange phenomenon with children where they cannot hear something they are told unless I tell them multiple times. It's interesting because it doesn't seem to be all the time, only certain times, and usually only those times when they need to do something they don't particularly want to do. And I really get tired of repeating myself. It gets quite annoying after a while.

Ok, so now everyone's wondering, what does this have to do with coding and best development practices. Today I want to talk about the principle of Don't Repeat Yourself.

Definition

Wikipedia defines the Don't Repeat Yourself Principle as follows:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. 

Let's take that definition and break it down into some easy-to-understand pieces. And then let's apply it to code.

Every piece of knowledge: In development that could be a class, a function, or merely even a block of code within a function.
single, unambiguous, authoritative representation: code should exist only once and it should be clearly written.
within a system: inside your component, module, plugin, application etc.

If we take those pieces and re-write the definition in our new terms it would look more like this:

Any code written and used within your component should exist in only one location and be clearly written.

That seems to make more sense. Now that we have a good working definition of what is involved in the principle of Don't Repeat Yourself let's look at some examples of how you would do this within your code.

Example of Bad Code

function getSingleItem($id) 
{
   // assume all variables needed
   $query = $this->db->getQuery(TRUE)
            ->select($this->db->quoteName(array('i.*', 'c.name', 'a.something')))
            ->from($this->db->quoteName('#__myitems', 'i'))
            ->join('LEFT', $this->db->quoteName('#__categories', 'c') . ' ON (' . 
              $this->db->quoteName('i.category_id') . ' = ' . $this->db->quoteName('c.category_id') . ')')
            ->join('LEFT', $this->db->quoteName('#__attributes', 'a') . ' ON (' .
              $this->db->quoteName('a.item_id') . ' = ' . $this->db->quoteName('i.item_id') . ')')
            ->where($this->db->quoteName('i.item_id') . ' = '. (int) $id);
   $this->db->setQuery($query);
   $item = $this->db->loadObject();
}

function getManyItems($ids) 
{ 
   // assume all variables needed 
   $query = $this->db->getQuery(TRUE) 
            ->select($this->db->quoteName(array('i.*', 'c.name', 'a.something'))) 
            ->from($this->db->quoteName('#myitems', 'i')) 
            ->join('LEFT', $this->db->quoteName('#categories', 'c') . ' ON (' . $this->db->quoteName('i.category_id') . ' = ' . 
              $this->db->quoteName('c.category_id') . ')') 
            ->join('LEFT', $this->db->quoteName('#__attributes', 'a') . ' ON (' . $this->db->quoteName('a.item_id') . ' = ' . 
              $this->db->quoteName('i.item_id') . ')') 
            ->where($this->db->quoteName('i.item_id') . ' IN '. implode(',', $ids)); 
    $this->db->setQuery($query); 
    $item = $this->db->loadObject(); 
}

Does that code look similar? It should. I created the second function by copying the first function and then changing a single line. (Hint: Look at the "where" clause). So what would this code look like if I re-wrote it but did so without duplicating any lines of code? Here's one possible example.

Example of Better Code

function getSingleItem($id) 
{ 
   // assume all variables needed 
   $query = $this->getQuery(); 
   $query->where($this->db->quoteName('i.item_id') . ' = '. (int) $id); 
   $this->db->setQuery($query); 
   $item = $this->db->loadObject(); 
}

function getManyItems($ids) 
{ 
   // assume all variables needed 
   $query = $this->getQuery(); 
   $query->where($this->db->quoteName('i.item_id') . ' IN '. implode(',', $ids));
   $this->db->setQuery($query);
   $item = $this->db->loadObject();
}

function getQuery() 
{ 
   $query = $this->db->getQuery(TRUE) 
            ->select($this->db->quoteName(array('i.*', 'c.name', 'a.something'))) 
            ->from($this->db->quoteName('#myitems', 'i')) 
            ->join('LEFT', $this->db->quoteName('#categories', 'c') . ' ON (' . $this->db->quoteName('i.category_id') . ' = ' . 
              $this->db->quoteName('c.category_id') . ')') 
            ->join('LEFT', $this->db->quoteName('#__attributes', 'a') . ' ON (' . $this->db->quoteName('a.item_id') . ' = ' . 
              $this->db->quoteName('i.item_id') . ')');
   
   return $query;
}

Instead of re-writing the query function twice, once inside of each function, I have extracted the repeated code and written it as a third function which I can now call from either of the two other functions. It seems simple. In fact, many developers are probably already implementing this type of coding to make their code better.

Benefits

Why is it important to not repeat yourself? There are many benefits to writing your code only once. Sure, nobody like to waste time writing code over and over again, but even more importantly you reduce the chance for bugs to occur. Less code means less chance of failure points. I am sure we've all had those moments when we can't find the problem until after wasting an hour or more looking you find a missing semi-colon. I know it's happened to me. There are other benefits too. When you later realize you need to add another table on to the query because your client needs more information from the database you only need to update one query now!

I hope many developers are already aware of this principle of Don't Repeat Yourself. If this is a new concept, congratulations you have now learned what it means to write DRY code. I wanted to start this series with an easy topic and though this doesn't cover every technical detail of this principle it does focus on a strong aspect of it. In the coming releases I look forward to looking at more principles of good development.

 

0
Leçons de bonnes pratiques de codage : ne vous rép...
More About Joomla! Certification
 

Comments

Already Registered? Login Here
No comments made yet. Be the first to submit a comment

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/