Worked example — a repository defined as a typing.Protocol.
Python's Protocol (PEP 544) lets the domain declare a shape without importing anything from infrastructure. Any class with matching methods automatically satisfies it — duck typing, type-checked:
from typing import Protocol
from uuid import UUID
from .order import Order # the aggregate root we defined earlier
class OrderRepository(Protocol):
"""Collection-like interface for the Order aggregate."""
def get(self, order_id: UUID) -> Order: ...
def add(self, order: Order) -> None: ...
def remove(self, order: Order) -> None: ...
Three things to notice:
- Each method body is just
... — Protocols are interfaces, not implementations.
- The interface lives in the domain package; a
SqlOrderRepository (in infrastructure) implements it without inheriting from it.
- The repository deals only in aggregate roots — there is no
OrderLineRepository because OrderLine cannot exist outside an Order.
Fill in the playground below with the same three methods.