Chapter 3 — Programming I
Lesson map
Lesson 03 published. Map, example, EX007.
flowchart TD
N0["Learning outcomes"]
N1["3.1 Why program"]
N2["3.2 Basic constructs"]
N3["3.3 Reading files"]
N4["3.4 Testing"]
N5["3.5 Readability"]
N6["3.6 Handling errors"]
N7["3.7 Keeping code"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX007"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["3.1 Why program"]
N2["3.2 Basic constructs"]
N3["3.3 Reading files"]
N4["3.4 Testing"]
N5["3.5 Readability"]
N6["3.6 Handling errors"]
N7["3.7 Keeping code"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX007"]
[Learning outcomes]
|
v
[3.1 Why program]
|
v
[3.2 Basic constructs]
|
v
[3.3 Reading files]
|
v
[3.4 Testing]
|
v
[3.5 Readability]
|
v
[3.6 Handling errors]
|
v
[3.7 Keeping code]
|
v
[Worked example] --> [Exercise EX007]
Learning outcomes
You will (1) write short programs that read and count records; (2) use loops, conditions and dictionaries; (3) test programs on small known inputs; (4) write readable, commented code.
3.1 Why program
Analysts often ask questions no dashboard answers: "How many students received the phishing email per faculty?" A short program answers it reliably and can be rerun.
The recipient export for the library-fines email listed every delivery attempt, so counting rows would have overstated the number of people reached. Lucas's program de-duplicated by recipient and found 6,980 unique accounts. The same script ran again unchanged when a second export arrived the next day, which a manual count in a spreadsheet would not easily allow.
3.2 Basic constructs
Variables hold values; loops visit each record; conditions test fields; dictionaries map keys such as faculty names to counts. These four ideas solve most counting tasks.
Lucas's per-faculty counter uses all four: a dictionary called faculty_counts starts empty, a loop reads each recipient row, a condition checks whether the faculty field is present, and the matching count is increased by one. The whole program is under twenty lines, short enough for Dr. Kim to read before trusting its output.
3.3 Reading files
Exports arrive as CSV files. Python's csv module reads them into dictionaries keyed by column name, avoiding fragile string splitting.
The mail service's export quoted some faculty names because they contained commas, such as "Arts, Humanities". Splitting each line on commas would have broken those names into two fields and shifted every column after them. The csv module handles the quoting, so Lucas's counts were correct without any special code for awkward names. He also reads the file with an explicit encoding, since some names contain accented letters.
3.4 Testing
Before running on the real export, Lucas writes a five-line test file where he knows the answer: two students in Law, three in Engineering. If the program prints anything else, the program is wrong.
His first run on the test file printed three for Law, because the program counted the header row as a student. Fixing that took one line. Had he run the untested program on the real export, the error would have been hidden among thousands of rows and might never have been noticed.
3.5 Readability
Clear variable names (faculty_counts, not fc) and a comment stating intent help Dr. Kim and other students review his code.
When a fellow student analyst picked up the script during a later shift, the names and a one-line comment saying "count unique recipients per faculty" were enough for them to use and adapt it without asking Lucas. Code that only its author can understand becomes useless as soon as that person is off duty or graduates at the end of the year.
3.6 Handling errors
Some rows lack a faculty field. Lucas counts them under "unknown" instead of crashing, and prints how many there were.
In the phishing export, 112 rows had no faculty, mostly shared mailboxes and recent staff hires. Reporting that number told Dr. Kim how much of the data the faculty breakdown did not cover. A program that silently skipped those rows would have produced totals that did not add up to 6,980, without explaining why. Unknowns are a finding, not a nuisance, and they shrink as records improve.
3.7 Keeping code
Scripts are stored in the SOC's shared repository with a short description.
The description states what the script does, what input it expects and its known limits, such as treating shared mailboxes as unknown. Storing it in the shared repository means the next campaign can reuse it, and any change is recorded with the author and date. Scripts kept only on a student's laptop are lost when the student graduates, and nobody can check how an old figure was produced.
Rerunning analyses
Because the script is saved, Lucas reruns it the next morning on a fresh export and sees 1,140 additional recipients from a second wave of the campaign. A manual count would have needed repeating from scratch; the script took seconds and its earlier output stayed as a record.
Worked example
Lucas's first version counts 7,412 recipients. His test file passes, but the total seems high. He discovers duplicates: the export lists one row per delivery attempt. He de-duplicates by recipient address and gets 6,980 unique recipients.
Synthetic case. Code and counts are invented.
Errors and limits
A program that passes a small test can still mishandle unusual real data; check totals for plausibility.
Exercises
- EX007 — Four constructs. Name the four basic constructs used for counting tasks. Rubric: 3 = variables, loops, conditions, dictionaries; 2 = three; 1 = one; 0 = none.
- EX008 — Missing fields. How should missing faculty fields be handled? Rubric: 3 = count as unknown, report how many, do not crash; 2 = partial; 1 = crash; 0 = none.
- EX009 — Duplicate count. Why was the first total too high, and what fixed it? Rubric: 3 = one row per delivery attempt; de-duplicate by recipient; 2 = partial; 1 = ignored; 0 = none.
Synthesis
Small, tested, readable programs answer questions dashboards cannot, as long as results are checked for plausibility.
Continue studying — chapter 03 of 40
← Chapter 02 (draft) · Course chapter index · Chapter 04 (draft) →