Chapter 2 Flashcards — Discerning Coupling in Software Architecture
flashcards saht coupling architecture-quantum dynamic-coupling static-coupling
What is an architecture quantum, and what three properties define it?
?
An architecture quantum is the smallest unit of architecture that can be independently deployed while delivering meaningful business value. It is defined by three properties: (1) High functional cohesion — its parts work together toward a unified purpose; (2) Independent deployability — it can be deployed without deploying other quanta; (3) High static coupling within — it contains everything it needs to function. Notably, high internal coupling is a feature of a quantum, not a flaw.
Why is “high static coupling” listed as a positive property of an architecture quantum?
?
Because a quantum is supposed to include everything it needs to function. If a quantum has to reach into another quantum to operate, it is not truly independently deployable. High internal static coupling means the quantum is self-contained — all its dependencies are bundled within its boundary. The problem is coupling between quanta, not within them.
How many architecture quanta does a monolith have, and why?
?
A monolith has one quantum. All functionality is deployed together as a single unit, shares a single database, and fails or succeeds as a whole. It satisfies all three quantum properties as a single unit: it is highly cohesive internally, independently deployable (from an external perspective), and has all its dependencies within itself. The cost is that this single quantum cannot be scaled, deployed, or evolved in parts.
What is the difference between static coupling and dynamic coupling?
?
Static coupling exists at build/compile time — it is visible in the dependency graph (imports, library dependencies, shared schemas, API contracts). It constrains what can be independently deployed. Dynamic coupling exists at runtime — it is how components communicate, what consistency they require, and how they coordinate. It cannot be read from source code alone. A system can be statically decoupled (separate services) yet dynamically highly coupled (synchronous calls with atomic transactions).
What is afferent coupling, and what does high afferent coupling imply about a component?
?
Afferent coupling (Ca) is the number of components that depend on a given component — incoming dependencies. High afferent coupling means many things depend on you, which implies high stability and high importance: you are hard to change because changing you would break many dependents. Stable, foundational components (like domain entities or shared utilities) should have high afferent coupling.
What is efferent coupling, and what does high efferent coupling imply about a component?
?
Efferent coupling (Ce) is the number of components that a given component depends on — outgoing dependencies. High efferent coupling means you depend on many things, which implies high fragility: any of your dependencies failing, changing, or being unavailable can break you. The instability metric I = Ce / (Ca + Ce) captures this: I = 1 means maximally unstable (many outgoing, no incoming dependencies).
What is the instability metric, and what are its extremes?
?
Instability I = Ce / (Ca + Ce), where Ce is efferent coupling (outgoing) and Ca is afferent coupling (incoming). I = 0 means maximally stable: many things depend on you, you depend on nothing. I = 1 means maximally unstable: you depend on many things, nothing depends on you. Good architecture directs coupling from unstable components toward stable ones — unstable components should depend on stable ones, not the reverse.
What are the three dimensions of dynamic coupling in distributed systems?
?
Dynamic coupling has three orthogonal binary dimensions: (1) Communication style: synchronous vs. asynchronous — does the caller block waiting for a response? (2) Consistency model: atomic vs. eventual — must all operations succeed or fail together? (3) Coordination style: orchestrated vs. choreographed — is there a central coordinator, or do services react to events independently? These three dimensions produce 2 × 2 × 2 = 8 possible combinations.
What is temporal coupling, and which communication style creates it?
?
Temporal coupling is the dependency between a caller and callee’s availability at the same moment in time. Synchronous communication creates temporal coupling: if Service B is unavailable, Service A’s operation fails because A is blocked waiting for B’s response. Asynchronous communication breaks temporal coupling — the caller sends a message to a queue and continues executing, regardless of whether the callee is currently available.
What are the key trade-offs of synchronous vs. asynchronous communication?
?
Synchronous: Simple to reason about, immediate response, easy to debug — but creates temporal coupling (caller fails if callee is unavailable), additive latency (caller waits for every hop), and cascading failure risk. Asynchronous: Resilient to callee unavailability, caller unblocked, higher throughput — but requires complex error handling (dead-letter queues, idempotency), eventual consistency, and harder distributed tracing. Neither is universally better; choose based on whether the caller genuinely needs the result immediately.
What does atomic consistency mean in a distributed system, and what is its cost?
?
Atomic consistency means all operations in a distributed transaction either all succeed or all fail together — at any moment, all consumers see the same state. Its cost: it requires distributed coordination (locks, two-phase commit, or sagas with rollback), which reduces availability (coordination can block if a participant is slow/failed) and reduces performance (coordination overhead on every write). It maps to the “C” in ACID and is expensive to achieve across service boundaries.
What is eventual consistency, and when is it an acceptable choice?
?
Eventual consistency means updates propagate asynchronously; different parts of the system may temporarily have different views of the data, but the system will converge to consistency eventually. It is acceptable when: (1) temporary data divergence is tolerable for the business (e.g., showing a slightly stale product count), (2) high availability is more important than strong consistency, and (3) the system operates at a scale where coordination is prohibitively expensive. It is not acceptable when data correctness is non-negotiable (e.g., financial debits/credits).
What is orchestrated coordination in distributed systems?
?
Orchestrated coordination uses a central orchestrator (saga orchestrator, workflow engine) that directs all participating services — telling each what to do and when, and managing failures centrally. The orchestrator knows the entire workflow. Benefit: workflow is explicit and visible; error handling and compensation are centralized. Cost: the orchestrator is a single point of change (any workflow modification requires changing the orchestrator), and all services are coupled to it.
What is choreographed coordination in distributed systems?
?
Choreographed coordination has no central coordinator. Each service reacts to events it receives and emits new events in response. Workflow emerges from the collective reactions of services. Benefit: services are maximally decoupled — adding or removing a service does not require changing others, just subscribing/unsubscribing to events. Cost: the overall workflow is implicit (no single place shows the full flow), making it hard to debug and audit. Can devolve into “choreography hell” with complex systems.
What is “choreography hell,” and how does it arise?
?
Choreography hell is the state where a choreographed event-driven system has become so complex that no one can understand the full workflow. It arises when: many services each react to many events and emit many other events; the causal chain between an initial trigger and a final outcome spans dozens of event hops; and no single artifact (code file, diagram, or service) captures the complete business process. It is the choreography equivalent of spaghetti code — technically decoupled, but cognitively impenetrable.
Which combination of dynamic coupling is characteristic of the “distributed monolith” anti-pattern?
?
Synchronous + Atomic + Orchestrated (Combination 1). Services call each other synchronously, expect atomic (all-or-nothing) results, and a central coordinator manages the flow. Despite being deployed as separate services, they behave as one: if any service in the chain is unavailable, the whole operation fails; all services must be deployed in compatible versions simultaneously; the system loses the primary benefits of distributed architecture while retaining all its costs.
What combination of dynamic coupling characterizes the saga orchestrator pattern?
?
Asynchronous + Atomic + Orchestrated (Combination 5). A central saga orchestrator coordinates a multi-step workflow via asynchronous messages. Each step is triggered by a message; if a step fails, the orchestrator issues compensating transactions to undo previous steps. This achieves distributed “atomic” semantics (all-or-nothing business outcome) without requiring distributed locks, using compensation instead of rollback. It is the most common approach to distributed transactions in microservices.
What combination of dynamic coupling characterizes pure event-driven architecture?
?
Asynchronous + Eventual + Choreographed (Combination 8). Services communicate entirely through events; there is no central coordinator; and the system tolerates temporary data inconsistency. This provides maximum decoupling and resilience — services can be unavailable without blocking others — but requires developers to handle eventual consistency, idempotency, out-of-order events, and emergent workflow complexity. It is the pattern used in event sourcing and CQRS systems.
What is connascence, and why is it a useful vocabulary for coupling?
?
Connascence describes the relationship between two components that must change together when one changes. It is more precise than “coupled” because it identifies what must match. Static connascence (visible in code): Name (shared identifiers), Type (shared types), Meaning (shared value semantics), Algorithm (shared computation). Dynamic connascence (at runtime): Execution (order matters), Timing (timing matters), Values (related values), Identity (same instance). In distributed systems, connascence of values and connascence of identity are most dangerous — they require cross-service synchronization.
What is shared database coupling, and why is it particularly dangerous in distributed architectures?
?
Shared database coupling occurs when multiple services read from and write to the same database schema. It is dangerous because: (1) It makes independent schema evolution impossible — changing a table used by Service A may break Service B; (2) It couples deployments — schema migrations must be coordinated across all services that share the schema; (3) It violates data ownership — no single service owns its data, so business rules about that data are scattered; (4) It makes it impossible to scale, replicate, or replace a service’s storage independently.
How does the CAP theorem relate to the atomic vs. eventual consistency choice in distributed systems?
?
The CAP theorem states that a distributed system cannot simultaneously guarantee Consistency, Availability, and Partition tolerance — only two of three. Atomic consistency requires distributed coordination, which reduces availability (a coordinator failure can block the system) — trading A for C. Eventual consistency allows the system to remain available during partitions — trading C for A + P. The choice between atomic and eventual consistency is therefore a choice about which CAP property to sacrifice when the network partitions.
What makes two components effectively one quantum even if deployed as separate services?
?
Two services form one effective quantum if: (1) they must always be deployed together because an API or schema change in one requires a simultaneous change in the other; (2) they share a database, so a schema change in one affects the other’s queries; or (3) one calls the other synchronously and depends on the response to complete its own operation — meaning a failure in one causes a failure in the other. Independent deployability requires that both the static and dynamic coupling between components be minimal.
How does asynchronous communication break availability coupling between services?
?
With synchronous communication, Service A’s availability is tied to Service B’s: if B is down, A’s request fails immediately. With asynchronous communication via a queue or broker, A sends a message to the broker and continues executing — even if B is currently down. B processes the message when it comes back online. The broker acts as a buffer that decouples the availability of A from the availability of B. The cost is that A cannot know immediately whether B succeeded; error handling must be asynchronous.
What is the Sysops Squad’s current state in terms of quanta, and what questions does Chapter 2 raise about its target state?
?
The current state is a single quantum: monolith with shared database, all functionality deployed together. Chapter 2 raises four key questions for the target distributed architecture: (1) What are the natural quantum boundaries (which functionality belongs together)? (2) What static coupling exists between candidate quanta (shared data, shared libraries)? (3) What dynamic coupling style should be used between quanta (sync/async, atomic/eventual, orchestrated/choreographed)? (4) What consistency is required — e.g., if ticket creation succeeds but routing fails, must ticket creation also fail? These questions guide all subsequent decomposition decisions in the book.
Why can a system be statically decoupled but dynamically tightly coupled?
?
Static coupling is about build-time dependencies (imports, schemas, library versions) — these can be eliminated by running services in separate processes with no shared code or database. But dynamic coupling is about what happens at runtime: if Service A synchronously calls Service B and waits for an atomic response before proceeding, they are tightly coupled at runtime even if they share no code. They fail together under B’s unavailability; they must be deployed in compatible versions; they are effectively a single unit of failure. Static and dynamic coupling are independent dimensions that must both be evaluated.
Total Cards: 25
Priority: HIGH
Last Updated: 2026-05-30