ENGG1811 Style Guide

Overview

What is Style?

Programming style refers the set of guidelines used when writing code for a computer program. Following good style practices will help with the readability of your code, which allows us as markers to better understand what you are trying to achieve.

Style in ENGG1811

In this course, style is only assessed in assignments, however it is recommended that good style is used throughout your weekly lab exercises and exams as well.

How to use this guide

For assignments, all of the style described is mandatory. This means that in order to achieve full marks, you must adhere to all the requirements outlined in this guide.

Mandatory Style Guide

Code Layout

Use the following order when laying out your code.

"""
Purpose: Find the average of 3 numbers
Author: Alicia Shih
Date: 21/09/2022
"""
# Import modules
import math

# Constants are defined here
DEGREES_IN_CIRCLE = 360

# Remainder of code
print("Hello world!")

Docstring Contents

All programs should have a docstring comment. It must include the following elements:

The data dictionary should contain all the input, output, variables and constants defined and used within the function/file. It should include their datatype (float, string, int etc.), name as well as a short description of what the variable contains and its units.

"""
Purpose: To calculate the average of 3 numbers
Author:  Alicia Shih
Date:    21/09/2022
Method:  Sums up the 3 numbers and then divides the
         result by 3
Data dictionary:
 [float] number_1   The first number
 [float] number_2   The second number
 [float] number_3   The third number
 [float] average    The average of the 3 numbers
"""
"""
Purpose: To calculate the displacement of a particle
Author:  Tuyet Nguyen
Date:    13/09/2024
Method:  Uses the particle displacement equation
         s = ut + 0.5at**2
Data dictionary:
 [float] disp       displacement of the particle (m)
 [float] init_vel   initial velocity of the particle (m/s)
 [float] time       time interval of the particle's motion (s)
 [float] accel      acceleration of the particle (m/s**2)
"""

init_vel = 80
time = 30
accel = 9.81
disp = init_vel * time + 0.5 * accel * time ** 2

Constant Naming

Constants should be named in all uppercase.
Constants should be reserved for values that are either:

All other terms should be defined as variables.

GRAVITY = 9.81

Variables

Variable Naming

Variables should be named either using snake_case or camelCase, you can choose the case style that you prefer. Please ensure that you use only one case style in your code and do not use a combination of them. Note that both case styles start with a lowercase letter.

Descriptive variable names should always be used where possible. Variables should have meaningful names that indicate the value stored within them - a user should be able to read your code and understand it without the presence of your Data Dictionary. Short variable names such as x or i are acceptable if there is no appropriate long descriptive name (which is often for variables used as loop counters).

speed = 80
angle = 30

Declaring Variables

Variables should be declared when (or close to when) they are first assigned a value, and close to when they are first used.

# Do this
i = 0
for j in num_list:
    i += j

# Don't do this
i = 0
# ... lots of code not involving i ...
for j in num_list:
    i += j

Variables should also be initialised on separate lines

# Do this
x = 10
y = 8
z = 6

# Don't do this
x = 10 ; y = 8 ; z = 6

Loop Variables

It is recommended variables controlling while loops be declared before the loop and used only to control that loop.

i = 0
while i < threshold:
    # do something
    i += 1

It is recommended variables controlling for loops be declared as part of the for loop.

for i in num_list:
    # do something

Maximum line length

Keep lines under 80 characters. Note that this extends to docstrings and comments. Break up long lines to keep them under 80 characters unless keeping it as a longer line is significantly more readable. There are several methods for you to break a long line of code into multiple lines:

  1. Shortening variable names
  2. Code within () [] {} can be spread over multiple lines.
  3. Using the line continuation \ symbol

Line breaks should occur before the binary operator because this aims readability.

# Do this
sum = number_1 + number_2 \
      + number_3

# Don't do this
sum = number_1 + number_2 + \
      number_3

We want to point out that Spyder has a visual aid to tell you whether you are using long lines. The Spyder editor has a vertical line (see picture below) that indicates Spyder’s default 79 character limit. While you can still write code that extends beyond the character limit, good style practice includes writing short lines that are within the character limit.

