Some notes about DDD
@dataclass(frozen=True)for value objects
- For entities (objects with long lived identity, aka Reference Objects) use a normal class and implement
- Don’t use
BarManagerclasses, just functions
.commit()as a responsibility for the caller.
- For simple cases this abstraction is unnecessary, you can just stick with ORMs.
- Create an in-memory
Some people consider “monkeypatching” a code smell and prefer using Fakes.
- Pass the repository as a parameter to service-layer functions and use primitives instead of Domain objects.
- Leave endpoints as a thin wrapper for parsing and returning HTTP responses, but you can combine controller/views if it is just a web app.
- Write tests for the service layer.
Unit of Work
- Use context manager and initialize the repository on
commitis recommended for easier state flushing.
uowto the service layer.
Aggregates and Consistency Boundaries
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes.
- Configure version counters for Optimistic Concurrency Control.
- Retry on conflict.
- The only repository that should be used is the one for the aggregate.
Part 1: https://github.com/cosmicpython/code/tree/chapter_07_aggregate
Events and Message Bus
- To avoid violating the single responsibility principle, use events instead of commands.
- A message bus is a dict that maps event types to a list of handlers.
- Rethink API calls as capturing events.
- Services will have only 2 params: the event and the uow.
If at first you don’t succeed, retry the operation with an exponentially increasing back-off period.
- Commands are usually imperative verbs and expect a response.
- Events are usually past-tense verbs and broadcasted.
- Use an external message broker (redis, kafka, rabbitmq).
- Two services should accept eventual consistency between them.
- Avoid the Distributed Big Ball of Mud, think in terms of verbs / business processes with asynchronous communication.
Command-Query Responsibility Separation (CQRS)
- Create thin views for our data: via raw SQL?? (repository are clunky and ORMs slow).
Dependency Injection (DI)
- Dependency Injection vs Monkeypatching.