# Code Documentation & Comments - Looking Back

Most of your code in CS 150 and CS 250 probably had quite a few comments. Inline comments are not the focus of this discussion. The focus of this discussion is documentation of classes, functions, and methods.

# 1 A Few Starting Examples

I work in few different languages. Throughout my

You have definitely been told to “comment your code” in the past, but in a less formal fashion.

Let us start with a few selected documentation examples from my CS 330 and CS 417 notes.

## 1.1 C++

Doxygen can be used for C++. Consider the following Doxygen Example:

Example 1: C++ Doxygen Documentation
/**
* Retrieve the value stored in three selected Cells
*
* @param cell1Id numeric id representing the 1st desired cell
* @param cell2Id numeric id representing the 2nd desired cell
* @param cell3Id numeric id representing the 3rd desired cell
*
* @return value stored in the Cell
*
* @pre (cell1Id > 0 && cell1Id < 10) &&
*      (cell2Id > 0 && cell2Id < 10) &&
*      (cell3Id > 0 && cell3Id < 10)
*/
CellTriple get3Cells(int cell1Id, int cell2Id, int cell3Id) const;


## 1.2 Java

/**
*
* @param numTrials # flips to simulate
*
*
* @throws InterruptedException if a thread is stopped prematurely
*/
throws InterruptedException


## 1.3 Python

Pydoc or Sphinx can be used for Python. Consider the following Pydoc Example:

Example 3: Python 3 Pydoc Documentation
def parse_raw_temps(original_temps: TextIO,
step_size: int=30, units: bool=True) -> Iterator[Tuple[float, List[float]] ]:
"""
Take an input file and time-step size and parse all core temps.

:param original_temps: an input file
:param step_size:      time-step in seconds
:param units: True if the input file includes units and False if the file
includes only raw readings (no units)

:yields: A tuple containing the next time step and a List containing _n_
core temps as floating point values (where _n_ is the number of
CPU cores)
"""


I prefer the Sphinx/Google style for Python.

Example 4: Python 3 Sphinx/Google Style Documentation
def parse_raw_temps(original_temps: TextIO,
step_size: int=30, units: bool=True) -> Iterator[Tuple[float, List[float]] ]:
"""
Take an input file and time-step size and parse all core temps.

Args:
original_temps: an input file
step_size: time-step in seconds
units: True if the input file includes units and False if the file
includes only raw readings (no units)

Yields:
A tuple containing the next time step and a List containing _n_
core temps as floating point values (where _n_ is the number of
CPU cores)
"""


## 1.4 Rust

Example 5: Rust Documentation
///
/// Take a room and change the flooring
///
/// # Arguments
///
///   * original - House to change
///
/// # Returns
///
/// House with the updated flooring
///
fn upgrade_flooring(original: &House) -> House {
//...
}


# 2 Writing Good Documentation

All code should be properly and fully documented using a language appropriate comment style. All functions (including parameters and return types) must be documented.

## 2.1 Auditing the C++ Cookbook

You may recall my Cookbook Example from the Mutator-Accessor Unit Testing Notes from CS 350 (Introduction to Software Engineering) and (possibly) the C++ and Java class checklists in CS 330 (Object Oriented Programming and Design).

Let us start with a quick audit of a C++ Cookbook Example.

C++ Cookbook

The second constructor looks incomplete.

        /**
* Create a Cookbook that can contain at most _r_
* recipes.
*/
Cookbook(int r);


Notice the int r? It is not documented. What does r represent? Let us start by adding @param r to the documentation

        /**
* Create a Cookbook that can contain at most _r_
* recipes.
*
* @param r max number of recipes that can be stored.
*/
Cookbook(int r);


That is a little more clear. The description should probably be cleaned up a little.

        /**
* Create a Cookbook with a set recipe limit.
*
* @param r max number of recipes that can be stored.
*/
Cookbook(int r);


What did we do?

1. We documented the input into the constructor (i.e., the parameter r) with an @param tag.
2. We revised the description for brevity and clarity.

Any time a function has a parameter it should be documented. Should, not must. There are a few exceptions.

## 2.2 Auditing the Java Cookbook

Let us perform a quick audit of a Java Cookbook Example.

Java Cookbook

Similar to the C++ Cookbook… the second constructor looks incomplete.

        /**
* Create a Cookbook that can contain at most _r_
* recipes.
*/
public Cookbook(int r);


The int r is not documented. What does r represent? Let us by add @param r to the documentation and clean up the description.

        /**
* Create a Cookbook with a set recipe limit.
*
* @param r max number of recipes that can be stored.
*/
public Cookbook(int r);


What did we do?

1. We documented the input into the constructor (i.e., the parameter r) with an @param tag.
2. We revised the description for brevity and clarity.

This feels like Déjà vu. We just updated the Java Constructor using the same process from the C++ version!

There are a few more tweaks to be made to the Java Cookbook documentation. However, I will leave those tweaks as a practice exercise.

## 2.3 Documentation for a New Function

Suppose we have just finished writing a quick program to simulate a trick coin (i.e., a coin where heads and tails are not equally probable).

bool one_flip(double p);

int main(int argc, char** argv)
{
// Seed the random number generator with the current time
srand(time(NULL));

const int num_flips = 8;

for (int i = 0; i < num_flips; i++) {
if (one_flip(0.7)) {
}
else {
cout << "Tails" << "\n";
}
}

return 0;
}



The one_flip function needs a description.

/**
* Simulate a single coin flip.
*/


What does p represent? Does it represent the probability of heads or tails?

/**
* Simulate a single coin flip.
*
* @param p probability of heads
*/


Now what about the return? We know that bool means a true or false. Which one do I get for heads? Let us add an @return.

/**
* Simulate a single coin flip.
*
* @param p probability of heads
*
* @return true if the result is heads and false if the result is tails
*/
bool one_flip(double p);


There is no more ambiguity or guesswork. Both p and the possible return values are documented.

Java and C++ are similar. If we change bool to boolean, and rename one_flip to oneFlip… we have a Java function.

    /**
* Simulate a single coin flip.
*
* @param p probability of heads
*
* @return true if the result is heads and false if the result is tails
*/
boolean oneFlip(double p)
{
//...
}


Notice how the documentation is identical? The basic Javadoc comment syntax overlaps Doxygen comment syntax.