◇ OpenCyber Academy
Bachelor's · Chapter 3 · English

Chapter 3 — Programming I

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

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

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) →