Style Guide

Programs are easier to read and to understand when they are written in a familiar style and follow standard coding conventions. Most organizations that develop software therefore require programmers to write programs that follow the organization's preferred style and coding conventions. These conventions can be very elaborate.

Example: C++ Programming Style Guidelines

Although guidelines are often arbitrary, arbitrary deviation from accepted style makes readers wonder why the code is written so strangely. Is there some peculiarity of the particular program that motivates the nonstandard style? Or is the programmer using nonstandard style merely because the programmer is inexperienced or unfamiliar with the programming language or with software development in general?

In CS 5010, we want you to use the coding style and conventions described here. We have attepted to keep our conventions as simple as possible, consistent with making your code readable by the course staff and reusable by you. We have divided our guidelines into three groups:

General Guidelines

Design Guidelines

If you have been given a specification to implement, you are not allowed to change that specification. If you believe the specification is itself incorrect, you should ask the person(s) who gave you the specification to correct it.

In particular, you are not allowed to change the names, contracts, or purpose statements of functions or methods you have been asked to write. Rationale: Changing any of those things will prevent your code from working when it is combined with other parts of the program that rely on the given specifications.

Similarly, you are not allowed to change the definitions of any types defined by the specification.

Function and method definitions should be short. If you find yourself writing a long function or method, you should probably define one or more help functions that would allow you to write a shorter and clearer definition of that function or method. Rationale: Dividing a function or method body into smaller pieces not only makes the definition clearer; it also allows the pieces to be tested independently, making debugging easier.

When designing your own help functions and methods, each function or method should accomplish exactly one thing. Rationale: Functions and methods that try to accomplish several things at once will be harder to read, and they will also be harder to reuse as your program evolves.

Try not to recompute the same value(s) repeatedly. Rationale: Performing exactly the same computation multiple times is inefficient.

Don't write the same or similar code in multiple places. Rationale: If you find yourself writing similar code within two or more definitions, you should probably write a help function that accomplishes the common task and call that help function from within all definitions of functions and methods that need to accomplish the task.

Don't hard-wire magic numbers within your code. Although occurrences of 0 and 1 within your code will probably always be zero and one, other numerical constants may be subject to change as your program evolves. Rationale: Even if you think the numerical constant 3.141592653589793 is unlikely to change, multiple copies of that constant are less readable and more prone to editing mistakes than a symbolic name such as PI. Furthermore, the numerical value of pi might depend on the precision of your floating point hardware and libraries, which are more likely to change than you may realize.

Don't hard-wire any kind of magic constants within your code. That includes strings used to name the legal values of itemization data. Rationale: You may think repeating the string "red" throughout your program is just as readable as repeating the symbolic constant RED, but some future refactoring of your program might change the value of that constant to 0xf80000.

When the value of a boolean expression is being used to compute a boolean value, you don't need a conditional expression or statement. Example: (x > 0) ? true : false is equivalent to (x > 0), which is shorter and easier to read.

Naming Guidelines

Most programming languages are case-sensitive, but you should never use two different names in the same scope whose only difference is the casing of one or more letters. Even if your programming language is not case-sensitive, you should use consistent case for every reference to a name.

The larger the scope of a name, the more important it is to use a meaningful name. Example: An index variable whose scope is confined to a small for loop might well be named i, but using i as the name of a global or instance variable is ill-advised. On the other hand, names that are too long can be cumbersome. Some useful advice on choosing names is here.

When naming a function that has no side effects, the name of the function should be a noun that describes the information represented by the result of the function, possibly augmented by some succinct suggestion of the relationship between that result and (some of) the arguments. Example: When naming a function that returns the quotient of x and y modulo n, quotientModN is a better name than divideXbyY.

When naming a function or method that operates by side effect, its name should be a verb that describes the side effect. Example: When naming a method that converts its argument to a string and prints that string, print is a better name than asString.

Formatting Guidelines

Do not write any lines that are longer than 80 characters. Rationale: Long lines are harder to read. Long lines are especially hard to read if they wrap when the font size is increased to make your code readable when displayed by a video projector during code reviews.

Do not use any tab characters in your programs. Rationale: Tabs have no standard interpretation. Your organization may impose its own standard interpretation of tab characters, but tab characters can still make your code look weird when viewed by anyone who is using display software that hasn't been adjusted to match your organization's preferred interpretation. Example: In this course, we will use DrRacket, GitHub, and editors such as Emacs to examine your code. If your code contains tab characters, its indentation will change depending on the tool used to view it. If its indentation looks wrong when we view it, you will be criticized for improper indentation, and you will deserve that criticism.

Language-specific Guidelines

The Racket project has published its own style guidelines for programmers using Racket. For CS 5010, we ask you to follow the simplified guidelines listed below.

Functions that return a boolean are known as predicates. Their names should end with a question mark. Example: string?

Functions that do not return a useful value, so they are executed only for their side effects, should have names that end with an exclamation mark. Example: vector-set!

DrRacket's editor can indent your code for you. Even if you prefer to indent your code yourself, your indentation should be almost indistinguishable from the indentation suggested by DrRacket.

Every left parenthesis should appear at the beginning of a line, or preceded by another left parenthesis, or preceded by a space.

Right parentheses should not be preceded by a space, with one exception: the right parentheses that follow a long list of items, each indented individually, may be on a line by themselves, preceded by a space, and indented to line up with the items above them.

An if expression's test expression should begin on the same line as the if. Unless the if expression is very short, its then and else parts should each begin on separate lines.

Every cond clause should begin on a separate line. The first cond clause should begin on the same line as the cond. (Professor Wand's online materials often put the first cond on the following line. That's acceptable practice but I don't recommend it.) All subsequent cond clauses should begin on a new line, properly indented.

Course-specific Guidelines

Each file of code should start with a purpose statement explaining what the code is intended to accomplish.

The require declarations go next, followed by provide declarations.

Data definitions and global constant definitions belong near the beginning of a file.

Constant names should consist entirely of capital letters and hyphens. Example: INITIAL-VELOCITY.

Type names begin with a capital letter. If a type name is formed from two or more words, use CamelCase.

Structure and field names do not begin with a capital letter. They should look like variable names.

In variable names, use hyphens to separate words, not underscores or CamelCase.

Unit tests belong in the same file with the definitions they test. Short tests can be placed directly after the function(s) they test, where they can serve as examples. Longer tests can go near the end of the file.

Last modified: Mon Sep 18 17:12:11 Eastern Daylight Time 2017