Functions – How to Write Good Functions

Writing good functions requires an understanding of how functions work as well as lots of practice. It is important to think  through how the function will interact with the rest of the code. In this post, we offer examples of functions and guidelines about what to do and what not to do when writing functions. We also include a video that illustrates some of these function-writing conventions.

Students will produce code of a wide range of quality. Even when code runs and works as specified, it can be of poor quality.

The following code contains a function computing the area of a circle, a function computing the area of a rectangle, and a function computing the distance between two points (which is invoked by both area computing functions).  The functions in the file are shown below:

from __future__ import print_function
import math

## compute and return the distance between points (x1,y1) and (x2,y2)
def computeDistance(x1, y1, x2, y2):
    diffx = x2 - x1
    diffy = y2 - y1
    result = math.sqrt(diffx**2 + diffy**2)
    return result

## compute and return the area of a circle given the coordinate
## of the center (xc,yc) and one point on the perimeter(xp,yp)
def computeCircleArea(xc, yc, xp, yp):
    radius = computeDistance(xc, yc, xp, yp)
    result = math.pi * radius**2
    return result

## compute and return the area of a rectangle given the coordinates
## of two corner points on opposite ends of one diagonal,(xl,yl) and(xr,yr)
def computeRectangleArea(xl, yl, xr, yr):
    length = computeDistance(xl,yl,xr,yl)
    width = computeDistance(xl,yr,xr,yr)
    result = length * width
    return result

The following block contains code that might have been written by a student.

from __future__ import print_function


def fun(xc, yc, xp, yp):
    radius = d(xc, yc, xp, yp, xc)
    result = 3.14 * radius * radius
    print(result)
    return result

def ar(xl, yl, xr, yr):    
    length = d(xl,yl,xr,yl,xr)
    width = d(xl,yr,xr,yr,xr)
    area = length + width
    print(area)
    return area

## computes the distance
def d(a,b,c,d,e):
    return ((c - a)*(c - a) + (d - b)*(d - b))**0.5

def ar(xl, yl, xr, yr):    
    v1 = d(xl,yl,xr,yl,xr)
    v2 = d(xl,yr,xr,yr,xr)
    v3 = v1 * v2
    return v3

px = 0
py = 0
qx = 5
qy = 0

foo = fun(px,py,qx,qy)
print(foo)
    
zoo = d(px,py,qx,qy,0)
print(zoo)

print(ar(0,0,5,5))

The code executes correctly, but it violates many of the recommendations on how code and functions should be written. These include:

  • names of functions say little about what each function does and returns
  • there are no comments describing the functions
  • the value of pi is hard coded as 3.14 (math.pi should be used)
  • function d computes the distance between two points. It has 5 arguments, but only 4 are used
  • the expression in the return statement in function d would be more readable if first assigned to a variable (which is returned).
  • function ar appears twice; the first definition is incorrect and is not executed when the program is run sincePython uses the definition preceding the call
  • the choice of variable names is poor
  • it would be good to place function d before the functions using it
  • function ac contains a print statement (probably left from testing it)

In addition to the poor practices, the following are considered poor practices leading to confusing code that is hard to debug:

  • Too many return statements.
  • Function calls another function to do a small task that is unlikely to be re-used in other functions.
  • I/O in a function.
    In general, input and output should be done in the main. If there is I/O in a function, it should be clearly explained and justified in the comments.

The following video demonstrates good function writing conventions and styles. Video Length: 8:55