Table of Contents

Code is just as likely to be read by a human as by a machine. It must be readable - interpretable. The code that you submit is expected to adhere to the following style guidelines. Some of these items will not apply until later assignments, but the majority of them can be put into practice immediately. They include:

Indentation

Every time a new block of code is introduced via a curly brace, the code within it should be indented 2 or 4 spaces more than the code in the next outer block (but be consistent! Pick either 2 or 4 and use that for the whole program). This makes it extremely easy to see which code is in the same block and is so fundamental to coding style that you would likely have trouble reading your own code without it!

Example:
int main(int argc, int argv[]){
   cout << "First outer block, one level of indentation";

   if(...){
      cout << "Second block, two levels of indentation";

      if(...){
         cout << "Third block, three levels of indentation";
      }
   }
}
      	
Of note: You should always use spaces instead of tabs for your indentation, as different editors interpret and display tabs differently. The good news is that VSCode does this for you. When you hit the tab button, it inserts 4 spaces by default (you can change the number of spaces in File -> Preferences -> Settings, searching for "tab size", and changing the number).

Statements and Spacing

C++ doesn’t care if you put multiple statements on a single line, but we do! A statement in C++ is simply some instruction that ends in a semicolon, so it could be an assignment, a cout or cin, or any number of interesting things. Each statement should go on it's own line.

You should also strive to separate your code into logical sections using blank lines. This will make it much easier to locate a particular section of code.

Example:
double sum_elems(double arr[], int length){

   // Local variable declarations
   double sum = 0;
   int i;

   // Loop through array, accumulate sum
   for (i = 0; i < length; i++) {
      sum += arr[i];
   }

   // Return sum to the caller
   return sum;
}
      	
Finally, as demonstrated above, binary operators (=, +, <, &&, etc.) should be buffered with a leading and trailing space:

Good: sum = 0;
Bad: sum=0;

Line Length

A good rule of thumb is that a single line of code should not exceed 80 characters in length; anything longer than that becomes less readable, particularly during grading.

In this class, having a couple lines of code that exceed the 80-character limit by a few characters is not world-ending. However, if you are consistently writing lines of code longer than 80 characters you need to re-strategize.

Global Variables

Global variables should only be reserved for constants (variables whose values do not change after initialization). To indicate that a variable is global, a great convention is to write their names in upper case, with underscores as needed.

Name-Calling

A rose by any other name would smell as sweet? Not in this class. One of the most difficult parts of writing good, clean code is naming things well: it's ideal to use short, descriptive names for variables, functions, and classes to keep your code concise but understandable. The names should describe what we're trying to represent without being too wordy. First, here are some general guidelines on what kinds of names to use:
  • The name of each variable should be either (a) a noun saying what, in the world of ideas, the variable represents, (b) a name given in the assignment description, or (c) conventional, e.g., a loop counter might be i, j, or k.
  • Once we start using functions in the course, each function should be named either with a noun describing the result it returns, or with a verb describing the action it does.
Names should also look a certain way. It's much harder to read text if different conventions are used in the same file. Here are some general form guidelines:
  • Variable names should either (1) be all lowercase, words separated by underscores (e.g., next_word), or (2) be in "camelcase" (e.g., nextWord). Be consistent with your style. If your name looks ridiculously long, it probably is. Shorten where appropriate.
  • Function names should follow the same rules as variable names, and should not include information about the return type. That's built in.
  • Class names should start with capital letters and be single words, if possible. If this is impossible, do your best to get there or use shorthand. CamelCase is used if there are mulitple words.
Note that we break these rules sometimes at the start of the course for pedagogical reasons. For example, in encrypt.cpp we were being overly-luscious with variable names in order to make the code as interpretable as possible!

General Commenting

Reading code without any accompanying documentation is not something we can do super well until we've spent months (if not years) reading it, and even then someone is likely to have used some feature or collection of tricks that aren't totally obvious. This is particularly true when we're grading your programs! This is why we need good comments; comments let you as a programmer express some of the thought process that went into your code.

Every C++ program you write in CS 11 must start with a "header" comment that summarizes the file's contents (again, this should be the first thing in your file). Some of the contents of a header comment may seem redudant to you, but it's actually useful for grading and in real-world projects! This header must contain at least three pieces of information:
  1. The name of the program file.
  2. Your name as the author of the program.
  3. The date when you started working on the file.
  4. A succinct description of the program's purpose.
Here's an example of a header comment:
// welcome.cpp
// Author: Richard Townsend (rtowns01)
// Date: 9/6/2022
// Purpose: Print a greeting out to the screen.
      	
Other comments should occur frequently enough in your code to be informative, but not so frequently as to be overwhelming. This can take some practice! Some examples of places comments belong:
  • Above variable declarations (one comment for a group of variable declarations suffices).
  • Above a calculation, especially if it’s complex and/or unclear why it’s needed
  • Above function definitions (main() is the exception; see below for more info)
  • Above a for loop or while loop (usually unnecessary inside the loop)
In general, comments should be useful to the person reading your code. They should not be a narration of how the code works. Furthermore, while it's useful to comment out code snippets while you're working on a program all commented out code should be removed from your programs before they are submitted.

Functions: Style and Contracts

General Function Style


As programmers, we strive to write code that can be reused to solve other problems and that hides unimportant details from the people using our code. This should immediately make you think of functions; we define small sub-operations that take some small, easy to solve problem and solves it in a nice little package that we can use wherever we need it with the right inputs.

There are some style guidelines that actually help us adhere to these principles more closely when writing functions:
  • Functions should have a single purpose.
  • Functions should have at most about 5-10 local variables.
  • Functions should be short; ideally less than or equal to 30 lines in length (including everything between the function's curly braces). They should ideally fit on one of those 24-line screens you get when you open a terminal on the lab machines.
These criteria make it much easier to quickly understand a function's purpose and how it fits into the whole program. They also help you determine when it is appropriate to separate your code into more than one function. For example, Having a huge number of variables in your function usually indicates you've added too much complexity, and should consider writing another function or two. Another indication that your funtion is too complex is that there are more than 3 or 4 levels of indentation.

Function Contracts


Each function you write in this class is expected to have a function contract: a block comment above the function definition that explains how the function operates. By providing a function contract, you can both keep track of what your own function should be doing and convey its meaning and purpose quickly to readers of your code. Furthermore, coming up with the contract first can simplify the implementation process immensely (i.e., it makes the code easier to write since the contract tells you what the code should do). Every function contract should list the following components:
  • The name of the function.
  • The arguments the function expects. Aim to describe what those arguments represent.
  • A succinct description of the function's job or purpose.
  • What the function returns or what "effect" it has. Again, you should try to describe what the returned value(s) represent, not just their name and type.
Here are some examples of function contracts. You should be able to understand what the function will do even without seeing its code!

  /* distance
   * Input: Two points on the plane (x, y) and (u, v).
   * Description: Compute the distance between points (x, y) and (u, v).
   * Output: The distance between the two points.
   */
  double distance(double x, double y, double u, double v) {
    //Code goes here!
  }

  /* print_menu
   * Input: None (so this function always computes the same thing).
   * Description: Print out a menu of options for the user.
   * Output: A message printed to standard output.
   */
  void print_menu() {
    //Code goes here!
  }
  /* read_line
   * Input: The name of a file and a pointer to an empty array of
   *        characters.
   * Description: Read the first line of text from the file named by
   *              'filename' and store that text in the character array
   *              pointed to by 'words'.
   * Output: Populates the array pointed to by 'words' and returns the
   *         total number of characters read in.
   */
  int read_line(string filename, char *words) {
    //Code goes here!
  }