I guess every programmer was once told to use meaningful variable names in whatever code they are writing. If we add meaning to our variable names we can greatly improve readability and make our code easier to understand for fellow developers and for ourselves in case we end up looking at code we've written quite a while ago. Adding meaning to variables by means of using descriptive names is one thing but we can quite easily take this a significant step further. A small essay on how to make variables tell something about their nature with the names we assign to them.
The discussed method of variable naming is not my invention. It's known as the Hungarian Notation. What you'll learn in this article is my personal interpretation of this notation. It's the way I use it. Other developers may use slightly different interpretations. The philosophy behind it however remains the same.
Unreadable code
Nobody likes to work with code looking like this, unless they're serious masochists:
<?php
class a {
var $b;
function __construct($n=0) {
if($n != 0) {
$this->f2($n);
}
else {
$this->f2(1);
}
}
function f1($i) {
$j = $i * $this->b;
return $j;
}
function f2($k) {
$this->b = $k;
}
}
$d = new a(5);
echo $d->f1(6);
?>
Let's make things better
Even with this ridiculously trivial example a lot of people will need some time to understand what the code actually does. Most programmers would improve the example by rewriting it like this:
<?php
class multiplyUtil {
var $multiplier;
function __construct($multiplier=0) {
if($multiplier != 0) {
$this->setMultiplier($multiplier);
}
else {
$this->setMultiplier(1);
}
}
function multiply($number) {
$result = $number * $this->multiplier;
return $result;
}
function setMultiplier($multiplier) {
$this->multiplier = $multiplier;
}
}
$myMultiplyUtil = new multiplyUtil(5);
echo $myMultiplyUtil->multiply(6);
?>
I'm sure the whole development community will agree with me the second example is a lot easier to understand. Bytes are cheap these days which means there's absolutely no gain in reducing filesizes on our code by using short, hard to understand variable names. Many developers would probably be quite satisfied with the way the example looks now. We've got descriptive names and we're using the so-called camelCase notation where appropriate. Most PHP code you will encounter in the open source world will more or less look like this. Nice isn't it? I think not! There's a whole lot we can still improve.
Introducing the Hungarian Notation
Let's rework the example again.
<?php
class clsMultiplyUtil {
var $m_nMultiplier;
function __construct($p_nMultiplier=0) {
if($p_nMultiplier != 0) {
$this->setMultiplier($p_nMultiplier);
}
else {
$this->setMultiplier(1);
}
}
function multiply($p_nNumber) {
$nResult = $p_nNumber * $this->m_nMultiplier;
return $nResult;
}
function setMultiplier($p_nMultiplier) {
$this->m_nMultiplier = $p_nMultiplier;
}
}
$objMultiplyUtil = new clsMultiplyUtil(5);
echo $objMultiplyUtil->multiply(6);
?>
Some people might have to get used to the notation I used in this third example but once they have, most developers never want to go back anymore. We've now created a piece of code that's as descriptive as possible. Let's take a look at some things.
First of all, we've renamed the class into clsMultiplyUtil. By adding the prefix cls the name of our class tells us what it is: a class! When creating an instance of this class we call our instance $objMultiplyUtil. Prepending the letters obj to the variable name tells anyone reading the code we're dealing with an object here. Then there's our little member variable. We've added the prefix m_n to it's name which tells us two things:
- The m tells us it's a class member
- The n tells us it's a numerical value.
That's a whole lot of extra information! In a similar fashion we've added a prefix p_nto the argument of the method clsMultiplyUtil->multiply(). The p tells us it's a parameter and the n tells us it's a numerical value. I hope you're picking up a pattern here!
The local variable $nNumber doesn't have a prefix with an underscore but we still add a letter n at the beginning of it's name. By the absence of an underscore we know we're dealing with a local variable. Because of the n we know the variable is numeric.
Defining types
So what have we got here? Let's look at an overview for this naming convention. First of all we introduced some prefixes that tell us what kind of variable it is we're dealing with:
| prefix | example | explananation |
|---|---|---|
| n | $nAge | Numeric |
| s | $sName | String |
| a | $aEmployees | Array |
| b | $bEnabled | Boolean |
| obj | $objIterator | Object |
| fp | $fpHhtmlDocument | File Pointer |
I'm sure I'm missing some types here. These are rather common however. Feel free to use some extra ones if you feel that's appropriate. This list isn't meant to be fully complete and it isn't meant in a dogmatic fashion either. I'm merely explaining a concept here.
Defining scope
In the example we've seen I've been doing more than just describing types for my variables. We can add even more meaning to the names. After adding a type prefix we can add an extra prefix that tells us something about the scope of a variable. In the table below we'll combine this new prefix with what we've already learned from the previous table. We will separate our two different prefixes with an underscore.
| prefix | example | explanation |
|---|---|---|
| p | $p_nAge | A function parameter denoting a numerical value |
| m | $m_sName | A class member which is a string |
Adding no extra prefix tells us we're dealing with a local variable. These would be variables defined within a function or variables defined in plain scripts with no functions or objects. Here's some additional examples to help you get used to it:
$p_bEnabled
- A function parameter with type boolean
$m_objUser
- A class member which happens to be an object
$p_aEmployees
- A function parameter which is an array
$m_sCity
- A class member with type string
Is there more we can do?
This is almost it really. In the example we've improved things a little bit more by using the prefix cls for a class name. This makes things really easy when it comes to distinguishing classes from actual objects when reading code. Furthermore we've added set to a method that sets a member variable. Little extra's that add additional meaning to our code. In the second example we've seen the concept of camelCase names. You are encouraged to combine this with everything you've seen in this article. It will result in a maximum amount of information contained within the code itself combined with maximum readability.
Closing notes
I hope this essay has been useful for you. The discussed naming convention has proven to be extremely useful to me. I've been using it for many years already after originally learning about it in 2000-2001 from Wouter Tengeler, my former team manager at Endemol. It's also discussed in detail in the book on PHP I've co-authored with him. Unfortunately for most readers this book is in Dutch.
I've used PHP in all my examples but of course you can use this naming convention in just about any programming language, be it Java, Ruby, Python, C, C++ etc.
Now let's go and write some better code!