Skip to content
Clean Code

Clean code: practical principles to write less and better 🧼

Writing good code is not a competition about who knows the most patterns. It is about delivering systems that are clear, testable, and easy to maintain. Three principles matter more than most: DRY, KISS, and the gloriously unromantic rule of less code, less bugs.

Why clean code matters 🧠

“Clean” code is not the prettiest code. It is the code your colleague understands at first glance, even when that colleague is you six months from now.

Immediate benefits:

  • fewer bugs and regressions
  • faster development cycles
  • lower maintenance costs
  • less dependence on project gurus and resident magicians

DRY: do not repeat yourself 🧴

DRY means every piece of knowledge should have a single authoritative representation in the system.

When to apply it:

  • extract repeated logic into functions or modules
  • centralize validation, mapping, and formatting
  • maintain a single source of truth for constants and configuration

What to avoid:

  • turning two repeated lines into a 50-line abstraction
  • abstracting before the pattern is actually clear
1
2
3
4
5
6
const (
  VATIT = 0.22
  VATDE = 0.19
)

func PriceWithVAT(p, rate float64) float64 { return p * (1 + rate) }

KISS: keep it simple 😌

KISS means choosing the simplest solution that actually works.

  • prefer small functions with explicit names
  • avoid premature optimization
  • reduce accidental complexity before chasing cleverness
  • use simple data structures as long as they are enough

Typical traps:

  • over-engineering for hypothetical future needs
  • layers of abstraction that hide the real logic
  • hyper-dynamic configuration where an enum would do just fine
  • ignoring YAGNI and building today’s ceremony around tomorrow’s fantasy

Less code, less bugs 📉

Less code means fewer surfaces for failure, fewer mental dependencies, and fewer merge conflicts. This is not aesthetic minimalism. It is risk management.

How to reduce code responsibly:

  • remove dead features or always-off flags
  • replace repetitive plumbing with reliable libraries
  • merge almost-identical functions through better parameters and types
  • automate boilerplate where it is truly boilerplate

What to measure:

  • complexity per file or module
  • duplication rate
  • onboarding time for a new person entering the codebase

When not to apply DRY and KISS blindly 🚧

  • prototypes and exploration work
  • unstable domains where abstractions would age badly in a week
  • critical performance paths where a small local ugliness may be the right trade-off

Golden rule: duplicate first, abstract when the pattern is real.


Review and refactoring checklist ✅

  • does the function name say what it really does?
  • does the module have one clear responsibility?
  • is there obvious duplication of logic or constants?
  • would a simpler solution work just as well?
  • can I delete something without anyone noticing?
  • do the tests describe behavior rather than implementation details?

In short 🧾

Use DRY to remove knowledge duplication, KISS to avoid decorative complexity, and remember that less code often means less trouble. Work in small steps, measure impact, and leave the code a little better than you found it.

Last updated on