Repository Pattern یا ریپازیتوری پترن یک مرز بین منطق دامنه و جزئیات دسترسی به داده ایجاد میکند. سرویس ثبت سفارش به قراردادی مانند OrderRepository وابسته میشود، نه لزوماً به مدل ORM یا کوئری SQL. این الگو برای همه پروژههای CRUD الزامی نیست.
PHP: قرارداد و پیادهسازی با Eloquent
interface OrderRepository {
public function find(int $id): ?Order;
}
class EloquentOrderRepository implements OrderRepository {
public function find(int $id): ?Order {
return Order::find($id);
}
}
class OrderService {
public function __construct(private OrderRepository $orders) {}
public function get(int $id): ?Order { return $this->orders->find($id); }
}
// In AppServiceProvider::register()
$this->app->bind(OrderRepository::class, EloquentOrderRepository::class);
Python: پروتکل و پیادهسازی
from typing import Protocol
class OrderRepository(Protocol):
def find(self, order_id: int): ...
class SqlOrderRepository:
def __init__(self, connection): self.connection = connection
def find(self, order_id):
return self.connection.execute(
'SELECT id, total FROM orders WHERE id = ?', (order_id,)
).fetchone()
C# با Entity Framework Core
public interface IOrderRepository { Task<Order?> FindAsync(int id); }
public sealed class EfOrderRepository(AppDbContext db) : IOrderRepository {
public Task<Order?> FindAsync(int id) => db.Orders.FindAsync(id).AsTask();
}
// Program.cs
builder.Services.AddScoped<IOrderRepository, EfOrderRepository>();
مزیت و هزینه
| مزیت | هزینه |
|---|---|
| جدا کردن وابستگی سرویس از دیتابیس | کلاس و Interface بیشتر |
| امکان جایگزینی پیادهسازی در تست | احتمال ساخت abstraction تکراری بر ORM |
| کنترل کوئریهای تخصصی در یک مرز | امکان پنهان شدن قابلیتهای کاربردی ORM |
نکته فنی
اگر فقط تمام متدهای ORM را یکبهیک در ریپازیتوری کپی میکنید، ممکن است لایه تازه ارزشی اضافه نکند. ابتدا مرز دامنه و سناریوهای تغییر واقعی را مشخص کنید.
اصطلاحات مرتبط: اینترفیس، سرویس کانتینر، سرویس کانتینر، تزریق وابستگی، معماری تمیز، واحد کار، الوکوئنت.