Choosing Variable Names

This is an update of a post that originally appeared on January 17, 2014.

It often surprises me that developers seem to choose completely useless variable names like MyVariable when creating an application. Although MyVariable could be an interesting variable name for an example in a book, it never has a place in any sort of production code. Even then, I try to create book examples with meaningful variable names, especially when getting past the initial “Hello World” example. Variable names are important because they tell others:

  • What sort of information the variable stores
  • When the variable is commonly used
  • Where the variable is used
  • How to use the variable correctly
  • Why the variable is important

In some cases, the variable name could even indicate who created the variable; although, this sort of information is extremely rare. If you never thought a variable name should contain all that information, then perhaps you haven’t been choosing the best variable names for your application.

Even with these restrictions in place, choosing a variable name can be uncommonly hard if you want to maximize the name’s value to both yourself and other developers. Some organizations make the selection process easier by following certain conventions. If you don’t have an organizational style guide for variable naming, modern programming languages like Python commonly provide a style guide for you to use. These style guides often consider a great deal more than simply variable naming and include issues like the amount of indentation to use. In some respects, they become quite draconian in their approach. Other style guides, like the one for C#, are less time consuming to learn, which is a good thing because most developers have better things to do with their time than to learn some of these nitpicky details. A few languages suffer from an abundance of style guides, like C++. It’s best to choose one of them, such as the Google C++ Style Guide, and stick with it.

However, let’s say that you want to create your own style guide for your organization to use because you use multiple languages and having a different style guide for each language seems just a bit absurd, not to mention adding needless complexity. In this case, you need to ask yourself a series of questions to determine how you want the style guide to work, such as these:

  1. What sort of casing do you want to use for what types of variables?
  2. What information does the variable contain (such as a list of names)?
  3. How is the variable used (such as locally or globally, or to contain coordinates, or a special kind of object)?
  4. When appropriate, what kind of information does the variable contain (such as a string or the coordinate of a pixel on screen)?
  5. Is the variable used for a special task (such as data conversion)?
  6. What case should prefixes, suffixes, and other naming elements appear in when a language is case sensitive?

The point is that you need to choose variable names with care so that you know what they mean later. Carefully chosen variable names make it possible for you to read your code with greater ease and locate bugs a lot faster. They also make it easier for others to understand your code and for you to remember what the code does months after you’ve written it. However, most important of all, useful variable names help you see immediately that a variable is being using the wrong way, such as assigning the length of a name string to a coordinate position on screen (even though both variables are integer values). Let me know your thoughts about variable naming at [email protected].

Passing By Value Versus By Reference

A number of readers have written me about the examples that use pointers in the book. One of the most common questions comes from the example on page 149 of C++ All-In-One Desk Reference For Dummies. In this example, the application contains a function that accepts an argument by reference. The use of a reference seems to have many people confused and this post will hopefully clear the issue up.

The first thing you need to understand is that there isn’t any magic going on here. The process for working with functions remains constant in C++. When you call any function with an argument, the application creates memory to hold the argument. The memory is local to that function. When the function ends, the memory is released. What the memory holds, now that changes.

Think of the memory as a box. This box has an address that points to it. When you work with a pointer, you’re working with the address. On the other hand, when you work with the value, you’re working with the content pointed to by the pointer, or the contents of the box. Whether the box the function receives contains a pointer or the value depends on how you write the function and what you pass to it from the caller.

Now, let’s look at an example so that you can better understand what’s going on.  This example will do the same thing to the number each time, but using different techniques: by value, using a pointer, and by reference.

#include <iostream>
 
using namespace std;
 
void MessMeUpA(int myparam)
{
    myparam = myparam * 2 + 10;
}
 
void MessMeUpB(int* myparam)
{
    // Obtain the current value.
    int currentValue = *myparam;
 
    // Perform the required math.
    currentValue = currentValue * 2 + 10;
 
    // Save the result.
    *myparam = currentValue;
}
 
void MessMeUpC(int &myparam)
{
    myparam = myparam * 2 + 10;
}
 
int main()
{
    // Call by value.
    int mynumber = 30;
    MessMeUpA(mynumber);
    cout << "By Value: " << mynumber << endl;
 
    // Call using a pointer.
    mynumber = 30;
    MessMeUpB(&mynumber);
    cout << "By Pointer: " << mynumber << endl;
 
    // Call using a reference.
    mynumber = 30;
    MessMeUpC(mynumber);
    cout << "By Reference: " << mynumber << endl;
 
    return 0;
}

You may notice that part of this example comes directly from page 149. If you run this example, you’ll see this output:

PassingData01

When you pass the data by value, you’re passing the information, not a pointer to the information. As a result, MessMeUpA() receives a value of 30. It doesn’t receive a pointer to the initial variable, nor does it obtain a reference to the initial variable. As a result, when the application performs the calculation, the result is thrown away.

When the application calls MessMeUpB(), it provides a pointer to the variable. However, the pointer isn’t a value. As a result, you move the value pointed to by the pointer into a local variable, perform the required math, and then move the value back into the original pointer. As a consequence, the original value is altered to 70.

Finally, when the application calls MessMeUpC(), the function obtains a reference to the original memory location. When the function performs the math, it’s actually using the original value as pointed to by the reference, which means that this is a kind of pointer, just not passed from the caller. The changes made in MessMeUpC() are reflected in the original value because you’re using a pointer to that value and not a copy of the value in local memory.

I highly recommend that anyone trying to understand how code works use the debugger to trace through that code. It’s instructive to look at each of the functions to see how they look. Place a breakpoint in each of the functions and then start the debugger. Open the Watches window, if necessary, by choosing Debug | Debugging Windows | Watches. Here is the view of the Watches window when calling MessMeUpA().

PassingData02

What you see here is a function argument—an integer that contains the value of 30. Now, let’s look at MessMeUpB().

PassingData03

In this case, you see a local variable, currentValue, that contains the updated value and a pointer to the variable used by the caller in myparam. The pointer gives you access to the value held by the caller and allows you to change it. Finally, let’s look at MessMeUpC().

PassingData04

Look at the function argument, myparam. The debugger is giving you a valuable insight here. See the address provided with the variable? Match that address to the pointer provided to MessMeUpB() and you’ll see that they’re the same. The reference is simply another sort of pointer, but one that gives you direct access to the memory without having to go through the extra steps required by pointers. The debugger even shows you that the current value of that memory is 30 (the math hasn’t been performed as of yet).

A function argument is simply a box that holds either a value or a pointer. Whether that pointer is an actual pointer or a reference depends on how you write you code. That’s the point of the example. Pointers don’t have to be mysterious or hardthey’re simply an address for an area of memory (a box if you will) that holds a specific value. Please let me know if you have any questions about this issue at [email protected].