16 Dec 2023




Intermediate

Clean Architecture also called as Layered Approach to Software Design, developed by Robert C. Martin (Uncle Bob), is a set of principles for designing software that is simple, understandable, flexible, testable, and maintainable. It achieves this by organizing the code into layers with dependencies flowing inwards, making it independent of frameworks, databases, and other external elements.

Clean Architecture:

Clean Architecture

1. Domain: This layer represents the "core" of your application and contains the business logic, business rules, entities that define your domain model. It's independent of any specific technology or framework. Think of it as the "heart " of your application.

Note📝: Business Rules: Business rules are the specific guidelines and conditions that define how the business logic of a system operates, such as validating user input, calculating prices, or enforcing specific workflows. Examples: Business rules for an online shopping system

  • Focus: Core business logic and domain models, independent of any specific technology or framework.
  • Components: Entities, value objects, domain services, repositories (interfaces, not implementations).
  • Responsibilities: Defining domain concepts, enforcing business rules, managing data consistency, and providing operations for manipulating domain objects.
  • Dependency: No dependencies on higher layers (Presentation, Infrastructure, Application).
  • Benefits: Reusability, testability, maintainability, and independence from external frameworks.

2. Application: The Application layer, also known as the Use Cases layer, contains application-specific business rules and use cases. It acts as an intermediary between the Domain layer and the outer layers. This layer manages the flow of data and business logic, coordinating the execution of use cases without containing detailed business rules. It's responsible for interacting with the Domain layer to achieve specific application functionality.

  • Focus: Implements the use cases defined in the domain, coordinate interactions with other layers.
  • Components: Application services, factories, domain events.
  • Responsibilities: Coordinating domain logic execution, responding to events, managing transactions, and validating data.
  • Dependency: Depends on the Domain layer and Infrastructure layer.
  • Benefits: Encapsulates business logic, simplifies presentation logic, and provides a clear separation of concerns.

Note📝: Use Cases: Use cases are specific actions or tasks that users can perform in a software system, like placing an order or searching for information. Examples: Use cases for an online shopping system

3. Persistence (Infrastructure): The Persistence layer is responsible for managing the data storage and retrieval mechanisms, such as databases or file systems. It interacts with the Application layer to store and retrieve data but does not contain business logic. The goal is to abstract away the details of data storage, making it possible to switch database implementations or storage mechanisms without affecting the core business logic in the Domain layer.

  • Focus: Implements data storage and retrieval mechanisms specific to the chosen technology (e.g., database, file system).
  • Components: Repositories (concrete implementations specific to the storage technology), data access objects, mappers.
  • Responsibilities: Persisting and retrieving domain objects, translating between domain objects and data storage format, and managing data access infrastructure.
  • Dependency: Depends on the Domain layer and Application layer.
  • Responsibilities: Persisting and retrieving domain objects, translating between domain objects and data storage format, and managing data access infrastructure.
  • Benefits: Decouples the domain layer from specific storage technologies, promotes testability, and enables switching storage providers easily.

4. Infrastructure: The Infrastructure layer contains components that deal with external concerns, such as frameworks, libraries, and tools. It includes implementation details related to the user interface, external services, communication protocols, and other technical aspects. The Infrastructure layer acts as a bridge between the inner layers (Domain, Application, Persistence) and the external environment, allowing the application to interact with the outside world while keeping the core business logic isolated.

  • Focus: Provides technical services and frameworks used by other layers.
  • Components: Logging, messaging, caching, authentication, networking, security, etc.
  • Responsibilities: Providing technical services, handling cross-cutting concerns, and integrating with external systems.
  • Dependency: Depends on the Domain Layer , Application layer and Persistence
  • Benefits: Promotes loose coupling, simplifies technical implementation, and enables using various technologies without affecting the core domain logic.

