Tiger Style
Apply the Tiger Style coding philosophy when writing, reviewing, or refactoring code. Tiger Style prioritizes safety, performance, and developer experience through disciplined engineering practices.
Read the full Tiger Style guide at references/tigerstyle.md for complete details.
Core Principles
1. Safety
- •Simple, explicit control flow. Favor straightforward structures. Avoid recursion. Keep execution bounded and predictable.
- •Fixed limits. Set explicit upper bounds on loops, queues, and data structures. Fail fast on violations.
- •Function length under 70 lines. Each function does one thing well.
- •Centralize control flow. Parent functions manage branching and state. Helper functions are pure, non-branching computations.
- •Functional Core, Imperative Shell. Extract pure, deterministic business logic into functions with no I/O, no async/await, no external state mutation. Keep side effects (network, disk, time, randomness) in a thin shell layer. The shell calls the core; the core never calls the shell.
- •Explicitly sized types. Use
u32,i64notusize. Consistent behavior across platforms. - •Static memory allocation. Allocate at startup, avoid dynamic allocation after initialization.
- •Assertion density. Target at least two assertions per non-trivial function. Assert positive AND negative space. Split compound assertions (
assert!(a); assert!(b);notassert!(a && b)). - •Compile-time assertions. Use
const _: () = assert!(...)to verify constant relationships before any code runs. - •Handle ALL errors. 92% of catastrophic failures come from incorrect error handling. Test error paths with equal rigor.
- •Buffer external events. Don't react directly to external events. Process in controlled batches.
- •Decompose compound conditions. Use nested
if/early returns instead of complex boolean expressions.
2. Performance
- •Design for performance early. The biggest wins (1000x) come from design decisions, not micro-optimizations.
- •Napkin math. Back-of-the-envelope calculations to estimate performance and catch bottlenecks early.
- •Separate control plane from data plane. Different optimization strategies for each.
- •Batch operations. Amortize expensive operations across multiple items.
- •Resource priority: Network > Disk > Memory > CPU. Optimize the slowest first.
- •CPU large work chunks. Hand the CPU a batch, let it process in a tight loop.
- •Extract hot loops with primitive arguments. No
&self, no trait objects, no complex structs in hot inner loops.
3. Developer Experience
- •Naming:
snake_case, no abbreviations, acronyms as single words (RpcHandlernotRPCHandler), include units (latency_ms_max), helper prefix convention (process_batch_validate_entry). - •Organization: Entry points and public API first, then private helpers. Callbacks last in parameter lists.
- •No duplicates or aliases. Single source of truth for every piece of data.
- •Off-by-one prevention. Indexes (0-based), counts (1-based), and sizes are distinct types.
- •Long-form CLI flags in scripts.
--forcenot-f,--recursivenot-r. - •Prefer Rust tooling.
xshell/ductover bash for automation. - •Minimize external dependencies.
- •Zero technical debt. Do it right the first time.
Formal Verification with Verus
For high-assurance pure functions, use the two-file pattern:
code
crates/my-crate/
src/verified/ # Production pure functions (compiled by cargo)
mod.rs
lock.rs # Pure logic: is_expired, compute_deadline
src/lock.rs # Imperative shell: async try_acquire, I/O
verus/
lib.rs # Verus module root with invariant documentation
lock_state_spec.rs # Verus specs with ensures/requires clauses
Use Verus for: coordination primitives, state machine transitions, fencing token logic, overflow-sensitive arithmetic, any critical pure function.
Applying Tiger Style
When writing new code:
- •Identify pure logic and separate it from I/O (Functional Core, Imperative Shell)
- •Add assertions (at least 2 per non-trivial function, positive and negative space)
- •Set explicit bounds on all loops and collections
- •Use saturating/checked arithmetic for overflow safety
- •Keep functions under 70 lines
- •Name things with units and qualifiers
- •Add
// Tiger Style:comments explaining safety properties
When reviewing code:
- •Check assertion density and quality
- •Verify error paths are fully tested
- •Look for unbounded loops/queues
- •Check for proper separation of pure and effectful code
- •Verify compound conditions are decomposed
- •Confirm naming follows conventions
Additional Resources
Reference Files
For the complete Tiger Style guide with all examples and rationale:
- •
references/tigerstyle.md- Full Tiger Style specification (Version 0.1-dev)