Clean Architecture یا معماری تمیز رویکردی برای جدا نگه داشتن قواعد کسبوکار از فریمورک، دیتابیس و جزئیات ارتباطی است. قانون اصلی Dependency Rule است: وابستگیهای سورس کد باید به سمت لایههای داخلی و قوانین پایدارتر باشند.
نمونه فروشگاه: ثبت سفارش مستقل از ORM
Use Case ثبت سفارش باید بتواند از یک قرارداد Repository و درگاه پرداخت استفاده کند. اینکه برنامه با لاراول، جنگو، Go یا ASP.NET Core ارائه شده، نباید هسته قانون «سفارش بدون موجودی ثبت نشود» را عوض کند.
| لایه | مسئولیت | مثال فروشگاه |
|---|---|---|
| Entity / Domain | قواعد پایه | Order، OrderItem و Money |
| Use Case / Application | جریان کاری | PlaceOrder، CancelOrder |
| Interface / Port | قراردادهای بیرونی | OrderRepository و PaymentGateway |
| Infrastructure / Adapter | جزئیات اجرا | Eloquent، Django ORM، PostgreSQL |
| Transport / Controller | HTTP، CLI یا Consumer | CheckoutController |
PHP
interface OrderRepository { public function save(Order $order): void; }
final class PlaceOrder {
public function __construct(private OrderRepository $orders) {}
public function execute(Order $order): void {
$order->validateStock();
$this->orders->save($order);
}
}
Python
from typing import Protocol
class OrderRepository(Protocol):
def save(self, order): ...
class PlaceOrder:
def __init__(self, repo: OrderRepository): self.repo = repo
def execute(self, order):
order.validate_stock()
self.repo.save(order)
Go
type OrderRepository interface { Save(context.Context, Order) error }
type PlaceOrder struct { Repo OrderRepository }
func (u PlaceOrder) Execute(ctx context.Context, order Order) error {
if err := order.ValidateStock(); err != nil { return err }
return u.Repo.Save(ctx, order)
}
C#
public interface IOrderRepository { Task SaveAsync(Order order); }
public sealed class PlaceOrder(IOrderRepository repo) {
public async Task ExecuteAsync(Order order) {
order.ValidateStock();
await repo.SaveAsync(order);
}
}
Java
interface OrderRepository { void save(Order order); }
final class PlaceOrder {
private final OrderRepository repo;
PlaceOrder(OrderRepository repo) { this.repo = repo; }
void execute(Order order) {
order.validateStock();
repo.save(order);
}
}
اشتباه رایج
معماری تمیز الزام به ساخت دهها Interface برای هر جدول نیست. در برنامه کوچک ممکن است پیچیدگی اضافه ایجاد کند. ارزش آن زمانی بیشتر است که منطق دامنه مهم، چرخه عمر طولانی و چند منبع یا چند فریمورک داشته باشید.
اصطلاحات مرتبط: معماری ششضلعی، طراحی دامنهمحور، ریپازیتوری پترن، تزریق وابستگی، اصول سالید، کلین کد.
برای تکمیل این بحث، صفحه معماری نرمافزار را نیز ببینید.