---
name: Low-dependency functional coding practices
description: Default coding posture across all the user's projects regardless of language. Stdlib-first, immutable-first, composition over framework.
type: feedback
created: YYYY-MM-DD
---

**Why:** Maintaining many small services means every dependency is a future
upgrade tax. Functional, immutable code is easier to test and reason about.

**How to apply:** Before adding a dependency or reaching for a framework
abstraction, check this list.

## Rules

- **Stdlib first.** Before `npm install <thing>` / adding a hex dep, check
  whether the language stdlib already does it. Usually it does.
- **One dep per real need.** No utility-library kitchen sinks (lodash,
  underscore, ramda). If you use one function, write the function.
- **Pure functions by default.** Data in, data out, no hidden state.
  Side-effects pushed to the edges.
- **Immutable data.** No mutation of inputs. Return new values.
- **Composition over inheritance.** Build complex behaviour by piping small
  functions, not by extending classes.
- **No metaprogramming for cleverness.** Macros, decorators, reflection — only
  when the alternative is genuinely worse, and document why in a comment.
- **Names are predicates.** `is_*`, `has_*`, `*_eligible?` for booleans.
- **No premature abstraction.** Two call sites = inline. Three+ = consider
  extraction. Never abstract on the first occurrence.
- **Plain data over objects.** Maps/structs/dicts > custom classes when the
  data is just data.
- **Errors are values.** Return `{:ok, _} | {:error, _}` (Elixir),
  `Result`/tagged unions (Rust/TS), explicit error returns. Avoid exceptions
  for control flow.
- **Comments explain *why*, not *what*.** The code shows what. Comments earn
  their keep by stating intent the code can't.
