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_case for variables, methods, and functions
  • UpperCamelCase for structs and enums
  • UPPER_SNAKE_CASE for constants and statics

Modules

  • Use descriptive, domain-specific names
  • Avoid generic junk drawers like utils.rs, helpers.rs, or common.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() and expect() 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::Error and Display for 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,ignore if 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.rs files 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 (true means 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.rs only 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.