Skip to content
Beskid The Beskid Book

Beskid

Jump to a Beskid service

Beskid

Jump to a Beskid service

1.3 SOLID, DRY, and the failure of DDD

When good principles become mandatory abstraction layers.

SOLID, DRY, and the failure of DDD

SOLID and DRY are fine. They became a problem when the industry turned them into religion and DDD into mandatory theatre.

Dramatic preaching

  • Single responsibility: good until every class is one line and your navigation is a war crime.
  • Open/closed: good until you wrap everything in inheritance because “extension points.”
  • Liskov: good until nobody can explain why your “rectangle” broke the square.
  • Interface segregation: good until you have seventeen IThingReader variants for one CSV import.
  • Dependency inversion: good until it means a DI container black box that injects everything because it can.

Too many layers

Beskid’s compiler-side take (see also the compiler README): IoC is a direction; IoC frameworks are not. Inversion of control belongs in compile-time wiring you can verify, not in runtime indirection you discover when production logs start speaking in interfaces.

DRY — do not repeat yourself (into a monolith)

Section titled “DRY — do not repeat yourself (into a monolith)”

DRY was never “one copy of every string in the universe.” It was one authoritative place for each rule.

What happened in the wild:

  • Shared “utility” assemblies that couple every service to every other service’s mistakes.
  • Generic repositories because someone heard DRY and panicked.
  • Abstractions that exist only so two teams do not talk to each other.

Warning — wrong abstraction

Sometimes repetition is cheaper than the wrong abstraction. Beskid prefers compile-time reuse (modules, metaprogramming) over runtime cleverness (reflection, service locator soup).

Domain-Driven Design contains useful ideas: ubiquitous language, bounded contexts, explicit boundaries. The industry implementation is often:

  1. Draw aggregates on a whiteboard.
  2. Invent seventeen entity types for a table with four columns.
  3. Add “domain services” because the entity got fat.
  4. Add “application services” because the domain service got fat.
  5. Add “infrastructure” folders until the repo looks like a matryoshka doll of interfaces.
  6. Ship the same CRUD anyway, but now onboarding takes a quarter.

Nested layers — matryoshka architecture

DDD forces overcomplication when:

  • The business is mostly state transitions on rows (it usually is).
  • The team treats patterns as moral requirements, not tools.
  • “Rich domain models” become anemic data with aggressive naming.

The failure mode is not DDD the book—it is DDD the performance: architects performing complexity so stakeholders feel sophistication.

Standing ovation for the performance

  • Language features are language features—not ten layers of corelib and framework glue.
  • Prefer explicit modules and compile-time composition over runtime discovery.
  • Make illegal states harder at compile time without inventing a new bounded context for EmailAddress.

Next: 1.4 Trauma — by developers, for developers.