Clean Architecture — Explained with Examples
Clean Architecture organizes code into concentric layers where inner layers contain business rules and outer layers handle frameworks, UI, and infrastructure.
Clean Architecture, coined by Robert C. Martin, is also known as Hexagonal Architecture (Ports and Adapters) or Onion Architecture. Its core rule: dependencies point inward. Outer layers (UI, database, web) depend on inner layers (business logic), never the reverse.
Why Clean Architecture Matters
Frameworks and databases become obsolete or get replaced. If your business logic is tightly coupled to Django, Spring, or MySQL, replacing them means rewriting everything. Clean Architecture isolates business rules from infrastructure concerns, making the system adaptable and testable without frameworks.
Real-World Analogy
A company’s core operations (accounting, payroll) happen in a secure inner office. Visitors, deliveries, and contractors interact through a reception desk (interface). If the receptionist is replaced or the mail system changes, the core operations continue undisturbed. Clean Architecture is that inner office protected by well-defined interfaces.
Example: Clean Architecture Layers
# ---- Inner layer: Entities (enterprise business rules) ----
class Order:
def __init__(self, items: list):
self.items = items
self.paid = False
def total(self) -> float:
return sum(item.price for item in self.items)
# ---- Inner layer: Use Cases (application business rules) ----
class CheckoutUseCase:
def __init__(self, payment_gateway, order_repo):
self.payment_gateway = payment_gateway # interface
self.order_repo = order_repo # interface
def execute(self, order):
total = order.total()
success = self.payment_gateway.charge(total)
if success:
order.paid = True
self.order_repo.save(order)
# ---- Outer layer: Adapters (frameworks, UI, DB) ----
class StripePaymentGateway: # implements payment interface
def charge(self, amount):
print(f"Charging ${amount} via Stripe")
return True
class PostgresOrderRepository: # implements repo interface
def save(self, order):
print(f"Saving order (${order.total()}) to Postgres")
# Wiring — done at composition root
repo = PostgresOrderRepository()
gateway = StripePaymentGateway()
use_case = CheckoutUseCase(gateway, repo)
use_case.execute(Order([Item("Laptop", 999)]))Related Terms
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro