Comments and self-documenting code

Comments and documentation seem to be more controversial than they should be. On the one hand, many people think comments and documentation are a waste of time. Writing documentation literally takes time away from writing code, and reading comments takes time away from reading the code. In addition, some people think that comments just don't help because they can become out of date, and don't explain anything that isn't already in the source code. The worst situation with comments is when they are flat out wrong. In that case, the code would be better off without the comments at all.

However, there are few things more frustrating than debugging code written by someone that didn't add comments. Even debugging your own code just a few months after you have written it can be difficult. In the end, the time spent writing and updating comments is time that you and your teammates won't need to spend deciphering code.

While the use of comments may be controversial, writing clean, high-quality code is important to everyone. As we have already seen earlier, using white space well can improve readability. However, white space alone doesn't make code readable. We really want our code to be self-documenting. Here is an example of that, which is difficult to read, even though it has proper white space:

void DoStuff(bool x[], int y) 
{
for(int i = 0; i < y; ++i)
x[i] = true;

x[0] = x[1] = false;

int b = static_cast<int>(std::sqrt(y));

for(int a = 2; a <= b; ++a)
{
if(x[a] == false)
continue;

for(int c = a * 2; c < y; c += a)
x[c] = false;
}
}

Can you tell what the algorithm is doing? Unless you happen to know this algorithm already, chances are that you may not understand the intent of the function. Comments would help here, but the bigger problem is the low quality of the identifiers. Good variable names provide a hint as to what they will be used for. The idea is that, with good variable names, you should be able to understand the code without the need for comments. This is how you make your code self-documenting:

void CalculateSievePrimes(bool primes[], int arraySize) 
{
for(int i = 0; i < arraySize; ++i)
primes[i] = true;

primes[0] = primes[1] = false;

int upperBound = static_cast<int>(std::sqrt(arraySize));

for(int candidate = 2; candidate <= upperBound; ++candidate)
{
if(primes[candidate] == false)
continue;

int multiple = candidate * 2;
for(; multiple < arraySize; multiple += candidate)
primes[multiple] = false;
}
}

Even if you don't understand every single line of the preceding code example, you can at least use the function name as a guide. The name CalculateSievePrimes is a big clue as to what the function is doing. From there you should be able to piece together what each line is doing. Names such as candidate, arraySize, and multiple are much more meaningful than a, b, and c. The best part about self-documenting code is that it can never be wrong, and never become out of date. Of course, the code can still contain bugs. It just can't be out of sync with the documentation, because the code is the documentation.

There are a few things that you can do to attempt to make the code self-documenting, as we said before. Good variable names are a start. The variable name should explain the exact purpose of the variable and they should only be used for that purpose. For Boolean variables, give a name that makes it obvious what true means. A name such as isActive is much better than simply active or activeFlag because the names gives a hint as to what true means for that variable.

Often there will be naming conventions that distinguish between types, local variables, constants, and static or global variables. Some of these naming conventions, such as using all capital letters for const variables, are very common and used by most programmers. Other naming conventions, such as beginning all static variable names with an s_, or adding a p at the beginning of pointers, are less common. Whether you think these styles look ugly or not, understand that they are there to help readability and make wrong code look wrong. The compiler will already catch some of the problems that these naming conventions aim to solve, but since they can still help readability they are worth considering.

When giving names to methods and functions, similar rules apply. Give a clear name that explains the purpose of the function. Make sure the function or method only has one purpose. Typically, the name should be an action. CalculateSievePrimes is a much clearer name than SeivePrimes or even just Calculate. As with Boolean variables, methods or functions that return Boolean values are often named with a hint. The name IsEmpty or IsPowerOfTwo are much more clear than Empty or PowerOfTwo.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.22.160