The repository pattern gives the application a stable interface for data access. The service layer depends on an abstraction instead of depending directly on a database library.
export interface OrderRepository {
findById(id: string): Promise<Order | null>;
save(order: Order): Promise<void>;
}
export class CreateOrderService {
constructor(private readonly orders: OrderRepository) {}
async execute(input: CreateOrderInput) {
const order = Order.create(input);
await this.orders.save(order);
return order;
}
}
Benefits
- The business layer becomes easier to test.
- Persistence technology can change with less impact.
- Domain logic stays away from SQL, ORM or driver-specific code.
export class PostgresOrderRepository implements OrderRepository {
async findById(id: string) {
const row = await db.order.findUnique({ where: { id } });
return row ? Order.fromPersistence(row) : null;
}
async save(order: Order) {
await db.order.upsert({
where: { id: order.id },
create: order.toPersistence(),
update: order.toPersistence()
});
}
}