5. Presentation: The Presentation layer is responsible for handling the user interface and user interactions. It includes components for displaying information to users, capturing user input, and presenting the results. In web applications, this layer often includes the UI components (e.g., web pages, views) and handles user input, forwarding relevant requests to the Application layer. The Presentation layer should be kept as thin as possible, with most of the business logic residing in the deeper layers.

  • Focus: User interface, network communication, formatting, and display of data.
  • Components: Controllers, views, APIs, web services, etc.
  • Responsibilities: Formatting data for presentation, handling user interactions, routing requests, and displaying information to the user.
  • Dependency: Depends on the Infrastructure layer and Application layer.
  • Benefits: Enables independent development and deployment of different presentation formats, facilitates UI/UX design, and keeps the core logic decoupled from specific presentation technologies.

Dependencies flow

The arrows in the diagram indicate the direction of dependency flow, enforcing the principle that dependencies should always point inward. This means that the more abstract and business-centric layers (Domain and Application) remain independent of the concrete implementation details found in the outer layers (Persistence/Infrastructure and Presentation). This separation enhances maintainability, testability, and adaptability to changes in the system.

+-------------------------+
|                   	  |
|                         |
|     +---------------+   |
|     | Domain        |   |
|     +---------------+   | 
|             |           |
|             v           |
|     +---------------+   |
|     | Application   |   |
|     +---------------+   |
|             |           |
|             v           |
|     +---------------+   |
|     | Persistence/  |   |
|     | Infrastructure|   |
|     +---------------+   |
|             |           |
|             v           |
|     +---------------+   |
|     | Presentation |    |
|     +---------------+   |
+-------------------------+

Explanation of each layer:

  1. Domain Layer:

    • The core of the application where business entities, rules, and logic reside.
    • Independent of other layers, contains the essential business knowledge.
  2. Application Layer:

    • Coordinates and contains use cases, applying business rules from the Domain layer.
    • Acts as an intermediary between the outer and inner layers.
    • Depends on the Domain layer but is independent of the Presentation and Infrastructure layers.
  3. Persistence/Infrastructure Layer:

    • Deals with data storage, external services, and infrastructure concerns.
    • Contains implementations for interacting with databases, file systems, or external APIs.
    • Independent of the other layers, including the Application layer.
  4. Presentation Layer:

    • Responsible for user interfaces and delivering information to users.
    • Interacts with the Application layer to obtain data and execute use cases.
    • Independent of the other layers, including the Application layer.

Flow of control:

+-------------------------+
|  User Input / Events    |
|        (UI Layer)       |
|             |           |
|             v           |
|   +-----------------+   |
|   | Presentation    |   |
|   |   (Controller)  |   |
|   +-----------------+   |
|             |           |
|             v           |
|   +-----------------+   |
|   | Application     |   |
|   |    (Use Cases)  |   |
|   +-----------------+   |
|             |           |
|             v           |
|   +-----------------+   |
|   | Domain          |   |
|   |   (Entities &   |   |
|   |    Business)    |   |
|   +-----------------+   |
|             |           |
|             v           |
|   +-----------------+   |
|   | Persistence/    |   |
|   | Infrastructure  |   |
|   +-----------------+   |
+-------------------------+

Explanation:

  1. User Input / Events (UI Layer): Represents user input or events triggering the application.

  2. Presentation (Controller): The controller in the Presentation layer receives user input, processes it, and invokes corresponding actions in the Application layer.

  3. Application (Use Cases): The Application layer contains use cases that orchestrate the application's business logic. It interacts with the Domain layer to execute business rules.

  4. Domain (Entities & Business): The core of the application where business entities and rules reside. The Domain layer does not depend on any other layer.

  5. Persistence/Infrastructure: Responsible for data storage and external services. It interacts with the Domain layer to persist and retrieve data but remains independent of the other layers.

The one-way flow of control ensures that high-level policies (in the Domain layer) are not influenced by the details of lower-level implementation (in the Presentation and Infrastructure layers), promoting maintainability and flexibility.

Key Points:

  • Dependencies flow inwards: Domain -> Application -> Persistence/Infrastructure -> Presentation.
  • Higher layers are independent of lower layers, promoting testability and reusability.
  • Each layer has a well-defined responsibility and is decoupled from others.