Tale of Software Architect(ure): Part 13 (Clean Architecture)

Tale of Software Architect(ure): Part 13 (Clean Architecture)


Story:

In this world, Allah is the most powerful and only independent who doesn't need any help or something like that. Allah creates the whole world and all the creatures. Human is one of the best creature of Allah. He also creates a dependency chain that should be followed for maintaining the balance. If anyone want to break the chain or so called break the rules then a very unexpected and dangerous things happen. Which cost a very big damage in the system.

In the right hand part of the below picture, I try to draw a dependency flow of the universe where Allah (SWT) is one and only independent and all other parts are dependent of him directly or indirectly.


Previously I had written details about the Clean Architecture in Random Topic - 32 . You can check it out and then continue from the below section.


Clean Architecture:

Left hand: Uncle bob, Right hand : Myself

Clean Architecture is a software design philosophy introduced by Robert C. Martin (Uncle Bob) in his book Clean Architecture: A Craftsman’s Guide to Software Structure and Design. The main idea is to create a system that is flexible, maintainable, and independent of frameworks, databases, UI, or any external services. This is achieved by organizing code into layers, ensuring that each layer has a clear responsibility and that core business logic remains isolated from implementation details.

Key Concepts of Clean Architecture

  • Layered Structure (Onion-like or Concentric Circles): Clean Architecture is often visualized as a set of concentric circles, with each layer representing a different level of abstraction. Each layer can only depend on the layer directly inside it (higher-level layers depend on lower-level layers, not the reverse).
  • Dependency Rule: The dependency rule dictates that source code dependencies can only point inwards. The outer layers depend on the inner layers, but the inner layers should have no knowledge of the outer ones. This makes the core logic independent of external concerns (frameworks, databases, or UIs).
  • Boundaries: A key feature of Clean Architecture is the establishment of boundaries, using interfaces to separate the different layers. This ensures that each layer interacts with the adjacent layers in a controlled, predictable way.


Context

In software development, it is common to build systems that are initially easy to manage but become hard to maintain as they grow. Typically, these systems have tightly coupled components like user interfaces, databases, and business logic, making it difficult to make changes without breaking things or introducing bugs.

Developers often struggle to keep their codebases flexible, testable, and maintainable over time. Frameworks evolve, databases change, and new user interfaces are required. These changes often result in complex refactoring efforts that lead to brittle code and high development costs.


Problem

The main problem is tight coupling between the different layers of an application, especially between the business logic, frameworks, and external services. This creates several issues:

  • Framework Dependency: The business logic is tightly bound to the framework or database in use. Changing or upgrading a framework may break core application logic.
  • Difficult to Test: With logic mixed up between UI, database, and core operations, testing individual pieces of the application in isolation becomes difficult. You may need to spin up a full database or web server to test basic business logic.
  • Complex Refactoring: Even small changes in one part of the system can lead to ripple effects in other parts, making refactoring and extending the application difficult.
  • Poor Maintainability: As the codebase grows, the system becomes increasingly hard to understand and maintain, increasing the chance of introducing bugs when making updates or feature changes.


Solution

Clean Architecture provides a structured approach to solving these problems by separating the application into layers, with clear boundaries and dependency rules:

Separation of Concerns: The architecture defines distinct layers (entities, use cases, interface adapters, frameworks/drivers), each responsible for a specific type of functionality. This makes the system more understandable and easier to maintain.

  • Core Business Logic (Entities): Contains the high-level rules and is completely independent of external services or frameworks. This means you can change frameworks, databases, or UI without affecting this layer.
  • Application Logic (Use Cases): Encapsulates application-specific logic and coordinates the interaction between entities. It is focused on solving specific business needs (e.g., placing an order) without knowing how the data is persisted or presented.
  • Interface Adapters: Translates data between the internal system and external components like UI, databases, or APIs. This ensures the core business logic is shielded from external changes.
  • Frameworks/Drivers: External services like the database, UI, or payment gateway reside here. The business logic doesn’t depend on these details, making the application more adaptable to change.

Dependency Rule: Clean Architecture dictates that dependencies flow inwards (towards core business logic). The innermost layers (entities, use cases) should know nothing about outer layers (frameworks, UI, or databases). Outer layers depend on the inner layers by adhering to the inversion of control principle (e.g., using interfaces to decouple dependencies).

