--- title: "Clean Architecture: Layers, the Dependency Rule, and Practical Application" description: "Named case studies and concrete thresholds for applying (or not applying) Robert C. Martin's Clean Architecture - where the Dependency Rule pays off, where it's cargo-culted, and what practitioners who ship it at scale actually do differently from the book." language: null framework: null category: software_architecture tags: - clean-architecture - architecture - dependency-rule - use-cases - hexagonal - onion-architecture - maintainability - ddd keywords: - clean architecture uncle bob dependency rule criticism - clean architecture overengineering thresholds - dhh clean architecture rails critique - when not to use clean architecture - clean architecture vs hexagonal vs onion last_updated: "2026-07-08" difficulty: intermediate version: "Architecture-level guidance; language-agnostic" related: - hexagonal.md - microservices.md - ../principles/solid.md - ../principles/clean_code.md - ../testing/unit_testing_principles.md - ../testing/integration_testing.md - ../../languages/python/frameworks/fastapi/best_practices.md - ../../languages/python/frameworks/django/best_practices.md search_priority: high status: published --- # Clean Architecture: Layers, the Dependency Rule, and Practical Application Assumes you already know the four-ring diagram and the Dependency Rule. This document is about where that diagram helps, where it's cargo-culted, and what the loudest practitioner critiques actually get right. ## Decision Table: Apply It or Don't | Signal | Apply Clean Architecture | Skip it / use simple layering | |---|---|---| | Team size | 4+ engineers touching the same codebase | 1-2 engineers who already share a mental model | | Domain complexity | Multiple use cases with real branching business rules | CRUD with validation only | | Expected lifetime | Multi-year, will outlive current framework/ORM | Prototype, script, short-lived tool | | Entry points | Needs HTTP + CLI + queue consumer sharing logic | Single entry point | | Explainability | New hire/agent grasps the ring split in ~30 minutes | Would take a design doc and a whiteboard session | | Change blast radius today | A single feature change already touches 5+ files across unrelated layers for no domain reason | N/A - that's the layered-MVC failure mode, not a Clean Architecture one | If none of the left column applies, the ring ceremony is pure overhead. This matches the practical rule of thumb from Three Dots Labs' "Is Clean Architecture Overengineering?": teams of two who already work well together, CLI tools, infra utilities, and anything that fits in one developer's head do not need it - and a Reddit-sourced anti-pattern they cite by name is six-plus layers with no domain reason for the split. ## Specific, Named Criticism of How This Gets Misapplied **DHH (creator of Rails) calls the pattern-heavy version a "J2EE renaissance fair"** - a revival of "discredited patterns of complexity." His specific target is service-object/command-pattern layering stacked on top of Rails' own MVC, which he says produces "a dense jungle of service objects, command patterns, and worse." His counter-position (fat models, thin controllers, REST purity, "clarity over cleverness") is the standing rebuttal any agent should recognize when a user asks to "clean up" a Rails app - that user may be asking for the opposite of what this document describes. (Source: DHH interviews/talks summarized in industry retrospectives, 2014-2026; see Sources.) **Practitioner critique (Bosepchuk, "Why I can't recommend Clean Architecture by Robert C Martin"):** the book treats SOLID as near-absolute rules rather than trade-offs ("a system that never violated the SOLID principles would be a giant mess"), gives almost no end-to-end worked examples, and is conspicuously silent on how to apply the rings to an *existing* codebase - despite most engineers spending most of their time on legacy systems, not greenfield ones. **Victor Rentea's conference talk material ("Overengineering in Onion/Hexagonal Architectures")** makes the same point from the enterprise Java side: the pattern is fine when domain complexity is genuinely high, but "powerful influencers have promoted these architectures without stressing enough" that applying them by the book on a CRUD-shaped problem is overengineering, not rigor. **Common quantified overengineering smell**: interface-per-implementation where only one implementation will ever exist. This defeats the point of Dependency Inversion (there's nothing to invert to) and is one of the most frequently cited Clean Architecture anti-patterns in post-mortems of failed adoptions - it adds a file and a mental hop with zero swap-ability payoff. ## What "Screaming Architecture" Actually Buys You Not aesthetic - it's a legibility bet for anyone (human or agent) who has never seen the codebase: top-level directories should answer "what does this business do" (`orders/`, `payments/`, `shipping/`) before "what framework is this" (`controllers/`, `services/`). An agent asked to add a feature should be able to `ls` the top level and guess the right directory without reading code first. Directory-per-technical-layer defeats this. ## Composition Root: The One Non-Negotiable Regardless of team size or how much ring ceremony you adopt, wiring (deciding which concrete adapter satisfies which port) belongs in exactly one place, at startup, never inside a use case. This is the part of Clean Architecture that survives every critique above intact - even DHH's Rails apps have one (`config/initializers`, `Dependencies` container). Skipping this and constructing concrete infrastructure classes inside business logic is the fastest way to make the rest of the ring discipline meaningless. ## Testing Payoff (Where the Discipline Earns Its Keep) - Entities/use cases: pure unit tests, no framework, no I/O - this is the actual return on investment, and the only one worth defending if a stakeholder asks "why did this take longer to build." - If your test suite isn't measurably faster or your unit tests aren't meaningfully more numerous than before adopting rings, the boundary was drawn in the wrong place (usually: business logic still leaking into a controller or an ORM-model method). - Prefer hand-written in-memory fakes over mocking frameworks for ports - ports are small and purpose-built, so a `dict`-backed fake is clearer than recorded mock expectations. ## When *Not* to Use / Alternatives | Dimension | Clean Architecture | Simple Layered (MVC) / Rails-DHH-style | Hexagonal Architecture | |---|---|---|---| | Protects logic from framework churn | Excellent | Weak - logic lives in models/views | Excellent (same core idea) | | Onboarding speed, small team | Slower | Fast | Slower | | Best fit | Complex domain, long-lived service, 4+ engineers | CRUD-heavy apps, prototypes, small tight teams | I/O-heavy services integrating many external systems | | Loudest critics | DHH, Bosepchuk, Rentea (overengineering on simple domains) | - | Same overengineering critique when domain is simple | **Choose Rails/Django-style MVC** for genuinely CRUD systems - the ORM model *is* an acceptable domain layer there, and the DHH critique is correct for that shape of problem. **Choose Hexagonal Architecture** when the organizing pressure is the *number and diversity of external systems* rather than internal business-rule layering - see [Hexagonal Architecture](hexagonal.md). **Do not let ring boundaries become the trigger for splitting into microservices.** A modular monolith with clean internal rings is the 2026 default; see [Microservices](microservices.md) for the named case studies (Amazon Prime Video, Segment/Twilio) of teams that split first and paid for it. ## Related Documentation - [Hexagonal Architecture (Ports & Adapters)](hexagonal.md) - [Microservices Architecture](microservices.md) - [SOLID Principles](../principles/solid.md) - [Clean Code Principles](../principles/clean_code.md) - [Unit Testing Principles](../testing/unit_testing_principles.md) - [Integration Testing](../testing/integration_testing.md) ## Sources - Bosepchuk, "Why I can't recommend Clean Architecture by Robert C Martin" - https://dev.to/bosepchuk/why-i-cant-recommend-clean-architecture-by-robert-c-martin-ofd - Three Dots Labs, "Is Clean Architecture Overengineering?" - https://threedots.tech/episode/is-clean-architecture-overengineering/ - Victor Rentea, "Overengineering in Onion/Hexagonal Architectures" - https://victorrentea.ro/blog/overengineering-in-onion-hexagonal-architectures/ - Optivem Journal, "A critique of Clean Architecture and TDD" - https://journal.optivem.com/p/a-critique-of-clean-architecture-and-tdd - Hacker News, "Ask HN: What do you recommend instead of Clean Architecture by Uncle Bob?" - https://news.ycombinator.com/item?id=30089134 - Robert C. Martin, original post - https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html