Commenting

Comments should be used to describe, explain and/or justify code - they should not simply restate what the code is doing or the methods that the code uses. For example, there is no need to include comments such as "importing the Math library" or "making a for-loop". They should also be succinct and as short as possible. Comments should be accurate and agree with the code they describe. If you modify some existing code, you should ensure that the surrounding comments are still accurate.

Comments should also be written in-line with the code it is referencing. This is to ensure readability.

# Count is only increased if value is even
if value % 2 == 0:
    count += 1

    # increment two_count when value is equal to 2
    if value == 2:
        two_count += 1

Do not use trailing comments (i.e., comments which appear at the end of a line containing other code) unless the comment is very short and describes only the code that it appears next to.

# Do this

# Increase value of a until it equals b
if a != b:
    a += 1

# Don't do this

if a != b: # Increase value of a until it equals b
    a += 1

Code complexity

Ensure that your code is as simple as possible - don't use a long winded algorithm to do something simple.

Try to avoid extremely nested loops and logic. A good standard to go by is: if your code is more than three times nested, you should try to simplify some sections of your code.

# For example, instead of doing
a * d + b * d + c * d

# Do this
(a + b + c) * d

# And instead of doing
if condition_1 and condition_2:
    return 'invalid parameter'

if condition_3 and condition_4:
    return 'invalid parameter'

# Do this
if condition_1 and condition_2 or condition_3 and condition_4:
    return 'invalid parameter'

Repeated Code

Do not cut-and-paste code. The exact same lines of code should not appear twice in your program. You can avoid repeating code by defining a function and calling it instead of repeating the lines of code. This should be avoided because repeated code makes your program hard to read and difficult to modify.

Imports

Imports should be on separate lines.

# Do this
import numpy
import math

# Don't do this
import numpy, math

Indentation

Between any function, if/else, or loop statement, the indentation level should increase by 1 stop. This is either one tab or four spaces.

# Indentation increases by 1 tab/four spaces
for i in num_list:
    print(i)

The arguments of long function calls should be aligned if they span over multiple lines.

# Function arguments are aligned here
if something and something_else and something_else_again \
   and another_thing and too_many_things_here:
       print(1)

Spacing

Include a space on each side of binary operators such as:
= + - * / // % < > <= >= == !=

Include a space on each side of Boolean operators such as:
and or not

Include a space before open brackets and after closing brackets:
if (a == b) and (b == c)

Include a space on each side of compound operations such as:
+= -= *= /=

# This is correct
if (a == b) and (b == c):
    a = b + c
    b += 1

# This is not correct
if (a==b)and(b==c):
    a=b+c
    b+=1

Avoid adding spaces in between each time of code as it makes code appear scattered and harder to read. Lines of code should be logically grouped together if they contribute to the same purpose or functionality. Spaces should only be added between lines of code to indicate that the code section is now performing a different aspect of the calculation or functionality than the previous code block.

# Don't do this
if (a==b)and(b==c):

    a=b+c
    
    b+=1

# Do this

# Group 1: Defining initial variables
x = 10
y = 5

# Group 2: Performing some basic arithmetic operations
sum_result = x + y
difference = x - y
product = x * y
quotient = x / y

# Group 3: Displaying Results
print("Sum: ", sum_result)
print("Difference: ", difference)
print("Product: ", product)
print(f"Quotient: ", quotient)

Functions

Function Comments

Every function must have a comment placed before the function implementation describing the purpose of the function and any side-effects the function has. Note: You do not need to do this for functions that have already been provided to you.

# Return quotient of all values in list
# Returns None if there is division by zero
def quotient(num_list):

Function Names

Function names should be descriptive, typically containing multiple words.
Names for most functions should be in snake_case. This should be consistent with your style for variable names.

Return

Do not overuse return statements. You should only use multiple returns only if this makes your function less complex or more readable.

For example, it is acceptable to have an early return statement(s) to handle error conditions or special cases, as well as another return statement for the computation of the function's main result.

# early return statement handing error condition
if a % 2 == 0:
    return ‘Error’

# computation of function’s main result
x = a - b
return x