An ideal variable naming convention for loop variables?
language-agnosticnaming-conventions
If you are writing a simple little loop, what should you name the counter?
Provide example loops!
Best Answer
I always use a meaningful name unless it's a single-level loop and the variable has no meaning other than "the number of times I've been through this loop", in which case I use i.
When using meaningful names:
the code is more understandable to colleagues reading your code,
it's easier to find bugs in the loop logic, and
text searches for the variable name to return relevant pieces of code operating on the same data are more reliable.
Example - spot the bug
It can be tricky to find the bug in this nested loop using single letters:
int values[MAX_ROWS][MAX_COLS];
int sum_of_all_values()
{
int i, j, total;
total = 0;
for (i = 0; i < MAX_COLS; i++)
for (j = 0; j < MAX_ROWS; j++)
total += values[i][j];
return total;
}
whereas it is easier when using meaningful names:
int values[MAX_ROWS][MAX_COLS];
int sum_of_all_values()
{
int row_num, col_num, total;
total = 0;
for (row_num = 0; row_num < MAX_COLS; row_num++)
for (col_num = 0; col_num < MAX_ROWS; col_num++)
total += values[row_num][col_num];
return total;
}
Why row_num? - rejected alternatives
In response to some other answers and comments, these are some alternative suggestions to using row_num and col_num and why I choose not to use them:
r and c: This is slightly better than i and j. I would only consider using them if my organisation's standard were for single-letter variables to be integers, and also always to be the first letter of the equivalent descriptive name. The system would fall down if I had two variables in the function whose name began with "r", and readability would suffer even if other objects beginning with "r" appeared anywhere in the code.
rr and cc: This looks weird to me, but I'm not used to a double-letter loop variable style. If it were the standard in my organisation then I imagine it would be slightly better than r and c.
row and col: At first glance this seems more succinct than row_num and col_num, and just as descriptive. However, I would expect bare nouns like "row" and "column" to refer to structures, objects or pointers to these. If row could mean either the row structure itself, or a row number, then confusion will result.
iRow and iCol: This conveys extra information, since i can mean it's a loop counter while Row and Col tell you what it's counting. However, I prefer to be able to read the code almost in English:
row_num < MAX_COLS reads as "the row number is less than the maximum (number of) columns";
iRow < MAX_COLS at best reads as "the integer loop counter for the row is less than the maximum (number of) columns".
It may be a personal thing but I prefer the first reading.
An alternative to row_num I would accept is row_idx: the word "index" uniquely refers to an array position, unless the application's domain is in database engine design, financial markets or similar.
My example above is as small as I could make it, and as such some people might not see the point in naming the variables descriptively since they can hold the whole function in their head in one go. In real code, however, the functions would be larger, and the logic more complex, so decent names become more important to aid readability and to avoid bugs.
In summary, my aim with all variable naming (not just loops) is to be completely unambiguous. If anybody reads any portion of my code and can't work out what a variable is for immediately, then I have failed.
Prefer composition over inheritance as it is more malleable / easy to modify later, but do not use a compose-always approach. With composition, it's easy to change behavior on the fly with Dependency Injection / Setters. Inheritance is more rigid as most languages do not allow you to derive from more than one type. So the goose is more or less cooked once you derive from TypeA.
My acid test for the above is:
Does TypeB want to expose the complete interface (all public methods no less) of TypeA such that TypeB can be used where TypeA is expected? Indicates Inheritance.
e.g. A Cessna biplane will expose the complete interface of an airplane, if not more. So that makes it fit to derive from Airplane.
Does TypeB want only some/part of the behavior exposed by TypeA? Indicates need for Composition.
e.g. A Bird may need only the fly behavior of an Airplane. In this case, it makes sense to extract it out as an interface / class / both and make it a member of both classes.
Update: Just came back to my answer and it seems now that it is incomplete without a specific mention of Barbara Liskov's Liskov Substitution Principle as a test for 'Should I be inheriting from this type?'
Best Answer
I always use a meaningful name unless it's a single-level loop and the variable has no meaning other than "the number of times I've been through this loop", in which case I use
i
.When using meaningful names:
Example - spot the bug
It can be tricky to find the bug in this nested loop using single letters:
whereas it is easier when using meaningful names:
Why
row_num
? - rejected alternativesIn response to some other answers and comments, these are some alternative suggestions to using
row_num
andcol_num
and why I choose not to use them:r
andc
: This is slightly better thani
andj
. I would only consider using them if my organisation's standard were for single-letter variables to be integers, and also always to be the first letter of the equivalent descriptive name. The system would fall down if I had two variables in the function whose name began with "r", and readability would suffer even if other objects beginning with "r" appeared anywhere in the code.rr
andcc
: This looks weird to me, but I'm not used to a double-letter loop variable style. If it were the standard in my organisation then I imagine it would be slightly better thanr
andc
.row
andcol
: At first glance this seems more succinct thanrow_num
andcol_num
, and just as descriptive. However, I would expect bare nouns like "row" and "column" to refer to structures, objects or pointers to these. Ifrow
could mean either the row structure itself, or a row number, then confusion will result.iRow
andiCol
: This conveys extra information, sincei
can mean it's a loop counter whileRow
andCol
tell you what it's counting. However, I prefer to be able to read the code almost in English:row_num < MAX_COLS
reads as "the row number is less than the maximum (number of) columns";iRow < MAX_COLS
at best reads as "the integer loop counter for the row is less than the maximum (number of) columns".An alternative to
row_num
I would accept isrow_idx
: the word "index" uniquely refers to an array position, unless the application's domain is in database engine design, financial markets or similar.My example above is as small as I could make it, and as such some people might not see the point in naming the variables descriptively since they can hold the whole function in their head in one go. In real code, however, the functions would be larger, and the logic more complex, so decent names become more important to aid readability and to avoid bugs.
In summary, my aim with all variable naming (not just loops) is to be completely unambiguous. If anybody reads any portion of my code and can't work out what a variable is for immediately, then I have failed.