CSCI 265 project standards (code, documentation, and processes)

All code submitted as part of the project is expected to adhere to the set of code standards described below. Failing to adhere to these standards can result in substantial loss of marks.


General Standards

Note that, although most of the examples below are shown in C++, these standards apply to all items within your project, not just the C++ files for the end product.

The standards below are not exhaustive: students are expected to follow sound software engineering practices and exercise good judgement and common sense throughout the development process - following poor processes or generating low quality code can still result in loss of marks even if it does not violate any specific guideline listed below.

development environment and version control
All development is to be carried out through the xxxx.csci.viu.ca machines (the cubs or pups) in your project git repository. If you wish to work from your laptop or other device then so so by connecting to csci.viu.ca then jumping to one of the cubs/pups.

All deliverables are to be tracked in your project repository - i.e. all code, all support scripts, all makefiles, all documentation, all test files.

Commit regularly, providing clear and informative messages with each commit.

Each commit must represent a small, logically cohesive unit of change. (Don't add multiple different elements of functionality, or multiple different bug fixes, into the same commit.)

The code in each commit should adhere to standards (i.e. follow standards as you write the code, don't retrofit to follow them later).

Avoid indiscriminate use of "git add .",
instead, specifically identify the files to be added.

compilation and execution
Your project code must be written in C++ and must compile cleanly - meaning no errors and no warnings - when compiled on the cubs/pups (xxxx.csci.viu.ca) using the -Wall -Wextra options of the g++ compiler.

Code that generates errors/warnings is not trustworth: no warning is too small to ignore.

Support tools will use a combination of C++, bash, and makefiles. Any C++ programs must also compile without errors or warnings with -Wall and -Wextra under g++.

Warnings and error messages generated by your programs should be directed to the stderr output stream, not stdout.

All programs and scripts must run without crashes and without generating runtime bash/C++ warnings/errors. (You are expected to be able to tell the difference between errors generated by bash/C++ and your programs' own output error messages!)

attribution of others' work
You are free to use the following without need for attribution:
  - code provided by the instructor through the course lecture notes, lab notes and repositories, and project notes and repositories,
  - code developed by you for this year's CSCI 265 project or labs.
Code and solutions from any other source (including your own work from other courses or independently) must be clearly attributed in your code and supporting documentation.

input error checking and sanitization
Appropriate error checking should be applied to all input data, preferably as soon as possible after the data is read.
In the event that user input (or parts of it) is used to build system/shell commands, that input must be sanitized to reduce the risk of exploits.

program output
All prompts for the user should give the user a clear idea of what the program is doing, and (for user input) should give the user a clear idea of the input format/range expected, e.g.
"Please enter the circle radius as a real number, e.g. 5.25"
as opposed to something like "Enter value"

All error messages should give the user a clear and concise view of what went wrong, e.g.
"Out of range value entered: 32 (should be an integer in range 1-19)"
as opposed to something like "Bad value"

All program results should be displayed in a way that explains their context, e.g.
"For the circle of radius 5, the computed circumference was 31.4"
as opposed to something like "Result 31.4"

identifiers
All identifiers (variables, constants, functions, parameters) must have clear and meaningful names, that reveal their intended purpose to the reader. For example, circleRadius is immediately clearer and more meaningful to the reader than R or cR.

comments
all files should begin with a comment describing the file content

When deciding on an appropriate level of detail for comments, think of what is needed to make the code clear to a peer who is unfamiliar with the particular program/project. In our case, think of it as if it were being read by a past CSCI 265 student and ask yourself "What explanation would they need to make the code clear and maintainable?".

All variables used in a program should have a brief comment indicating their purpose. In some cases a single comment can be used to describe a group of closely related comments, e.g.
   // variables to hold the three polynomial coefficients
   float a, b, c;
Logical blocks of code within the program should have a brief comment indicating their general purpose, e.g.
   // prompt the user to enter the polynomial coeffients and
   // read them in, assume they are seperated by whitespace
   printf("Please enter the degree 2 coefficient,\n");
   printf("followed by the degree 1, then the degree 0:\n");
   scanf("%g\n", &a);
   scanf("%g\n", &b);
   scanf("%g\n", &c);

layout
You are expected to use clear and consistent indentation, either three or four spaces (not tabs), for all blocks within your code.

Line widths: no line of code or comments in the program may be wider than 96 characters.

identifiers
You may chose any naming convention you wish (subject to the limitations below), but you must use it consistently within your project.

All names used in the program (variables, functions, parameters, constants, etc) must be meaningful - i.e. they must clearly represent the purpose of the item named, and distinguish it from other named items in the program.

For example, userInitial would be a much more meaningful identifier than i, and fuelLevel would be a much more meaningful identifier than data.

constants
With the possible exceptions of 0, 1, and 2, there should be no hard-coded numeric or character literals within the program. Instead, these values should be replaced with the use of constants whose scope covers all uses of the value.

For example, instead of the hard-coded value 3.1415 in the statement:
circumf = 3.1415 * radius;
we would introduce a named constant, e.g.

    const float Pi = 3.1415;
    .......
    circumf = Pi * radius;
Similarly, if we have meanings associated with specific characters in the program they should be represented with constants.

For example, if we have the user enter Q to quit or C to continue, we might use:

    const char QuitCmd = 'Q';
    const char ContCmd = 'C';
    ...
    printf("Enter %c to quit or %c to continue\n", QuitCmd, ContCmd);

file I/O
Each program is responsible for explicitly closing every file it successfully opened, under all circumstances.

functions, methods, and top-down design
Code segments that are used repetitively should be abstracted into functions to simplify maintenance and reduce code clutter.

To improve readability, lengthy sequences of code statements should also be divided into logical blocks, each of which is abstracted into a function.

An easily-followed top-down design approach should be followed.

Each function must have a prototype in the associted header file.

The full implementation of the function should generally be accompanied by a more detailed set of (implementation specific) comments than the call-focused comments in the header file.

The layout of a function is much like the layout of main, e.g.
void myfunction(int someparameter)
{
   .....
   all this is indented 3 spaces
   .....
}

Functions should not use reference parameters unless they actually need to change the value of the parameters.

If a function returns a value then that value should be meaningful and should be checked appropriately upon return.

goto, break, continue
These statements should be used sparingly, if at all. Normal flow of control should not be violated without a compelling reason.


*** C++ SPECIFIC STANDARDS ***

array sizes
Array sizes (for statically-allocated arrays) must be constants or constant expressions, not variables.
E.g. the following is not acceptable under the standard:
void doSomething(int arr[], int size)
{
   int someLocalArr[size];  // size is NOT a constant
   ...
(This won't apply to arrays that are dynamically-allocated using the "new", "malloc", or "calloc" operators, as discussed at the very bottom of this page.)

dynamic memory allocation
All dynamically allocated memory must be appropriately freed before the program exits - i.e. anything created using new must be deallocated using delete.

Anytime a dynamic memory allocation takes place, the location provided by the call to new must immediately be checked to ensure it is not null, and appropriate action taken if it is null.

header files
All .cpp files should have a matching .h file

Header files must always have appropriate guards (#ifndefs)

All type definitions (including enums, structs, classes, etc) belong in a .h file

All function and method prototypes belong in a .h file

No variable declarations should appear in a .h file

class definitions
All classes must declare a default constructor and destructor

Classes must use an appropriate division of public, protected, and private, and should limit the use of public accessors

namespaces
Do not globally use namespaces (i.e. avoid "using namespace std"), instead identify the specific elements needed from the namespace.


*** BASH SPECIFIC STANDARDS ***

quotes, expansion and substitution
Use ${var} rather than $var.

Always quote strings containing variables and command substitutions, e.g. "${x}" rather than simply ${x}. The exception to this is where the variable is expected/needs to expand into multiple separate words, e.g.
for oneword in ${sentence} ; do
Note that globs should not be included within the quotes, e.g. correct use would be something like
for file in "${dir}"/* ; do

Never quote literal integers.

Use $(command) instead of backticks.


*** MAKEFILE SPECIFIC STANDARDS ***

debugging targets
All C++ programs should be supported by a makefile target, e.g. projectx, and should also have a debugging target, e.g. projectd.

The debugging target should use the -g flag, while the "normal" target should disable asserts with the -DNDEBUG flag.

The .o files compiled for the debug versions should thus be stored separately from the .o files compiled for the "normal" versions.

wildcards and variables
Avoid the use of wildcards in remove commands.

Use variables for lists of names, for lengthy paths, or for values that are likely to change as the project progresses.

input/output
Use @echo, rather than echo, within makefiles.

Avoid the use of read in makefiles.


*** DOCUMENT SPECIFIC STANDARDS ***

file format
Plain text file formats are required for all documentation files. (i.e. no .pdf, .doc, .docx, .rtf, etc)

grammar, spelling
The use of correct spelling, punctuation, and grammar is expected in all supporting documentation for the project.