skip to content

As a tech lead, when would you avoid introducing a Mediator, and what alternatives would you weigh?

level: principalimportance: nice to knowfreq 25%

answer

  1. Don't mediate trivial/stable interaction graphs (YAGNI/KISS)
  2. Never one god mediator for a whole subsystem
  3. Alternatives: direct calls, event bus/pub-sub, presenter/state machine, many small mediators
  4. Axes: complexity & change rate, central control vs. traceability, cohesion, team fit
  5. Event bus = loose many-to-many but opaque flow

basics

~20 s

Avoid a Mediator when objects barely interact — the extra indirection just adds a class and hides simple calls. Also avoid one giant mediator for a whole system. Alternatives: keep direct calls when simple, or use an event bus for loose, many-to-many communication.

solid answer

~60 s

Mediator pays off when several objects interact in genuinely complex, interdependent ways and you want that logic centralized and reusable. It is over-engineering when the interactions are few or simple: you add an indirection layer that obscures otherwise-obvious direct calls and gives nothing back. As a lead I'd also avoid a single mediator spanning an entire screen or subsystem, since that's the fast track to a god object. The main alternatives to weigh: (1) plain direct references when the graph is small and stable — simplest, no ceremony; (2) Observer/event bus / pub-sub when you want decentralized many-to-many notification without a central authority owning all the rules — better for cross-module or cross-service decoupling, at the cost of harder-to-trace flow; (3) presenter/controller (MVP/MVVM) or a state machine/reducer for UIs, which is a more disciplined form of mediation; (4) splitting into several small, cohesive mediators rather than one big one. The decision hinges on interaction complexity, how often it changes, the need for centralized control vs. traceability, and team conventions.

go deeper

for a junior

Understands that adding a mediator for very simple interactions is unnecessary extra structure.

for a middle

Can name when Mediator helps (complex interdependent interactions) vs. when direct calls suffice.

for a senior

Weighs Mediator against Observer/event bus and presenter patterns and articulates the god-object scoping limit.

for a principal

Reasons across the full trade-off space (complexity/change rate, central control vs. traceability, cohesion, team conventions, testability) and sets guidance on when to mediate, when to use an event bus, and how to scope mediators across a codebase.

## Framing the decision Mediator is a tool, not a goal. A **mediator** centralizes the interaction logic of a set of **colleagues** so they don't reference each other. That indirection has a *cost* (an extra class, a layer of misdirection, a class that tends to grow) and a *benefit* (decoupled, reusable colleagues; one place for complex coordination logic). A lead's job is to apply it only where benefit > cost. ## When to avoid it (over-engineering signals) - **Few or simple interactions.** If two or three objects call each other in obvious ways, a mediator replaces clear direct calls with `a.notify() → mediator → b.update()` indirection that *adds* cognitive load without untangling anything. This is **YAGNI** ("You Aren't Gonna Need It") and **KISS** ("Keep It Simple") territory — don't add structure for complexity that isn't there. - **A stable, small dependency graph.** The pattern earns its keep when interactions are many and change often. If the graph is small and rarely changes, direct references are fine. - **One mediator for everything.** Avoid a single mega-mediator covering a whole screen/subsystem — that is the god-object trap; prefer several small mediators or none. - **You actually want decentralized routing.** If the real need is loose, many-to-many, cross-module communication where no single object should own all the rules, a centralized mediator is the wrong shape — an event-driven approach fits better. ## Alternatives to weigh 1. **Direct references (no pattern).** Simplest; best when the interaction graph is small and stable. Cost: re-couples objects, so it scales badly as interactions multiply. 2. **Observer / event bus / pub-sub.** Decentralized many-to-many notification: publishers emit events, subscribers react, nobody owns a central rulebook. Great for cross-module/cross-service decoupling and extensibility. Cost: control flow is implicit and harder to trace/debug; ordering and cycles can surprise you; no single place that documents "what reacts to what." 3. **Presenter / controller (MVP, MVVM) or state machine / reducer.** For UIs especially, these are *disciplined* mediators: a presenter coordinates view and model with a clearer contract; a state machine/reducer makes transitions explicit and testable. Often preferable to a hand-rolled ad-hoc mediator as complexity grows. 4. **Multiple small mediators (hierarchical).** Keep the pattern but scope each mediator to a cohesive cluster, with a thin top-level coordinator. Retains centralized coordination per cluster while avoiding the monolith. ## The trade-off axes a lead reasons over - **Interaction complexity & change rate**: high and volatile → centralizing in a mediator (or presenter) pays off; low and stable → direct calls. - **Centralized control vs. traceability**: Mediator gives one readable place for rules but can bloat; event bus gives loose coupling but opaque flow. Pick per the system's debuggability needs. - **Scope/cohesion**: never one god mediator; size mediators to cohesive clusters. - **Team conventions & testability**: which structure your team can maintain, review, and test consistently often outweighs theoretical purity. ## Bottom line Reach for a Mediator when a cohesive group of objects has genuinely complex, evolving, two-way interactions you want in one place. Avoid it for trivial interactions (use direct calls), for system-wide loose coupling (use an event bus), and for UIs that fit a presenter/state-machine model better — and never let it become a single god object.

  • What do you lose by choosing an event bus over a Mediator?
    You lose a single, readable place that documents which reactions follow which events — control flow becomes implicit and harder to trace and debug, and ordering or cyclic-notification surprises become easier. You gain looser, decentralized many-to-many coupling and easier extension, with no central object owning all the rules (and no god-object risk).
  • Is a presenter (MVP/MVVM) really just a Mediator?
    It plays a similar coordinating role — sitting between view and model and centralizing interaction logic — so it's a disciplined, well-scoped form of mediation. The difference is the clearer contract and conventions: a presenter has a defined responsibility boundary and is easier to test, which guards against the ad-hoc god-object drift of a hand-rolled mediator.

saying these in an interview costs you the question

  • Applying Mediator reflexively to any group of objects regardless of interaction complexity.
  • Treating Mediator and event bus as interchangeable — they differ on central control vs. traceability.
  • Ignoring the god-object risk when scoping the mediator to an entire subsystem.
  • Adding indirection for interactions that are few, simple, and stable (violates YAGNI/KISS).

context