- Start with a working skeleton; ship something that runs.
- Write code a new hire can read at 3 AM: clear names, flat structure, no magic.
- Handle failure explicitly—return errors, not surprises.
- Log every meaningful event with structured fields and levels.
- Keep interfaces small and obvious; hide internals.
- Profile before you optimize; measure, change, measure again.
- Leave margin—CPU head-room, error budgets, TODO comments that matter.
- Guard the main branch: tests pass, build green, always deployable.
- Prefer explicit over implicit.
- Duplicate once if it keeps things simple; extract only on the third sighting.
- Make one change at a time; commit early and often.
- Write comments for “why”, never for “what”.
- Default to functions over classes; compose over inherit.
- Assert early, assert often.
- Treat code reviews as design reviews, not blame sessions.
- Clever one-liners or meta-programming that hides logic.
- Guessing future requirements; today’s guess is tomorrow’s tech debt.
- Deep folder hierarchies and tiny files that split related logic.
- Over-optimizing hot paths before profiling.
- “Just enough” abstractions that breed more abstractions.
- Silent catches that swallow exceptions.
- Pushing broken code to
main
. - Hidden global state or mutable singletons.
- Copy-pasting stack-overflow code you don’t understand.
- Abstractions that leak critical details and block debugging.
- Relying on hope instead of tests.
Remember: Simplicity isn’t a style—it’s survival.