In How To Design Programs, one of the methods used to create functions and approach complexity is to (paraphrasing) “wish for” a specific functionality, assuming it exists prior to implementing it. For example, let’s say I’m writing a function that returns the sum of the surface area of two shapes. To start with, I can write the following:
def add_surface_areas(shape1: Shape, shape2: Shape) -> int:
...I know from that signature that I will write a function which takes two Shape objects and will return an integer value1. The next step is to simply define how that function will work:
def add_surface_areas(shape1: Shape, shape2: Shape) -> int:
return surface_area(shape1) + surface_area(shape2)
# Alternatively, if `Shape` has or will have a surface_area attribute
def add_surface_areas(shape1: Shape, shape2: Shape) -> int:
return shape1.surface_area() + shape2.surface_area()At this point we might have not written a surface_area() function or method anywhere and we can happily expect the code to yell at us about it. the specific technique, if I may, is that when writing the call to surface_area() when we know it doesn’t exist is to immediately write a stub for the function to create it later. In other words, when writing add_surface_area() assume that surface_area() exists insofar as the enclosing function is concerned. Just make note of the new functions required2
def add_surface_areas(shape1: Shape, shape2: Shape) -> int:
return surface_area(shape1) + surface_area(shape2)
...
# Somewhere else
def surface_area(shape: Shape) -> int:
# TODO
passFootnotes
-
Assume the
Shapedefinition exists elsewhere in the program. ↩ -
I think this might not be too different from the process I use in Obsidian. I write a note and use a
[[]]link to something else; if it doesn’t exist, the stub is created and it can be done down the line. It is also the “happy path” approach I like to use for some functions: the simplest version of a function is to assume it will return without errors; then, incrementally add error handling. ↩