Domain-Driven Design
info
Fluvius Framework is built on Domain-Driven Design (DDD) principles to help you build maintainable, scalable applications.
What is Domain-Driven Design?
Domain-Driven Design is an approach to software development that focuses on:
- Domain Logic: Business rules and logic are the heart of the application
- Ubiquitous Language: Code and business use the same terminology
- Bounded Contexts: Clear boundaries between different parts of the system
- Aggregates: Clusters of related entities treated as a single unit
Core Concepts in Fluvius
Domain
A Domain represents a bounded context in your application. Each domain encapsulates:
- Business logic and rules
- State management
- Command processing
- Event generation
from fluvius.domain import Domain
class UserDomain(Domain):
__aggregate__ = UserAggregate
class Meta:
revision = 1
tags = ["user", "identity"]
Aggregate
An Aggregate is a cluster of related entities treated as a single unit. It:
- Enforces business invariants
- Manages state transitions
- Generates domain events
from fluvius.domain import Aggregate, action
class UserAggregate(Aggregate):
@action(evt_key='user-created', resources=['user'])
async def create_user(self, name: str, email: str):
# Business logic here
pass
Commands
Commands represent intentions to change state. They are:
- Immutable
- Validated before processing
- Processed by aggregates
command = domain.create_command('create-user', {
'name': 'John Doe',
'email': '[email protected]'
})
Events
Events represent things that have happened. They are:
- Immutable facts
- Generated by aggregates
- Stored in event log
@action(evt_key='user-created')
async def create_user(self, name: str, email: str):
# Event 'user-created' is automatically generated
pass
State Manager
The State Manager provides:
- Read access to current state
- Transaction management
- Query capabilities
# Fetch current state
user = await domain.statemgr.fetch('user', user_id)
# Query state
users = await domain.statemgr.find('user', active=True)
Benefits of DDD in Fluvius
- Clear Boundaries: Domains provide clear boundaries between contexts
- Testability: Aggregates can be tested in isolation
- Scalability: Each domain can scale independently
- Maintainability: Business logic is centralized and easy to find
- Event Sourcing: Built-in event log for audit and replay
Best Practices
- Keep Aggregates Small: Focus on a single business concept
- Use Actions for State Changes: Always use
@actiondecorator - Validate in Aggregates: Enforce business rules in aggregate methods
- Use Events for Side Effects: Don't perform side effects in aggregates
- Keep Domains Focused: Each domain should have a clear purpose
Next Steps
- Learn about CQRS Pattern
- Explore Event Sourcing
- Read the Domain Module Guide