2026-02-10

software simplicity

actionable rules

external form

  • variable names contain only english words
  • shortened english words are allowed if unambiguous in context
  • single-letter variable names are allowed in very small scopes
  • if single-letter names are used:

    • i or j for indices
    • otherwise alphabetical order a, b, c, …
  • avoid bindings used only once
  • avoid identifiers with uppercase characters
  • no operator overloading
  • keep code to the essentials
  • examples must run
  • examples must exercise all demonstrated features

contracts and control

  • strict call by contract
  • always assume valid input
  • no asserts or defensive checks outside the contract
  • simplify by extending the contract, not by adding code
  • defensive checks excluded by design must not exist
  • omit error handling when the goal is instruction

structure and composition

  • structure modules to match visible or logical boundaries
  • keep the call hierarchy tidy
  • use bottom-up accretive composition
  • each component does one thing
  • reduce coupling
  • no hidden control flow or registries
  • intermediate formats must have defined mappings
  • inline when small and used at most twice
  • outline when large or used more than twice

semantics and logic

  • prefer positive conditions over negated control flow
  • use language truth semantics consistently
  • identifiers are either value-replaceable or context-associated, not both
  • preserve referential transparency where possible
  • preserve idempotency where applicable
  • favor falsifiable structure over implicit behavior

reuse and scope

  • do not repeat yourself
  • do not implement unused or speculative functionality
  • convention over configuration
  • backward compatibility is irrelevant for new programs
  • common non-language conventions are optional

testing rules

basic tests

  • test minimal calls and compositions
  • surface compile errors, type changes, exceptions, and segfaults
  • assertions are only attached to data flow
  • test code structure must not be influenced by assertions

detailed tests

  • test fine-grained data assumptions
  • depend on already-working basics
  • remain separate from basic tests

c-specific rules

compilation and layout

  • single compilation units
  • include headers or c files directly for small libraries
  • declare all variables at function start

typing and expressions

  • use implicit casts where correct
  • avoid explicit casts unless required
  • do not use ++ or --
  • use explicit arithmetic
  • do not rely on indentation-sensitive syntax

language features

  • do not use enums
  • use 0 instead of NULL
  • prefer pointer arithmetic over indexed address-taking
  • avoid unused initialization or deinitialization

environment and platform

  • define target platform and standards explicitly
  • use inttypes.h
  • use while(1) instead of for(;;)
  • prefer caller-provided memory

scheme-specific rules

  • see streamlined scheme

design principles

complexity management

  • software development is managing complexity
  • complexity often arises from one component doing multiple things
  • contracts are a primary complexity-reduction mechanism
  • separating validation from logic reduces complexity

abstraction and representation

  • algorithmic identity encoding is language-independent
  • purely functional descriptions are canonical
  • imperative or stateful forms are projections, not inverses
  • avoid hidden state and order dependence

predictability

  • principle of least surprise
  • avoid order-dependent behavior
  • avoid implicit registries and global state

structure and data

  • key-value tree structures
  • derivative configuration files
  • defined intermediate representations

explanatory notes

naming

single-letter variables are acceptable when structure dominates over data. alphabetical ordering encodes minimal ordering information and reduces semantic collision.

contracts

extending a contract is a structural operation; adding defensive code is not. when invalid states are excluded by design, checks only add noise and execution cost.

testing separation

basic tests act as execution sentinels. detailed tests encode semantic assumptions. separation reduces maintenance cost and supports automated refactoring.

c declarations

early declaration matches actual stack allocation and provides a complete view of storage. late declaration does not correspond to runtime behavior in c.

functional primacy

functional representations avoid hidden mutation and order dependence, making them suitable as canonical descriptions from which other forms are derived.

conventions

external conventions not enforced by the language often add complexity without compensating expressive power.

links