Naming arguments and variables: Index and Number

It’s very common to have integers that are used to count objects. It’s also very common to have integers that are offsets into arrays (or similar structures).

Humans tend to count from 1 to n. In almost all cases when software uses offsets it makes sense to design the offset to run from 0 to n-1. Sometimes it is obvious which applies to a variable or function parameter. Sometimes this starts off being obvious but with the passage of time and the increase in the code complexity it becomes less obvious (even to the original code author). I know because I’ve been there.

There are also cases where it may not be so obvious from the start. Suppose you have a function which is passed the user response to the question “which one in this list of items do you want?”. Does the function return “1” if the user want’s the first one in the list or does it return zero?

I strongly encourage the use of the words “Index” in variable names which are expecting 0 to n-1 values and “Number” in variable names which are expecting 1 to n variables.

Thus you might declare the above function as

int GetUserSelectedNumber(void);

if the function returns 1 if the user selects the first item, or

int GetUserSelectedIndex(void);

if the function returns 0 if the user selects the first item.

Similarly if you have three things to control stored in an array, you might write:

const int NumberOfWidgets = 3;
TWidget Widgets[NumberOfWidgets];

and you could have a function somewhere that is declared as

void DoSomethingWithWidget(int WidgetIndex);

This is then immediately clear to everyone that the integer passed must run from 0 to n-1 (ie 0 to 3).

It’s a simple naming convention but it can save you hours when supporting your older (ongoing) code..

A Software Development Tip – !!!

When developing code it is a frequent occurance that you write something as a quick “get it to compile” fix whilst your mind is focused on the key part on which you are working.

Let me offer an example. Whilst developing a TCP/IP interface to a set of remote digital and analogue i/o you come across a need for a function to extract a set of characters that are specific within a string. You might quickly write a function with a prototype:

String ExtractSpecificCharactersFromString(String IncomingString);

 In order to keep going on the main code you are writing on you may quickly write a dummy function body:

 String ExtractSpecificCharactersFromString(String IncomingString)
{
  return String(“D0=0xf5c9”);
}

 This allows your code to compile and it retuns a sample data String that allows you to start testing your code, all of which is good!

 But there is a real danger that “dummy” code like this can get left in genuine code for too long. You end up creating your own bug: “I am sure that digital output byte is set to 0xf500, so why does it keep reading as “0xf5c9?”

 Having wasted time as a younger programmer chasing these self inflicted bugs I have adopted a procedure where I reserve a comment statement with three consecutive ’!’ characters specifically for tagging code that is still to be written. For the above example create the function body as:

 String ExtractSpecificCharactersFromString(String IncomingString)
{
  return String(“D0=0xf5c9”); // !!! still to be written
}

 Then at regular “low concentration” moments you can go back to the code and search for the character string ”!!!! in “all project files” (using the Embarcadero C++ search terminology here) and quickly find all examples of dummy code where you know further work is required.

 I chose ”!!!” for this task as it is a string which is exceedingly unlikely to appear in genuine C++ code. Choose something else if you like but whatever you choose stick with it!

 

Naming Advice – A Rule

Consider this:

If you have to write a comment in your code is it because you haven’t named your variables or functions well? I very very many cases the answer is yes.

Here’s a simple example

Consider the case of a control system for a passenger lift in a tower block. You have some digital inputs in a class called DigitalInputs and this has a series of functions to get the values of the inputs wired to input pins on your hardware. Lets suppose your software wants to check if the doors of the lift are safely closed (if they are the software may then start to move the lift to a different floor).

If the door is closed limit switch is wired to pin 16 for example your code might be:

if (DigitalInputs.Pin16IsActive()) {
// … your code to start the lift moving goes here
}

At a later date you may think this is not particularly well written so you choose to add a comment:

if (DigitalInputs.Pin16IsActive()) /* check the door is closed */ {
// … your code to start the lift moving goes here
}

This is clearer than the first sample. But a much better improvement is not to add the comment but instead to rename the member function Pin16IsActive() in class DigitalInputs to a better name, for example LiftCabDoorIsClosed(). The code then becomes much more readable (without comments)

if (DigitalInputs.LiftCabDoorIsClosed()) {
// … your code to start the lift moving goes here
}

The big bonus is that now, everywhere this function is called throughout the code, it is clear what is being checked.

Naming rule: If you have to write a comment in your code think to yourself “is it because a variable or function is badly named?”