The ease with which other people can read and understand a program — often called readability in software engineering — is perhaps the most important quality of a program. Readable programs are used and extended by others, sometimes for decades. Programs are written to be read by humans, and only incidentally to be interpreted by computers.

A program is composed well if it is concise, well-named, understandable, and easy to follow. For Hog, a member of the course staff will review your submission and assign a composition score out of 3 points. This score applies to the project as a whole, not to individual questions.

Excellent composition does not mean adhering strictly to a prescribed style. There are many ways to program well, just as there are many styles of effective communication. The principles below universally lead to better programs.

Names

To a computer, names are arbitrary symbols — xegyawebpi and tally are equally meaningful. To humans, comprehensible names aid immensely in understanding programs. Choose names for your functions and variables that indicate their use, purpose, and meaning.

# Poor naming
def f(x, y):
    return x if x % 2 == 0 else x * 3 + 1

# Better naming
def hailstone_step(n):
    return n // 2 if n % 2 == 0 else 3 * n + 1

Functions

Functions are our primary mechanism for abstraction. Each function should ideally have a single, well-defined job that can be reused throughout a program. When given the choice between calling a function or copying and pasting its body, always call the function.

If you find yourself writing the same logic in two places, that is a signal to extract it into a helper function.

Purpose

Each line of code in a program should have a purpose. Remove statements that no longer have any effect — perhaps they were useful during an earlier version but are now dead code. Large blocks of unused code, even when commented out, are confusing to readers.

# Don't leave this kind of thing in your final submission:
def take_turn(num_rolls, opponent_score, dice=six_sided):
    # result = old_implementation(num_rolls)  # old approach
    # if result == 0:                         # no longer needed
    #     return 1
    "*** YOUR CODE HERE ***"

Brevity

An idea expressed in four lines of code is often clearer than the same idea expressed in forty. You do not need to minimise the length of your program at all costs, but look for opportunities to reduce size by reusing functions you have already defined.

For example, if take_turn is already correct, your play function should call it — not re-implement its logic inline.

How Composition Is Scored

Score Description
3 Code is clean, well-named, and easy to follow throughout. No dead code, no unnecessary repetition.
2 Mostly readable with minor issues — a few unclear names, small redundancies, or leftover debug code.
1 Readable in parts but with significant composition problems — poor naming, repeated logic, or confusing structure.
0 Difficult to read. Submission shows little attention to readability or code quality.