Systems do not become complex. They accumulate complexity — one reasonable decision at a time — until no single person can hold the whole in their head.
Dead code, unreachable branches, and obsolete paths accumulate as geological layers
If understanding a single change requires understanding the entire system — if a class handles responsibilities that span multiple domains — if code exists that no one can explain but no one dares remove — complexity has accreted past the point of comprehension.
Every codebase experiences this. The force driving accretion is time itself — combined with changing requirements, changing teams, and the economics of "just add it here." Refactoring is expensive. Accretion is free. Until it isn't.
GOTO spaghetti (1960s) evolved into God Objects (1980s). The mechanism changed from unstructured control flow to unstructured responsibility, but the result is the same: systems too complex to comprehend
GOTO-heavy code accumulates unreachable branches because no one can trace the control flow well enough to identify what's dead
Year
1957–1968
Context
In the first decade of high-level programming, there was one control flow primitive: GOTO. FORTRAN (1957) had GOTO, computed GOTO, and assigned GOTO. COBOL had GO TO and ALTER (which changed where a GO TO pointed at runtime). Assembly, of course, had only jumps. Every program was a graph of numbered statements connected by explicit jumps. There were no if/else blocks, no while loops, no functions that returned to their caller by contract. There was GOTO.
Who Built This
Everyone. GOTO was not a bad practice adopted by lazy programmers. It was the only mechanism available. The languages provided GOTO because the hardware provided jumps. The abstraction matched the machine. Writing a sorting algorithm in FORTRAN II meant writing a sequence of numbered statements with GOTO instructions connecting them. The resulting control flow graph — if anyone had drawn it — would have looked like a plate of spaghetti.
Threat Model at Time
Correctness. Programs needed to produce the right output. The concern was not maintainability — programs were short, teams were small, and the programmer who wrote it was usually the programmer who maintained it. The idea that code needed to be readable by someone other than its author was years away.
Why It Made Sense
GOTO was efficient. It mapped directly to machine instructions. It was flexible — any control flow pattern could be expressed with GOTO. It required no runtime overhead. And it was the only tool available. Dijkstra himself used GOTO extensively in his early work. The problem was not that GOTO existed. The problem was that nothing else did.
This pattern has been found in applications built by talented developers at respected organizations across every decade of software history. Its presence in a codebase is not a reflection of the developer who wrote it — it is a reflection of what that developer was taught, what tools they had, and the path that was easiest given what they were taught. The goal is not to find fault. The goal is to find the pattern — before it finds you.
Katie's Law: The developers were not wrong. The shortcut was not wrong. The context changed and the shortcut didn't.