Unit 01.02: What a graph costs you in complexity
Graph tutorials show what a graph buys. It is worth being equally explicit about what it costs, because the cost is paid on every future change.
Two paths instead of one
The same work - fetch, summarise, save - expressed as a list and as a graph with a failure branch. The code counts what each shape asks you to hold in your head.
Look at the transition count, not the node count. Transitions are what you have to test.
# The same work, two ways. Count what you have to hold in your head.
linear = ["fetch", "summarise", "save"]
graph_edges = [
("START", "fetch"), ("fetch", "check"),
("check", "summarise"), ("check", "fail"),
("summarise", "save"), ("save", "END"), ("fail", "END"),
]
print(f"linear: {len(linear)} steps, {len(linear)} transitions, 1 path")
nodes = {n for e in graph_edges for n in e}
print(f"graph : {len(nodes) - 2} nodes, {len(graph_edges)} transitions, 2 paths")
print("""
What the graph buys: a failure path that does not crash the run, and a place
to add a human step later.
What it costs: every node needs its own tests, every edge is a decision you
have to justify, and state is now shared mutable data across all of them.
Pay that cost when you need branching, cycles or pausing. Not before.
""")
Three steps and three transitions become four nodes and seven transitions for one added failure path. Every one of those transitions is a decision someone can get wrong, and every node needs its own test.
What you get for it is real: a failure that produces a handled outcome instead of a stack trace, and somewhere to put a human step later. Whether that is worth doubling the transition count depends entirely on whether failures currently crash the run.
The mistake this prevents
The mistake is treating the graph as free because the library makes it easy to add nodes. Adding a node is easy; the cost lands later, when someone has to reason about which of seven transitions produced a state they did not expect. Count transitions before adding branches.
Takeaway
A graph buys branching, cycles and pausing, and charges you in transitions - each of which is a decision to justify and a path to test. Pay when you need what it buys, not before.