Testability and Flexibility: By isolating business logic from external dependencies, Clean Architecture enables easier testing. Each layer can be tested in isolation without requiring real databases or external services. This increases confidence in refactoring and adding new features.

Maintainability: The architecture encourages writing clear, modular code that separates business logic from implementation details. This improves long-term maintainability, as developers can change external components (e.g., switching from SQL to NoSQL) without modifying the core system.


Practical Example: E-Commerce Order System

Let’s apply Clean Architecture principles to an order processing system for an e-commerce platform.

Entities (Core Business Logic):

  • Entities might include classes like Order, Customer, and Product.
  • The Order entity would have the logic for calculating the total price, adding or removing items, and checking inventory.
  • These classes are completely unaware of the database, UI, or how orders are presented to users. They just encapsulate the business rules.

class Order:
    def __init__(self):
        self.items = []

    def add_item(self, product, quantity):
        # Business logic for adding an item
        self.items.append((product, quantity))

    def calculate_total(self):
        return sum([product.price * quantity for product, quantity in self.items])        

Use Cases (Application Logic):

  • This layer would contain use cases like PlaceOrder or CalculateShipping.
  • The PlaceOrder use case uses the Order entity to ensure that an order is valid and can be processed.
  • It also handles business logic, such as checking if the customer has enough balance to place the order or if the products are in stock.

class PlaceOrder:
    def __init__(self, order_repo, payment_service):
        self.order_repo = order_repo
        self.payment_service = payment_service

    def execute(self, order, customer):
        # Ensure the order is valid
        if order.calculate_total() > customer.balance:
            raise Exception("Insufficient balance")
        # Handle payment processing
        self.payment_service.process_payment(customer, order.calculate_total())
        # Store the order
        self.order_repo.save(order)        

Interface Adapters (Data Transformation):

  • This layer adapts the data for use by the inner layers. For example, if you're using a database, you'd have a repository interface here to adapt database rows to domain objects.
  • These adapters translate the format of the data used by the business logic to the one expected by external systems like databases or UI.

class OrderRepository:
    def __init__(self, db):
        self.db = db

    def save(self, order):
        # Convert order to database format and save
        self.db.insert("orders", {"items": order.items, "total": order.calculate_total()})        

Frameworks and Drivers (External Services):

  • This layer contains frameworks, databases, or external services like payment gateways.
  • For example, a payment processing service or database connector would reside here.
  • If we change the database from MySQL to MongoDB, we only need to modify this layer, without affecting the business logic.

class PaymentService:
    def process_payment(self, customer, amount):
        # External service handling the payment
        external_payment_gateway.charge(customer.account, amount)        

Summary:

Clean Architecture is a software design philosophy created by Robert C. Martin (Uncle Bob) that aims to produce systems that are flexible, maintainable, and independent of frameworks, databases, or external services. The main goal is to separate concerns by organizing code into layers, ensuring that core business logic (entities) is isolated from implementation details like UI, databases, and frameworks. It promotes creating adaptable and resilient systems by isolating business logic from external dependencies and organizing the codebase into well-defined, decoupled layers.


Previous Parts:

Part 1: Tale of software architect(ure): Part 1 (Software Architecture and Software Design)

Part 2: Tale of software architect(ure): Part 2 (Role of Software Architect and Knowledge To Have)

Part 3: Tale of Software Architect(ure): Part 3 (Characteristics of Software Architecture)

Part 4: Tale of Software Architect(ure): Part 4 (Things Should Consider When Design/Architect a Software System)

Part 5: Tale of Software Architect(ure): Part 5 (Wrong Assumption in Software Architecture and Fallacies of Distributed Computing)

Part 6: Tale of Software Architect(ure): Part 6 (Framework for System Design Interview)

Part 7: Tale of Software Architect(ure): Part 7 (Well Known Software Architectures Styles)

Part 8: Tale of Software Architect(ure): Part 8 (Architecture Patterns and Layered Architecture)

Part 9: Tale of Software Architect(ure): Part 9 (MVC Architecture Pattern)

Part 10: Tale of Software Architect(ure): Part 10 (Pipe-Filter Architecture)

Part 11: Tale of Software Architect(ure): Part 11 (Microkernel Architecture)

Part 12: Tale of Software Architect(ure): Part 12 (Service Oriented Architecture)


要查看或添加评论,请登录

社区洞察

其他会员也浏览了