Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
roth_stephan_clean_c20_sustainable_software_development_patt-1.pdf
Скачиваний:
25
Добавлен:
27.03.2023
Размер:
7.26 Mб
Скачать

Chapter 4 Basics of Clean C++

project, you better write them in separate files, like license.txt and copyright.txt. If a software license requires under all circumstances that license information has to be included in the head area of every source code file, you can hide these comments if your IDE has a so-called folding editor.

Don’t Use Comments to Substitute Version Control

Sometimes—and this is extremely bad—banner comments are used for a change log, as shown in Listing 4-17.

Listing 4-17.  Managing the Change History in the Source Code File

//#######################################################################

//Change log:

//2016-06-14 (John Smith) Change method rebuildProductList to fix bug #275

//2015-11-07 (Bob Jones) Extracted four methods to new class ProductListSorter

//2015-09-23 (Ninja Dev) Fixed the most stupid bug ever in a very smart way

//#######################################################################

Don’t do this! One of the main tasks of your version control system is tracking the change history of every file in your project. If you are using Git for example, you can use git log -- [filename] to get the history of file changes. The programmers who wrote the comments above are more than likely those who always leave the Check-In Comments box empty on their commits.

The Rare Cases Where Comments Are Useful

Of course, not all source code comments are basically useless, false, or bad. There are some cases where comments are important or even indispensable.

In a few very specific cases it may happen that, even if you used perfect names for all your variables and functions, some sections of your code need further explanation to support the reader. For example, a comment is justified if a section of the code has a high degree of inherent complexity and cannot be understood easily by anyone without deep expert knowledge. This can be the case, for example, when using a sophisticated mathematical algorithm or formula. Or the software system deals with an uncommon (business) domain, i.e., an area or field of application that is not easily comprehensible

to everyone. This could include areas such as experimental physics, complex simulations

84

Chapter 4 Basics of Clean C++

of natural phenomena, or ambitious ciphering methods. In such cases, some well-­ written comments explaining things can be very valuable.

Another good reason to write a comment is when you’re deliberately deviating from a good design principle. For example, the DRY principle (see Chapter 3) is, of course, valid in most circumstances. However, there may be some very rare cases in which you willfully duplicate a piece of code, such as to meet certain quality requirements. This justifies a comment explaining why you have violated the principle; otherwise, your teammates may not be able to comprehend your decision.

The challenge is this: Good and meaningful comments are hard to write. It can be more difficult than writing the code. Just as not every member of a development team is good at designing a user interface, not everyone is good at writing either. Technical writing is a skill for which usually there are specialists.

So, here are a few bits of advice for writing useful and necessary comments:

•\ Make sure that your comments add value to the code. Value in this context means that comments add important pieces of information for other human beings (usually other developers) that are not evident from the code itself.

•\ Always explain the why, not the how. How a piece of code works should be pretty clear from the code itself, and meaningful names for variables and functions are the keys to achieve this goal. Use comments solely to explain why a certain piece of code exists. For example, you can provide a rationale for why you chose a particular algorithm or method.

•\ Try to be as short and expressive as possible. Choose short and concise comments, ideally one-liners, and avoid long and garrulous texts. Always keep in mind that comments need to be maintained. It is actually much easier to keep short comments up to date than extensive and wordy explanations.

Tip  In integrated development environments (IDE) with syntax coloring, the text color for comments is usually preconfigured to something like light green or teal. You should change this color to loud red! A comment in the source code should be something special, and it should attract the attention of the developers.

85

Chapter 4 Basics of Clean C++

Documentation Generation from Source Code

A special form of comments is an annotation that can be extracted by a documentation generator. An example of such a tool is Doxygen (https://doxygen.org). It’s widespread in the C++ world and is published under a GNU General Public License (GPLv2). Such

a tool parses the annotated C++ source code and can create documentation in the form of a readable and printable document (e.g., PDF), or a set of cross-referenced and navigable web documents (HTML) that can be viewed with a browser. In combination with a visualization tool, Doxygen can even generate class diagrams, include dependency graphs, and call graphs. Thus, Doxygen can also be used for static code analysis.

In order for such a tool to generate meaningful documentation, the source code must be annotated intensely with specific comments. Listing 4-18 shows a not-so-good example with annotations in Doxygen style.

Listing 4-18.  A Class Annotated with Documentation Comments for Doxygen

//! Objects of this class represent a customer account in our system. class CustomerAccount {

// ...

//! Grant a loyalty discount.

//! @param discount is the discount value in percent. void grantLoyaltyDiscount(unsigned short discount);

// ...

};

