# software simplicity a collection of software related principles and phrases. ## general programming * software development is managing complexity * strict call by contract * everything that can be handled by the call contract should be handled by the call contract * always assume valid input * no asserts and defensive checks outside the contract * simplify by extending the contract, not by adding code * defensive checks are wasteful when their conditions are excluded by design * separating input validation allows the core logic to execute faster and remain clearer * correctness is a property of specification, not of runtime inspection * referential transparency * idempotency * falsifiability * expressions replaceable by their values * algorithmic identity encoding. language-independent method description * algorithms expressed in purely functional terms are a canonical encoding that can be projected upwards into imperative, object-oriented, or state-based implementations, and not equivalently reversed. * functional programming is both higher-level (not close to the machine) and lower-level (less complexity to define, since hidden state change and the consequent order dependence does not occur) * software described on three axes: procedures, functions, structures * the first describes algorithms and evaluation * the second describes the api in function signatures * the third describes the carrier entities with fields * descriptive variable names that use english words * short names are acceptable if they are real words and unambiguous in context (e.g. `count`) * prefer reuse of existing variables instead of introducing new ones * avoid identifiers with uppercase characters * structure modules to match visible or logical boundaries * keep the call hierarchy tidy * reduce coupling * avoid hidden control flow or registries. the hidden state changes make it harder to reason about and it causes order dependency and hinders clean abstraction * intermediate formats and defined mappings between them * triplet completion cases where any two variables define the third * key-value tree structures * derivative configuration files * convention over configuration. sensible defaults to derive from avoid boilerplate configuration * unnecessary conventions. if it is not part of the syntax, it is usually not worth following. keep it simple * do not repeat yourself * each component should do one thing well. much complexity in software comes from one thing trying to do two things * principle of least surprise * prefer positive conditions. `if (a) {b} else {c}` over `if (!a) {c} else {b}'` * use language truth semantics consistently: avoid `x == 0` and simply use `!` in c * inline when small and used at most twice; outline when large or used more than twice * no operator overloading * keep code to the essentials * omitting error handling for instruction * minimal examples that run * minimal examples that use all features ## c-specific principles * use single-compilation units * include headers and even c files directly when libraries are small * eliminates linker indirection and improves optimization visibility * declare and define all variables at the beginning of each function before usage * matches c's actual stack allocation behavior * gives an overview of storage use within the function * separates initialization from declaration * use implicit type casts where possible: avoid unnecessary explicit casts unless required for correctness * avoid convenience variables that are only used once and could be inlined * no usage of `--` or `++`; use explicit arithmetic instead * do not rely on syntax that depends on indentation * do not use enums; their typing and auto-numbering do not justify the overhead * use pointer arithmetic instead of taking the address of array index access * avoid unused initializations or deinitializations * transactional style where functions change output arguments only on success ## scheme-specific * see: [streamlined scheme](/computer/guides/scheme/streamlined.html)