Skip to content

General Coding Guidelines

Applies to all projects, independent of programming language or artifact type. OOP-specific guidance is in the OO Design and Programming Guidelines. Tool chain and build environment guidance is in the Tool Chain Guidelines.

Clean Code

  • Clarity, readability, and maintainability over performance (unless performance is explicitly critical).
  • Comments in English. Explain what and why, never how (if you need to explain how, rewrite the code).
  • Idiomatic code following the community standards of each language/ecosystem.
  • Define type aliases to give the programmer better hints and to improve type safety.
  • Move complex conditionals to separate, testable function with self-explanatory name.

Clean Architecture

  • Dependencies point inward only: appinfrausecasedomain. Never outward.
  • Main program - Handles command line arguments, environment variables, signals and exit codes. Instanciates and runs app
  • app - An abstraction for the application, instactiates and wires components
  • domain — technology-agnostic data structures and domain logic; immutable/functional, no side-effects
  • usecase — orchestrates domain objects; defines interfaces implemented by infra; spans transaction boundaries, side-effects via infra
    • Repository and other output-port interfaces are defined here, not in domain/. The domain layer has no knowledge of persistence.
  • infra — implements side effects: HTTP handlers, DB clients, message brokers, etc.
  • Enforce in the pipeline (architecture check): ArchUnit (Java), GoArch (Go), Clang-Tidy (C++).

Immutability/Functional Programming

  • Prefer immutability over mutation
  • Prefer functional style over procedural style

Architectural Red Flags

These patterns are not bugs — they are design signals. Each one is a mandatory prompt to re-examine the architecture before writing more code.

  • Locks, sleep/delay, polling: explicit synchronization primitives, timed waits, and busy-wait loops indicate a missing abstraction (event, queue, reactive stream). Reach for the right primitive; do not patch a structural problem with a timing hack.
  • Sockets and thread management in business services: direct use of sockets or thread APIs in domain or use-case code signals a broken layer boundary — infrastructure concerns leaking into business logic. These belong exclusively in the infra layer. Business services orchestrate domain rules; they do not manage I/O or concurrency.

Directives

  • Clarity and readability over performance unless performance is explicitly critical
  • Comments in English; explain why not how; never comment what obvious code does
  • Dependency direction: app → infra → usecase → domain; never outward
  • Domain layer: technology-agnostic, no I/O, no persistence, no external calls
  • Repository and output-port interfaces are defined in usecase, not in domain
  • Enforce architecture constraints in CI (ArchUnit for Java, go-arch-lint for Go, Clang-Tidy for C++)
  • Prefer immutability and functional style over mutation and procedural style
  • Locks, sleep/delay, polling → signal a missing abstraction; do not patch with timing hacks
  • Direct socket or thread management belongs exclusively in the infra layer