Codebase Conventions

This document aims to explain some of the common conventions found within the Song Match codebase.

Design Patterns

The Song Match codebase is almost entirely object oriented. There are many design patterns relating to object oriented programming (OOP) found throughout the codebase.

Wrapper Objects

The first design pattern you’ll see are our use of wrapper objects. A “wrapper object” is an object that takes an already instantiated object in it’s constructor and extends it’s functionality through custom methods.

More formally this is known as the Decorator Pattern because your decorating an object by wrapping it and adding behavior.

Common objects from the Cozmo SDK, like the objects representing Cozmo and the cubes, have a corresponding wrapper object in the Song Match codebase:

Many methods and properties of the wrapper objects match the corresponding wrapped object. For example, both NoteCube and LightCube have a set_lights method. The set_lights() method in NoteCube simply calls set_lights() on the internal LightCube object.

# note_cube.py

def set_lights(self, light: Light):
    self._cube.set_lights(light)

Object Creation Patterns

Static Factory Methods

A static factory method is a static method used for creating an object.

There are two static factory methods in the codebase. Both are methods named of, a concise naming convention for static factory methods popularized by EnumSet in Java. See How to name factory like methods? for more details.

Factories

A factory is an object for creating other objects.

In our codebase there is one factory, EffectFactory .

EffectFactory creates our various game effect subclasses:

Inheritance

We favor composition over inheritance and avoid complex class hierarchies.

No class extends an instantiable class, but there are two abstract base classes:

  • Effect - Abstract base class for various game effects
  • Song - Abstract base class for various songs

Public, Protected, and Private

Python lacks access modifiers like private and protected found in languages like Java and C#.

We follow the convention of preceding private methods and attributes with two underscores. For example:

def __some_private_method():
    pass

protected methods and attributes are preceded with a single underscore.

def _some_protected_method():
    pass

If you see anything that begins with a underscore, then it means don’t use it outside of that class or module.

In general, all public members in Song Match have docstring comments, while private and protected members do not.

Our API reference includes only public members.

Type Hinting

In general, all functions and methods are type hinted. Below we see a function that adds two int values together, and returns an int.

def add_two_numbers(a: int, b: int) -> int:
    return a + b

See support for type hints for more details.

Style Guide

We follow Python’s official style guide PEP 8.