Design Patterns

Junior Questions

Junior
1

What are DRY, KISS, and YAGNI?

  • DRY (Don't Repeat Yourself): Every piece of knowledge should have a single authoritative representation. Eliminate duplication via abstraction — but don't abstract premature similarities (WET: Write Everything Twice — duplicate once, then generalise).
  • KISS (Keep It Simple, Stupid): Simplest solution that works. Resist over-engineering. Complexity is the enemy of maintainability.
  • YAGNI (You Ain't Gonna Need It): Don't build features until they're actually needed. Avoid speculative abstractions.
  • These principles are in tension: DRY encourages abstraction; YAGNI discourages premature abstraction. Judgement is required.

What problems does this solve?

  • DRY/KISS/YAGNI are the most cited principles in code review — understanding the tensions between them shows engineering maturity.
Junior
2

What are Higher-Order Functions?

  • A Higher-Order Function (HOF) takes a function as an argument, returns a function, or both.
  • Built-in JS HOFs: Array.map, filter, reduce, sort.
  • Patterns: Currying (partial application), function composition, decorators, middleware.
  • Foundation of functional programming in JS — enables point-free style and reusable abstractions.

What problems does this solve?

  • HOFs are fundamental to functional JS — map/filter/reduce and function composition are the building blocks of clean, declarative code.
Junior
6

What are the SOLID principles?

  • S — Single Responsibility: A class/function should have one reason to change.
  • O — Open/Closed: Open for extension, closed for modification. Add behaviour by adding code, not changing existing code.
  • L — Liskov Substitution: Subtypes must be substitutable for their base types without altering correctness.
  • I — Interface Segregation: Clients shouldn't depend on interfaces they don't use. Prefer small, focused interfaces.
  • D — Dependency Inversion: Depend on abstractions, not concretions. High-level modules shouldn't depend on low-level modules.
  • SOLID guides object-oriented design but applies equally to functional and component-based code.

What problems does this solve?

  • SOLID is the most commonly asked design principles question — a confident answer shows architectural thinking beyond just writing working code.
Junior
17

What is the Factory pattern?

  • Factory provides an interface for creating objects without specifying their concrete classes. The factory decides which class to instantiate.
  • Factory Function (JS): A function that returns a new object — no new keyword needed.
  • Abstract Factory: A factory of factories — groups related object creation behind a single interface.
  • Use cases: Creating framework controls based on OS/platform, dependency injection containers, test doubles.

What problems does this solve?

  • Factory is the most practical creational pattern in JS — used constantly in framework internals and DI containers.
Junior
21

What is the Module pattern?

  • Module encapsulates related functionality into a self-contained unit, exposing only a public API and keeping internals private.
  • IIFE module (pre-ES6): Immediately-invoked function expression to create a closure with private scope.
  • ES modules (ES6+): Native module system — import/export. File scoping is private by default. Only exported names are public.
  • ES modules are the modern standard. Singletons by default.

What problems does this solve?

  • The evolution from IIFE modules to ES modules is a key JS history story — understanding both shows breadth.
Junior
27

What is the Singleton pattern?

  • Singleton ensures a class has only one instance and provides a global access point to it.
  • Use cases: Database connection pools, config objects, loggers, browser-side state stores.
  • In JavaScript: ES modules are singletons by default — the exported object is instantiated once and shared across all imports.
  • Pitfalls: Hidden global state makes code harder to test (can't easily swap the instance). Overuse leads to tight coupling.

What problems does this solve?

  • Singleton is the most recognisable pattern — understanding its pitfalls (global state, testability) is more important than just knowing its definition.

Mid-Level Questions

Mid
3

What are MVC, MVP, and MVVM?

  • MVC (Model-View-Controller): Model (data/logic), View (UI), Controller (handles input, updates model). Traditional server-rendered apps (Rails, Laravel). Controller mediates user actions.
  • MVP (Model-View-Presenter): View is passive. Presenter handles all UI logic and manipulates the view via an interface. Better testability — presenter tested without UI.
  • MVVM (Model-View-ViewModel): ViewModel exposes observable data/commands. View binds to ViewModel via two-way data binding. Angular, Vue, Knockout. No direct DOM manipulation needed.
  • React is closest to MVC — component is controller+view. Pinia/Redux is the model.

What problems does this solve?

  • MVC/MVVM comes up constantly in framework comparisons — knowing which paradigm each framework follows shows architectural context.
Mid
4

What are Render Props and Slots?

  • Render Props (React): A prop whose value is a function that returns JSX — the parent controls what gets rendered inside the child. Enables logic sharing without HOCs.
  • Slots (Vue): Vue's equivalent — named and scoped slots pass template fragments from parent to child, enabling the same flexible composition.
  • Both patterns are largely superseded by Custom Hooks (React) and Composables (Vue) for logic sharing, but still used for UI composition.

What problems does this solve?

  • Render Props and Slots represent the evolution of component composition before hooks — knowing them contextualises why hooks were introduced.
Mid
5

What are common anti-patterns to avoid?

  • God Object/Component — One class/component doing everything. Fix: decompose using SRP.
  • Spaghetti code — Tangled control flow with no clear structure. Fix: refactor to clear modules/functions.
  • Prop drilling — Passing props many levels deep. Fix: Context, state management library.
  • Premature optimisation — Optimising before profiling. "Premature optimisation is the root of all evil." — Knuth.
  • Magic numbers/strings — Unexplained literals. Fix: named constants.
  • Mutating props/external state directly — Breaks reactivity and predictability.
  • Callback hell — Deeply nested callbacks. Fix: async/await, Promises.
  • Cargo culting — Using patterns without understanding why (e.g., applying Redux to a simple counter app).

What problems does this solve?

  • Anti-patterns are as important as patterns — showing you recognise them and can refactor away is a hallmark of experienced engineers.
Mid
7

What is Dependency Injection?

  • DI is a technique where a component receives its dependencies from the outside rather than creating them itself — an implementation of Inversion of Control.
  • Benefits: Decoupling, easier testing (inject mocks), configurable.
  • In JS/React: Pass dependencies as props or function arguments. React Context provides implicit DI. Testing: pass mock stores/services as props.
  • Frameworks: Angular's DI system, NestJS's decorator-based IoC container.

What problems does this solve?

  • DI is the mechanism that makes code testable — showing you understand why it matters, not just what it is, is the senior signal.
Mid
9

What is the Adapter pattern?

  • Adapter converts the interface of a class into another interface the client expects — makes incompatible interfaces work together.
  • JS example: Wrapping a legacy API or third-party library so your code doesn't depend on its specific interface.
  • Also known as Wrapper. Commonly used when integrating third-party code or migrating legacy systems.

What problems does this solve?

  • Adapter is used every time you integrate a third-party library — recognising it as a named pattern helps reason about interfaces.
Mid
13

What is the Composite pattern?

  • Composite lets you compose objects into tree structures and treat both individual objects and compositions uniformly.
  • Classic example: File system (files and folders both support getSize()). React component tree (components can be leaves or contain other components).
  • Enables recursive structures where clients don't need to differentiate between simple and complex nodes.

What problems does this solve?

  • Composite explains the tree-shaped structure underlying component frameworks — recognising it shows conceptual depth.
Mid
14

What is the Compound Components pattern?

  • Compound Components is a React/Vue pattern where a set of components share implicit state through context, giving the consumer flexible control over layout and structure.
  • Examples: HTML's <select> + <option>. UI kit components: <Tabs>, <TabList>, <TabPanel>.
  • Avoids an explosion of props on a single component while still allowing customisation of internals.

What problems does this solve?

  • Compound Components is the gold standard for reusable, flexible UI components — showing you can design and implement them is a strong senior signal.
Mid
16

What is the Facade pattern?

  • Facade provides a simplified interface to a complex subsystem, hiding internal complexity from the client.
  • Examples: jQuery was a facade over complex DOM/AJAX APIs. SDK wrapper around multiple network calls. Service layer in a web app that orchestrates DB, cache, and email.
  • Reduces coupling between client code and complex subsystems.

What problems does this solve?

  • Facade is the pattern behind every good SDK and service layer — recognising it shows architectural awareness.
Mid
18

What is the Flux / Redux pattern?

  • Flux is a unidirectional data flow architecture: Action → Dispatcher → Store → View. Introduced by Meta to manage complex state in React apps.
  • Redux: Single global store, pure reducer functions, actions describe changes. Predictable, debuggable (time-travel), but verbose.
  • Redux Toolkit (RTK): Official, opinionated Redux — reduces boilerplate with createSlice, createAsyncThunk.
  • Key insight: Redux actions are the Command pattern applied to state management.
  • Pinia, Zustand, and Jotai are modern alternatives with far less ceremony.

What problems does this solve?

  • Flux/Redux defined how frontend state management evolved — understanding it contextualises every modern alternative.
Mid
19

What is the Iterator pattern?

  • Iterator provides a standard way to traverse a collection without exposing its internal structure.
  • In JS: Built into the language via the Iterator Protocol (Symbol.iterator). for...of, spread (...), destructuring all use it. Arrays, Maps, Sets, Strings, generators are all iterable.

What problems does this solve?

  • Iterator is baked into ES6+ — understanding it reveals how for...of, spread, and generators work under the hood.
Mid
22

What is the Observer pattern?

  • Observer defines a one-to-many dependency between objects so that when one object (subject) changes state, all its dependents (observers) are notified automatically.
  • JS examples: EventEmitter (Node.js), addEventListener, RxJS Observables, Vue's reactivity, Pinia subscriptions, Redux store subscribers.
  • vs Pub/Sub: Observer has direct subject-observer coupling. Pub/Sub uses a message broker (event bus) — observers don't know about the subject.

What problems does this solve?

  • Observer is the foundation of event-driven programming and reactivity — it appears in virtually every framework.
Mid
25

What is the Pub/Sub pattern?

  • Publishers emit events to a message bus/event channel. Subscribers register interest in event types. They are decoupled — publishers don't know about subscribers.
  • vs Observer: Observer has direct subject→observer coupling. Pub/Sub introduces an intermediary event channel.
  • Examples: Browser CustomEvents, Node.js EventEmitter used as event bus, Redis pub/sub, Kafka.
  • Trade-off: Very decoupled, but harder to trace event flows and debug (events "disappear into the bus").

What problems does this solve?

  • Pub/Sub is the backbone of cross-component communication and message queues — the distinction from Observer shows nuanced pattern knowledge.
Mid
26

What is the Repository pattern?

  • Repository mediates between the domain and data mapping layers, providing a collection-like interface for accessing domain objects.
  • Abstracts the data source (DB, REST API, localStorage) behind a consistent interface.
  • Benefits: Easy to swap data sources (e.g., real DB in prod, in-memory in tests). Centralises query logic.

What problems does this solve?

  • Repository is the standard pattern for data access in backend/full-stack JS — it's the bridge between business logic and persistence.
Mid
29

What is the Strategy pattern?

  • Strategy defines a family of algorithms, encapsulates each one, and makes them interchangeable. Lets the algorithm vary independently from the clients that use it.
  • JS example: Sorting strategies, payment methods, form validation rules, compression algorithms.
  • Eliminates conditionals — instead of if (method === 'credit') { ... }, pass the strategy as a function/class.

What problems does this solve?

  • Strategy is the pattern behind configuration-driven and extensible systems — it replaces complex switch/if chains with composable units.

Senior Questions

Senior
8

What is Inversion of Control?

  • Inversion of Control (IoC) is a principle where the framework calls your code rather than your code calling the framework — "Don't call us, we'll call you."
  • Frameworks implement IoC: React calls your component render functions; Express calls your route handlers; Angular calls lifecycle hooks.
  • DI is one form of IoC — control over dependency creation is inverted to a container.
  • IoC enables extensibility — plug in your code into defined extension points.

What problems does this solve?

  • IoC is the meta-principle that explains how frameworks work — understanding it reveals why all frameworks have lifecycle hooks and extension points.
Senior
10

What is the Builder pattern?

  • Builder separates the construction of a complex object from its representation, allowing the same process to create different results.
  • Useful when an object has many optional or ordered configuration steps.
  • Common in query builders, HTTP client configuration, test data factories.

What problems does this solve?

  • Builder's fluent/chaining interface is ubiquitous in JS libraries — recognising and implementing it is a practical skill.
Senior
11

What is the Chain of Responsibility pattern?

  • Pass a request along a chain of handlers — each handler decides to process the request or pass it to the next handler.
  • JS examples: Express/Koa middleware chains (next()), browser event propagation (capture/bubble), authentication middleware pipelines.

What problems does this solve?

  • Chain of Responsibility is what Express middleware is — naming the pattern connects everyday code to classic CS vocabulary.
Senior
12

What is the Command pattern?

  • Command encapsulates a request as an object, enabling parameterisation, queuing, logging, and undo/redo.
  • Structure: Command object with execute() and optionally undo(). Invoker calls commands. Receiver does the actual work.
  • Examples: Text editor undo/redo, Redux actions (each action is a command), task queues, macro recording.

What problems does this solve?

  • Redux is an implementation of the Command pattern for state management — recognising this connects React ecosystem knowledge to classic CS.
Senior
15

What is the Decorator pattern?

  • Decorator attaches additional responsibilities to an object dynamically without modifying its class — a flexible alternative to subclassing.
  • JS examples: TypeScript/Babel decorators (@), HOCs in React, middleware in Express (wrapping the next handler).
  • Respects the Open/Closed principle — adds behaviour without modifying the original.

What problems does this solve?

  • Decorator is fundamental to functional composition and middleware chains — it appears everywhere in modern JS codebases.
Senior
20

What is the Mediator pattern?

  • Mediator defines an object that coordinates communication between components, reducing direct dependencies between them.
  • Without mediator: Components communicate directly (tight coupling, combinatorial dependencies).
  • With mediator: Components communicate only with the mediator (event bus, message broker).
  • Examples: Event bus (Vue's $emit patterns), chat room (server as mediator between clients), air traffic control.

What problems does this solve?

  • Mediator is what underpins event buses and message brokers — it trades direct coupling for centralized coordination.
Senior
23

What is the Prototype pattern?

  • Prototype creates new objects by cloning an existing object (the prototype), rather than instantiating from a class.
  • In JavaScript: Prototype chain is the language's built-in mechanism. Object.create(proto) creates an object inheriting from proto. Structuring clone with spread: {'{ ...original, override }'}.
  • Use cases: Cloning complex configuration objects, undo/redo stacks (clone state before mutation), game entities.

What problems does this solve?

  • Prototype is JavaScript's native object system — understanding prototypal inheritance distinguishes JS-native thinking from class-centric thinking.
Senior
24

What is the Proxy pattern?

  • Proxy provides a surrogate or placeholder for another object to control access to it.
  • Types: Virtual proxy (lazy init), protection proxy (access control), caching proxy, logging proxy.
  • In JS: ES6 Proxy object intercepts operations (get, set, apply) on any object — used in Vue 3's reactivity system (wraps reactive objects to track/trigger updates).

What problems does this solve?

  • ES6 Proxy powers Vue 3's reactivity — understanding the pattern explains how modern frameworks track state changes.
Senior
28

What is the State pattern?

  • State allows an object to alter its behaviour when its internal state changes — the object appears to change its class.
  • Use cases: Traffic lights, vending machines, form wizard steps, UI state machines.
  • State machines (XState): Finite State Machines formalise state transitions — prevent invalid states by making impossible states impossible.
  • Eliminates sprawling if/else or switch blocks for state-dependent logic.

What problems does this solve?

  • The State pattern and state machines are increasingly used in complex UI — XState is a popular production tool worth mentioning.
Senior
30

What is the Template Method pattern?

  • Template Method defines the skeleton of an algorithm in a base class, deferring some steps to subclasses. Subclasses override specific steps without changing the overall structure.
  • JS functional equivalent: A higher-order function that calls customisable callback hooks at defined points.
  • Examples: Lifecycle hooks in frameworks (React's render cycle, Vue's lifecycle), Express middleware, test suite setup/teardown hooks (beforeEach, afterEach).

What problems does this solve?

  • Template Method is the pattern behind all lifecycle hooks — understanding it explains how React and Vue's lifecycle systems work.