What? Objects of class CustomerAccount represent customer accounts? Oh really?! And grantLoyaltyDiscount grants a loyalty discount? You don’t say!

But seriously folks! For me, this form of documentation cuts both ways.

On the one hand, it may be very useful to annotate, especially the public interface (API) of a C++ module, a library or a framework with these comments and to generate documentation from them. Particularly if the clients of the software are unknown (the typical case with publically available libraries and frameworks), such documentation can be very helpful if they want to use the software in their projects.

On the other hand, such comments add a huge amount of noise to your code. The ratio of code to comment lines can quickly reach 50:50. As seen in Listing 4-18, such

86

Chapter 4 Basics of Clean C++

comments also tend to explain obvious things (remember the earlier section in this chapter, “Do Not Comment Obvious Things”). Finally, the best documentation ever—an “executable documentation”—is a set of well-crafted unit tests (see the section about unit tests in Chapter 2 and the section about test-driven development in Chapter 8) that exactly show how the module’s or library’s API has to be used.

Anyway, I have no final opinion about this topic. If you want to, or have to, annotate the public API of your software components with Doxygen-style comments at all

costs, then, for God’s sake, do it. If it is well done, and those comments are regularly maintained, it can be pretty helpful. I strongly advise you to pay sole attention to your public API headers! For all other parts of your software, for instance, internally used modules, or private functions, I recommend that you not equip them with Doxygen annotations.

The previous example can be significantly improved if terms and explanations from the application’s domain are used, as shown in Listing 4-19.

Listing 4-19.  A Class Annotated with Comments from a Business Perspective for Doxygen

//! Each customer must have an account, so bookings can be made. The account //! is also necessary for the creation of monthly invoices.

//! @ingroup entities //! @ingroup accounting class CustomerAccount {

// ...

//! Regular customers can get a discount on their purchases. void grantDiscount(const PercentageValue& discount);

// ...

};

Maybe you’ve noticed that I do not comment the method’s parameter with Doxygen’s @param tag anymore. Instead, I changed its type from a meaningless unsigned short to a const reference of a custom type named PercentageValue. Due to this,

the parameter is now self-explanatory. Why this is a much better approach than any comment, you can read in a section about type-rich programming in Chapter 5.

87

Chapter 4 Basics of Clean C++

Here are a few final tips for Doxygen-style annotations in source code:

•\

Don’t use Doxygen’s @file [<name>] tag to write the name of the

 

file somewhere into the file itself. For one, this is useless, because

 

Doxygen reads the name of the file automatically. In addition,

 

it violates the DRY principle (see Chapter 3). It is redundant

 

information, and if you have to rename the file, you must remember

 

to rename the @file tag as well.

•\

Do not edit the @version, @author, and @date tags manually, because

 

your version control system can manage and keep track of this

 

information a lot better than any developer who would edit them

 

manually. If such management information should appear in the

 

source code file under all circumstances, these tags should be filled

 

automatically by the version control system. In all other cases, I

 

would do without them entirely.

•\

Do not use the @bug or @todo tags. Instead, either fix the bug

 

immediately, or use an issue-tracking software to file bugs for later

 

troubleshooting or to manage open points.

•\

It is strongly recommended to provide a descriptive project home

 

page using the @mainpage tag (ideally in a separate header file just

 

for this purpose), since such a home page serves as a getting started

 

guide and orientation aid for new developers. Comprehensive

 

concepts and high-level architecture decisions can also be

 

documented here.

•\

The interface of a class or library consists not only of method

 

signatures with their parameters and return values. There are more

 

things that belong to an interface but may not be visible to its users:

 

preconditions, postconditions, exceptions, and invariants. Especially

 

if a library is delivered in binary format and users have only header

 

files, such properties of an interface should be documented. For this

 

purpose, Doxygen offers the following tags:

 

•\ @pre for the preconditions of an entity.

 

•\ @invariant for a description of the properties that remain stable

 

throughout the lifetime of an entity.

88