Engineering Principles
How I build software. Agents: follow these unless the repo says otherwise.
Based on The Pragmatic Programmer; quotes are its tips.
curl -s https://www.huijo.xyz/about/engineering-principles.txt
-
DRY (Don’t Repeat Yourself)
Every piece of knowledge should have one authoritative representation.
// in practice- Each fact (a rule, limit, or format) lives in one place; code, docs, and config point to it instead of restating it.
- Code that merely looks alike but encodes different facts is not duplication.
- Docs explain why; they don’t copy facts the code already defines.
-
Orthogonality
Keep components independent so changing one doesn’t unnecessarily affect others. “Eliminate effects between unrelated things.”
// in practice- Give each component one well-defined purpose; changing it shouldn’t ripple into unrelated ones.
- Avoid global data and needless coupling.
-
Reversibility
Avoid design decisions that are difficult to undo. “There are no final decisions”: requirements, vendors, and architectures change. “Forgo following fads.”
// in practice- Keep vendors, frameworks, and volatile decisions behind a thin seam you can swap.
- Don’t adopt a tool because it’s fashionable.
-
Tracer Bullets
Build a small, working end-to-end implementation to validate your direction early. “Use tracer bullets to find the target.”
// in practice- Start with a thin, real slice through every layer, then grow it.
- Tracer code is kept: lean but complete production code, not a throwaway prototype.
-
Broken Windows Theory
Fix small problems before they normalize poor software quality. “Don’t live with broken windows.”
// in practice- Inside the task scope, fix bad designs and poor code when you find them. No time to fix properly? Board it up: comment it out, mark it unimplemented, or stub it.
- Outside the task scope, flag it; don’t fix it unasked.
-
Design by Contract
Define explicit expectations, guarantees, and invariants for software components.
// in practice- State preconditions, postconditions, and invariants for each routine.
- Be strict in what you accept; promise as little as possible.
- Crash early: a broken contract stops the program; never silently fall back or limp on.
-
Good-Enough Software
Balance quality, time, and actual user needs rather than pursuing perfection. “Make quality a requirements issue.”
// in practice- Ask where the quality bar is instead of guessing; ship early.
- Know when to stop: don’t spoil a working program with overembellishment.
-
When a Problem Feels Hard
Stop and ask before pushing harder:
- Is there an easier way?
- Are you trying to solve the right problem, or have you been distracted by a peripheral technicality?
- Why is this thing a problem?
- What is it that’s making it so hard to solve?
- Does it have to be done this way?
- Does it have to be done at all?