Clean Architecture: A Craftsman’s Guide to Software Structure and Design by Robert C. Martin (Uncle Bob)**
Clean Architecture by Robert C. Martin presents a structured approach to designing maintainable, scalable, and testable software. It builds on the principles of Clean Code and Clean Craftsmanship, emphasizing separation of concerns, dependency management, and long-term maintainability.
The book introduces the concept of architectural boundaries, focusing on keeping high-level business logic independent from frameworks, databases, and UI components.
- Software architecture is about structuring code to minimize the cost of change.
- A good architecture delays decisions about details (frameworks, databases) and keeps the core business logic protected.
A clean architecture should be:
- Independent of frameworks – Avoid locking business logic into specific tools.
- Testable – Core logic should be testable without UI, database, or external dependencies.
- Independent of UI – The system should work with different interfaces (CLI, web, mobile).
- Independent of databases – The database should be an implementation detail, not the core driver.
- Business rules should not depend on implementation details (like UI, database, or frameworks).
- Code dependencies should always point inward (toward business logic) and never outward (toward external systems).
- Single Responsibility Principle (SRP) – Each module should have one reason to change.
- Open-Closed Principle (OCP) – Systems should be open for extension but closed for modification.
- Liskov Substitution Principle (LSP) – Derived classes should be substitutable for their base classes.
- Interface Segregation Principle (ISP) – Avoid large, monolithic interfaces; use smaller, focused ones.
- Dependency Inversion Principle (DIP) – High-level modules should not depend on low-level modules, but on abstractions.
Uncle Bob introduces a layered approach to structuring software, where the core business logic is at the center:
- The most abstract and high-level part of the system.
- Contains core business logic, independent of frameworks, databases, or UI.
- Should be pure and reusable across different applications.
- Defines how the system behaves in response to user actions.
- Coordinates entities to execute business logic.
- Should not depend on external frameworks or databases.
- Responsible for converting external data (e.g., HTTP requests, database queries) into a format usable by the business logic.
- UI, database access, and external APIs belong here, not in the core business logic.
- The outermost layer, containing implementation details.
- Should depend on the inner layers, never the other way around.
- No inner layer should depend on an outer layer.
- Inner layers contain high-level policies, while outer layers contain implementation details.
- Dependencies should be inverted using interfaces and dependency injection.
- Frameworks (like Rails, Spring, or Django) are tools, not architectures.
- Instead of making the business logic dependent on a framework, keep it independent and adapt the framework to the architecture.
- Many systems make the database the foundation of the architecture, but this is a mistake.
- The database should be pluggable, allowing the system to work without it (e.g., using in-memory storage for testing).
- Business logic should be independent of SQL or NoSQL choices.
- A clean architecture makes unit testing easy by keeping business logic isolated.
- External dependencies (database, UI, network) should be mocked or stubbed.
- Use dependency injection to swap implementations easily.
- Microservices and monoliths can both follow clean architecture principles.
- Regardless of system size, business logic should remain decoupled from external dependencies.
Clean Architecture teaches that good software design prioritizes long-term maintainability over short-term convenience. The key takeaways include:
- Separate business logic from external concerns like UI, frameworks, and databases.
- Follow SOLID principles to make code flexible and extensible.
- Apply the Dependency Rule to keep core logic isolated and testable.
- Architectures should enable change, not resist it.
By following these principles, developers can create resilient, scalable, and testable systems that remain adaptable over time.