diff --git a/docs/design-principles/0170-eventing.md b/docs/design-principles/0170-eventing.md index c53ef549..09a8c28a 100644 --- a/docs/design-principles/0170-eventing.md +++ b/docs/design-principles/0170-eventing.md @@ -6,21 +6,24 @@ Eventing is the gateway to Event Driven Architecture (EDA), but it starts in the 1. We want all DDD aggregates to utilize "domain events" to drive use cases, irrespective of whether we are sourcing/capturing their current state from events (a.k.a Event Sourcing) or sourcing/capturing their current state from data snapshots (i.e. traditional record persistence). 2. For [event-sourcing persistence schemes](0070-persistence.md) (that are by definition "write models" only), we need to build associated "read models" so that we can query domain aggregates. -3. We want the flexibility to change our "read models" at any time, as the software changes, and ideally not have lost any data. -4. We may want denormalized data models to query for maximum efficiency. +3. We want the flexibility to add/change our "read models" at any time, as the software changes, and not have lost any data, and ideally re-create views of the data not previously seen (not persisted) in the past. +4. We want to use denormalized views of data to query for maximum efficiency (i.e. without complex joins). 5. We want to de-couple subdomains from each other as much as possible. Even for subdomains that are highly-coupled to begin with (e.g., `EndUsers` and `Organizations` and `Subscriptions`. -6. We want to deploy certain groups of subdomains into separate hosts and split the modular monolith into many APIs (i.e., micros-services) later in the lifecycle of the product, but not have to re-engineer flows to accommodate those changes. -7. We want the flexibility to make changes to key use cases in the product, without changing multiple subdomains at the same time. -8. We want to be able to communicate across process boundaries without coupling the processes. +6. We want to deploy certain groups of subdomains into separate hosts and split the modular monolith into many independent hosts (i.e., micros-services) later in the lifecycle of the product, but not have to re-engineer flows to accommodate those changes. +7. Sending imperative "commands" (i.e. API calls) between different API's is by its nature unreliable, and it encourages coupling (and assumptions) in many subtle ways for the software designer. We want to try to minimize that. +8. We want the flexibility to make changes to key use cases in the product, without changing multiple subdomains at the same time. +9. We want to be able to communicate across process boundaries without coupling the processes. ## Implementation In the design of most distributed systems, of the nature of this system (or of systems that are expected to evolve into distributed systems later) it is common practice to decouple each of the subdomains from each other. De-coupling effectively is absolutely vital to allowing the system to change independently, grow, and evolve over time. -> This is the whole point of having a single direction of dependencies, from: Infrastructure components -> Domain components. +> Decoupling is the whole point of having a single direction of dependencies, from: Infrastructure components -> Domain components. Coupling is the primary cause of the "accidental complexity" that software designers put into their code, in small incremental steps. Lack of effective de-coupling (at the technical level) is the main reason most software systems devolve into big-balls-of-mud, simply because of the coupling of many components to many other components often striving for maximum data and code reuse. +> Code re-use is a useful technique to combat the problem of not having to update multiple places in the code/system that share the same precise behaviour/context. But this technique (and blind pursuit of it) is also the primary cause of coupling when components, that have distinct behaviour, are changed and their behaviour/context diverges. Knowing the difference is an important skill to develop. Being DRY is not the goal, it is a precision tool that needs to be applied carefully. + There are several techniques for de-coupling your subdomains, including: separating layers, using ports and adapters, starting with a modular monoliths and decomposing it into microservices later etc. Another one of these techniques is the use of Event-Driven Architecture (EDA), where change is communicated within process boundaries, and across process boundaries.