Correctness is necessary but not
sufficient for safety.
To be safe, a program must not only run correctly. It must
apply defense-in-depth and verify itself while running, to run
correctly or else shut down if it detects that it has violated
expectations.
TigerStyle follows the spirit of NASA's Power of Ten Rules for Safety-Critical
Code by Gerard J. Holzmann. For example, static allocation,
assertions and explicit limits.
Read the Original Rules,
which will change the way you code forever.
“The rules act like the seat-belt in your car: initially they
are perhaps a little uncomfortable, but after a while
their use becomes second-nature and not using them
becomes unimaginable.”
— Gerard J. Holzmann
Put a limit on everything because everything has a limit.
Bound all resources, all concurrency, and all execution.
Avoid recursion. Bound loops and queues to detect
infinite loops and latency spikes.
Use fixed types like u32. Avoid architecture-specific
types like usize.
Allocate all memory at startup. Don't allocate after
initialization.
This centralizes and simplifies resource management,
solves fragmentation, forces you to think through “the
physics of the system”, and leads to an elegant design,
with efficient, predictable performance.
Where types check structure, assertions check all logic
and state, to detect programmer error, multiply fuzzing,
and downgrade catastrophe. Assert arguments,
returns, and invariants: what you expect and don't
expect, the positive and negative space, not only
contract but breach.
The safety (as well as performance and experience) of
a system is dominated by the quality of its interfaces.
- Minimize surface area.
- Define fault models.
- Abstract physical non-deterministic interfaces with
logical deterministic interfaces.
- Push control flow up and data flow down.
Simplify function signatures to minimize branches at
the call site, which are viral through the call graph.
As a return type, bool trumps u64 trumps !u64.
Minimize or define variables near to when/where they
are used, to close semantic gaps in time/space.
Dependencies risk safety and performance, invite
supply chain attacks, and increase install times. For
infrastructure in particular, these costs multiply up the stack.
Similarly, tools have costs. A small standard toolbox
feels slow for you at first but accelerates the team long
term.
Code, like steel, is easier to change while it's hot. Do it
right the first time, the best you know how, because
you may not get another chance, and because quality
builds momentum. This is the only way to make steady
progress, knowing that the foundations are solid.