Your program will be used by real people: some careless, some confused, a few actively hostile. Defensive design means writing code that expects the worst — anticipating misuse, checking everything that comes in, and failing safely when something goes wrong — instead of assuming everyone will do exactly what you hoped. It is the difference between a program that works in a demo and one that survives contact with the real world.
You have already met its front line:
A cornerstone technique is the guard clause — a check at the very top of a function that rejects bad input immediately, before any real work happens. Compare a naïve function with a defensive one. Press Run:
The naïve version happily divides by zero for an empty list, producing a nonsense value — a bug that will surface far away, in some other file, long after the real cause. The defensive version stops the bad data at the front door and says exactly what was wrong.
In 1996 the maiden flight of the Ariane 5 rocket self-destructed 37 seconds
after launch. The cause? A number too large to fit in the variable it was being squeezed into —
an unchecked conversion that a single guard clause would have caught. The undefended line of code
cost around