1. What is the difference between coupling and cohesion? What is the target state for each at component boundaries?
2. Name the five coupling types described in this chapter, from weakest to strongest. Give a one-sentence description of each.
3. What are the two code smells that signal coupling problems in practice? Describe what each looks like.
Classify the coupling type in each of the following scenarios:
(a) sendEmail(recipient, subject, body) — only these fields
are passed; (b) generateReport(user: User) where the
function only uses user.email and user.name;
(c) a class reads from a global FEATURE_FLAGS dictionary;
(d) process(data, skipValidation=True). For each, identify
the coupling type and describe the minimum refactoring to weaken
it.
A UserService class contains:
createUser, sendWelcomeEmail,
updatePassword, writeUserCreationToAuditLog,
calculateUserRiskScore. Which methods belong in
UserService? Which belong elsewhere? Organise them by
cohesion and describe what new components you would create.
Identify the code smell in this design:
OrderService.calculateTotal(order) reads
order.customer.taxRegion,
order.customer.discountTier, and
order.customer.memberSince. Name the smell and describe the
fix.
A complete answer will: (1) name the coupling type for each approach: (a) direct calls create connascence of execution and connascence of identity — the notification service must know the API shape of all five source services and call them in a specific order; (b) event subscription creates connascence of meaning only (shared event schema) — the notification service depends on the event structure, not on the source services’ internal APIs, (2) name AT8 (Coupling/Cohesion) as the governing tradeoff: direct calls are tighter coupling (easier to trace, lower latency) but higher change impact (if any source service changes its API, notification service must change too); event subscription is looser coupling (each service evolves independently) but harder to trace and adds event broker complexity, (3) name FM2 (cascading failure) for approach (a): if any of the five source services is down, the notification service cannot issue notifications for that event type — a failure in the payments service silences payment notifications; for approach (b), name FM4 (stale data): if the event broker is slow, notifications are delayed but the notification service remains operational, and (4) recommend approach (b) for this specific design and justify: five source services with independent release cycles create too many synchronous coupling points for approach (a) to maintain safely — the number of breaking changes scales with the number of source services, making event subscription the correct choice at this fan-in count.
Customer object used by billing,
support, marketing, and logistics. Each team needs slightly different
fields and methods. Propose a design that gives each team what it needs
without creating a single 500-line Customer class that
changes for every team’s reasons. Name the principle you are applying,
the tradeoffs, and where coupling is unavoidable.A complete answer will: (1) apply the Interface Segregation
Principle (or DDD bounded context decomposition): define separate
BillingCustomer, SupportCustomer,
MarketingCustomer, and LogisticsCustomer
types, each containing only the fields and methods relevant to that
team’s domain — each type is owned by the team that uses it and changes
only when that team’s requirements change, (2) name AT8
(Coupling/Cohesion): segregated types reduce the blast radius of changes
(billing changes do not affect support) but increase the total amount of
code and require a mapping layer when data must cross boundaries — state
the conditions under which the added mapping complexity is worth the
reduced coupling, (3) identify where coupling is unavoidable: all four
types share the same customer identity (customer ID, name, contact
information) — this shared identity creates connascence of meaning that
cannot be eliminated without duplicating the identity concept; propose a
CustomerIdentity type owned by a shared domain layer that
all four bounded contexts import, and (4) name FM8 (silent semantic
drift) as the failure mode when the four types diverge: if billing’s
Customer.address and logistics’
Customer.address are separately maintained and drift apart
(different validation rules, different field names), data
inconsistencies accumulate silently — state the synchronisation
mechanism (e.g., shared identity events or a read-model projection) that
keeps identity data consistent across bounded contexts.