Recent Posts
Archives

Posts Tagged ‘Siriona’

PostHeaderIcon [DevoxxFR2013] Distributed DDD, CQRS, and Event Sourcing – Part 1/3: Time as a Business Core

Lecturer

Jérémie Chassaing is an architect at Siriona, focusing on scalable systems for hotel channel management. Author of thinkbeforecoding.com, a blog on Domain-Driven Design, CQRS, and Event Sourcing, he founded Hypnotizer (1999) for interactive video and BBCG (2004) for P2P photo sharing. His work emphasizes time-centric modeling in complex domains.

Abstract

Jérémie Chassaing posits time as central to business logic, advocating Event Sourcing to capture temporal dynamics in Domain-Driven Design. He integrates Distributed DDD, CQRS, and Event Sourcing to tackle scalability, concurrency, and complexity. Through examples like order management, Chassaing analyzes event streams over relational models, demonstrating eventual consistency and projection patterns. The first part establishes foundational shifts from CRUD to event-driven architectures, setting the stage for distributed implementations.

Time’s Primacy in Business Domains

Chassaing asserts time underpins business: reacting to events, analyzing history, forecasting futures. Traditional CRUD ignores temporality, leading to lost context. Event Sourcing records immutable facts—e.g., OrderPlaced, ItemAdded—enabling full reconstruction.

This contrasts relational databases’ mutable state, where updates erase history. Events form audit logs, facilitating debugging and compliance.

Domain-Driven Design Foundations: Aggregates and Bounded Contexts

DDD models domains via aggregates—consistent units like Order with line items. Bounded contexts delimit scopes, preventing model pollution.

Distributed DDD extends this to microservices, each owning a context. CQRS separates commands (writes) from queries (reads), enabling independent scaling.

CQRS Mechanics: Commands, Events, and Projections

Commands mutate state, emitting events. Handlers project events to read models:

case class OrderPlaced(orderId: UUID, customer: String)
case class ItemAdded(orderId: UUID, item: String, qty: Int)

// Command handler
def handle(command: AddItem): Unit = {
  // Validate
  emit(ItemAdded(command.orderId, command.item, command.qty))
}

// Projection
def project(event: ItemAdded): Unit = {
  updateReadModel(event)
}

Projections denormalize for query efficiency, accepting eventual consistency.

Event Sourcing Advantages: Auditability and Scalability

Events form immutable logs, replayable for state recovery or new projections. This decouples reads/writes, allowing specialized stores—SQL for reporting, NoSQL for search.

Chassaing addresses concurrency via optimistic locking on aggregate versions. Distributed events use pub/sub (Kafka) for loose coupling.

Challenges and Patterns: Idempotency and Saga Management

Duplicates require idempotent handlers—e.g., check event IDs. Sagas coordinate cross-aggregate workflows, reacting to events and issuing commands.

Chassaing warns of “lasagna architectures”—layered complexity—and advocates event-driven simplicity over tiered monoliths.

Implications for Resilient Systems: Embracing Eventual Consistency

Event Sourcing yields antifragile designs: failures replay from logs. Distributed CQRS scales horizontally, handling “winter is coming” loads.

Chassaing urges rethinking time in models, shifting from mutable entities to immutable facts.

Links: