Code Conventions for Clarity and Control
Conventions that are opinionated, pragmatic, and written to prevent 3 AM self-hatred.
Philosophy
Core Principles
- Immutable configuration, mutable state — Hardware configuration parameters never change after construction; execution state evolves during runtime. Reality has laws of physics; so should your structs.
- Explicit resource lifecycle — Every resource follows
CREATE → USE → DESTROY. - Fail Fast — No hidden defaults, no silent “helpfulness.” If it explodes, it should explode in my face.
- Validate at Construction — Catch errors before they metastasize into runtime mysteries.
- Fail with Context — When you error, confess everything: what, why, and with which value.
- Brevity and Necessity — Every line should fight for its existence.
- Simplicity over Cleverness — The clever code you wrote today is the unreadable horror you’ll debug tomorrow.
Applies across all layers: simulation, hardware abstraction, orchestration…
Structure
- Config is immutable — represents physical constraints.
- Execution state is mutable — represents current simulation state.
- Clear module boundaries — each does one thing, no secret alliances.
- Prefer flat hierarchies; deep nesting just ends up confusing me later.
Conventions
General
snake_casefor variables, methods, and functionsUpperCamelCasefor structs and enumsUPPER_SNAKE_CASEfor constants and statics
Modules
- Use descriptive, domain-specific names
- Avoid generic junk drawers like
utils.rs,helpers.rs, orcommon.rs - Prefer names like
hardware.rs,scheduler.rs,consumption.rs - Nothing good has ever come out of
misc.rs.
Structs
- Use nouns that describe what they represent
- Avoid cryptic abbreviations — write code for humans, not compression algorithms
- Structs own their data unless shared ownership is provably required
Functions
- Use imperative verbs:
compute_signal,update_state,validate_input - Each should do one thing and finish the sentence: “This function will…”
- If it does two things, split it before it splits you.
Variables
- Use descriptive names
- Single letters (
i,j,k) only for loops or quantum states shorter than 5 lines
Errors
Use Result
- Wrap fallible operations in
Result<T> - Avoid
unwrap()andexpect()unless it’s cleaner.
Error Quality
- Define explicit error enums; never dump strings.
- Provide full context: what failed, why, and which value caused it
- Include field name, invalid value, and expected range
- Implement
std::error::ErrorandDisplayfor readable failure messages. Thank yourself later.
Fail Fast
- Validate at construction, not during use
- Constructors return
Result<Self> - Fail early, fail loud, fail informatively
Documentation
Each exported item gets a short doc comment.
Internal helpers can skip ceremony if self-evident
Loose Template:
- One-line summary
- Detailed explanation (purpose, algorithm, usage)
- Parameters and constraints
- Return value meaning
- Error conditions and triggers
- Lifecycle phase (
CREATE,USE,DESTROY) - Example (
/// ```rust,ignoreif it’s not meant to compile)
If you write “TODO: document,” I will kill you in your sleep.
Organization
Structure
- Prefer flat control flow and early returns (
?is your friend) - Avoid nesting that has me following definitions through multiple sub-modules.
- One function, one concern
mod.rsfiles are for declarations and re-exports only — not for secret business logic
Module Size
- Split when files when they start to loose cohesion.
- Split files when concerns start to become cloudy.
- Split files when they become short novellas.
- Cohesion first; files should want to exist
Function Size
- Keep functions small
- Complex validation belongs in its own validator module
Anti-Patterns
Avoid
- Hidden global state
- Hidden mutability (
RefCell,Mutex) - Silent failures (clamping, saturating, shrugging)
- Arbitrary constraints with no reason
- Boolean traps (
truemeans what, exactly?) - God objects
- String-based type discrimination (use enums like an adult)
- Validation during use instead of construction
- Context-free “something went wrong” errors
- Magic numbers — name them or exorcise them
- Speculative features (“might need later”) — write them in a note, not in
main.rs
Review Checklist
Before submitting code:
- All errors use
Result<T>— no panics, no unwrap roulette - Doc comments cover Args/Returns/Errors/Example
- Function names are verbs, struct names are nouns
- Each function has one clear responsibility
- Lifecycle (
CREATE/USE/DESTROY) is explicit - Validation occurs at construction
- Errors include context (field, reason, value)
- Tests cover both success and failure paths
- Module boundaries align with domain concepts
-
mod.rsonly contains declarations and re-exports - No dead or commented-out code
- No unbounded recursion or infinite loops (unless that’s the experiment)
Clarity and control come from discipline, not abstraction.
Cleverness fades, but clear intent survives refactors, rewrites, and whatever AI refactoring assistant replaces us in 2030.