Skip to main content
Back to module
Python Fundamentals · Mini Project

Planning a small program

Reading57mLesson 2 of 3 in this module

Turn a vague idea into inputs, outputs, functions, pseudocode and test cases before writing code.

Why it matters

The most common reason a beginner project stalls is not a hard bug. It is starting to type before knowing what the program should do. Ten minutes of planning on paper saves hours of rewriting, and the plan doubles as a checklist that tells you when you are finished. Professional developers plan too; they just call it requirements, design and test cases.

Step 1: write the problem in one or two sentences

Be specific about who uses it and what they get:

A lab technician has a CSV of sample masses from three balances. The program should report the mean and range for each balance and flag any sample more than 0.5 g from its balance's mean.

If you cannot write this sentence, you are not ready to code. Vague goals ("analyse the data") lead to programs that never feel done.

Step 2: pin down inputs and outputs

Write out a tiny, concrete example of each, by hand:

Input (masses.csv):

balance,sample,mass_g
B1,S-01,12.40
B1,S-02,11.80
B2,S-03,12.10
B1,S-04,13.10

Output:

B1: n=3 mean=12.43 range=11.80-13.10
B2: n=1 mean=12.10 range=12.10-12.10
FLAG B1 S-02 11.80 (0.63 from mean)
FLAG B1 S-04 13.10 (0.67 from mean)

Working out the expected output by hand is the single most valuable planning step. It forces you to decide the details (how many decimals? sorted how? what counts as "more than 0.5 g"?), and it becomes your first test.

Step 3: list the edge cases

Ask "what could be weird about the input?":

  • An empty file, or a file with only a header.
  • A mass that is blank or n/a.
  • A balance with only one sample (range is zero; can a sample be flagged?).
  • Extra spaces or different capitalisation (b1 vs B1).

Decide what the program should do for each. "Skip and count it" or "stop with a clear message" are both fine; pick one deliberately.

Step 4: break it into functions

Each function should do one job you can describe in a sentence, with clear inputs and outputs. Write the signatures before any bodies:

def read_rows(path):            # -> list of dicts from the CSV
def parse_mass(text):           # -> float, or None if unusable
def group_by_balance(rows):     # -> {balance: [(sample, mass), ...]}
def summarise(groups):          # -> {balance: {"n", "mean", "min", "max"}}
def find_flags(groups, summary, limit=0.5):  # -> list of (balance, sample, mass, diff)
def format_report(summary, flags):           # -> str

Notice the pattern from the previous lesson: read, parse, group, summarise, report. Most small data programs fit it.

Step 5: write pseudocode

Pseudocode is the plan written in plain language, structured like code but without worrying about syntax:

for each row in the file:
    mass = parse the mass text
    if mass is unusable:
        add 1 to the skipped count
        skip to the next row
    add (sample, mass) to that balance's list

for each balance:
    mean = average of its masses
    for each sample in the balance:
        if the distance from mean is more than 0.5:
            add it to the flags list

If a step in your pseudocode is fuzzy ("work out the flags somehow"), that is where you will get stuck while coding. Break it down further now.

Step 6: write the tests first

Turn your hand-worked example into checks before writing the functions:

assert parse_mass("12.40") == 12.4
assert parse_mass("n/a") is None
assert parse_mass("") is None

groups = {"B1": [("S-01", 12.4), ("S-02", 11.8), ("S-04", 13.1)]}
summary = summarise(groups)
assert round(summary["B1"]["mean"], 2) == 12.43

These fail at first, because the functions do not exist yet. That is the point: each one you make pass is visible progress, and when they all pass, you are done. This habit is the core of test-driven development, and it is exactly how the Do tab in this course works.

Step 7: build one function at a time

Implement the smallest function first (parse_mass), run its tests, then move to the next. Resist writing everything and running it once at the end; when that fails, you will not know which part is wrong. Commit or save a copy each time a function works.

Scope: what is in version 1?

Write down what you are not doing yet: no charts, no command-line options, no Excel files. A small program that works and is shared beats a big one that is half finished. Put extra ideas in a "later" list in your README.

Common mistakes

  • Coding before you can state the problem. Write the sentence first.
  • Skipping the hand-worked example. Without it you have nothing to test against.
  • Giant functions. If you cannot describe a function in one sentence, split it.
  • Ignoring edge cases until they crash the program. List them in the plan.
  • Scope creep. Finish version 1 before adding features.

Quick recap

  • State the problem in one or two specific sentences.
  • Work out a small input and its expected output by hand.
  • List the edge cases and decide how to handle each.
  • Break the work into small functions with clear signatures, then write pseudocode.
  • Write tests from your example first, then build and test one function at a time.

Try it

In the Do tab you will plan a small program of your own (or the grades analyser) on paper or in a text file, following these steps.

Also in this lesson: