FlashcardsRecall, then flip

Print · SOLID

Back to study

16 cards · 2 sheets · 4 pages.

Print double-sided, flipping on the long edge, at 100% scale with no margins added by the browser. Answer columns are already mirrored, so each answer lands on the back of its own question. Cut along the dashed lines.

Preview

SOLID flashcards — questions (cards 1-8)Print double-sided, flip on long edge, cut along dashed lines
CARD 1 · QUESTION

What does SOLID stand for, and where does it come from?

CARD 2 · QUESTION

State the Single Responsibility Principle. What counts as a 'reason to change'?

CARD 3 · QUESTION

What does an SRP violation look like in a React codebase?

CARD 4 · QUESTION

State the Open-Closed Principle.

CARD 5 · QUESTION

How would you apply OCP to a switch statement over payment providers that grows every quarter?

CARD 6 · QUESTION

State the Liskov Substitution Principle.

CARD 7 · QUESTION

Give a classic LSP violation and explain what breaks.

CARD 8 · QUESTION

How does TypeScript's type system relate to LSP?

SOLID flashcards — answers (cards 1-8)Columns mirrored so answers align with question backs
CARD 2 · ANSWER

A module should have one, and only one, reason to change. Martin later sharpened 'reason' to mean actor - each module should answer to a single stakeholder or business function, not to a single verb.

CARD 1 · ANSWER

Single responsibility, Open-closed, Liskov substitution, Interface segregation, Dependency inversion. Robert C. Martin gathered the five principles around 2000; Michael Feathers rearranged them into the acronym.

CARD 4 · ANSWER

Entities should be open for extension but closed for modification: you add behaviour by adding code, not by editing code that already works and is already tested. Polymorphism and composition are the usual mechanisms.

CARD 3 · ANSWER

One component that fetches, transforms, formats and renders, so both an API change and a design change land in the same file. Pull data access into a hook and formatting into pure functions, leaving the component to render.

CARD 6 · ANSWER

A subtype must be usable anywhere its supertype is expected without breaking the program's correctness. Subtypes may weaken preconditions and strengthen postconditions, never the other way round.

CARD 5 · ANSWER

Replace the switch with a registry - Record<Provider, Handler> or a strategy interface - so a new provider is a new entry rather than an edit to the dispatcher. The trade-off: you lose the exhaustive never check that forces you to handle each new case.

CARD 8 · ANSWER

TypeScript is structurally typed, so substitutability is judged on shape rather than declared inheritance. Method-shorthand parameters stay bivariant even under strictFunctionTypes - declare them as function properties to get sound, contravariant checks.

CARD 7 · ANSWER

Square extending Rectangle: setting width silently mutates height, so any caller written against Rectangle's contract is wrong. The same smell is a subclass that throws NotSupported on an inherited method.

SOLID flashcards — questions (cards 9-16)Print double-sided, flip on long edge, cut along dashed lines
CARD 9 · QUESTION

State the Interface Segregation Principle.

CARD 10 · QUESTION

What does ISP look like in a TypeScript React app?

CARD 11 · QUESTION

State the Dependency Inversion Principle.

CARD 12 · QUESTION

Distinguish DIP, dependency injection, and an IoC container.

CARD 13 · QUESTION

How do you apply DIP in React or Next.js without a DI container?

CARD 14 · QUESTION

What are the main criticisms of SOLID?

CARD 15 · QUESTION

How do SOLID, cohesion and coupling relate?

CARD 16 · QUESTION

How should a senior engineer talk about SOLID in an interview?

SOLID flashcards — answers (cards 9-16)Columns mirrored so answers align with question backs
CARD 10 · ANSWER

Props typed to exactly what the component reads - Pick<User, 'id' | 'avatarUrl'> rather than the whole User - and one narrow service interface per consumer. Components then compose with partial data and are trivial to test.

CARD 9 · ANSWER

No client should be forced to depend on methods it does not use. Prefer several small, role-specific interfaces to one fat one, so a change made for one consumer cannot break or rebuild the others.

CARD 12 · ANSWER

DIP is the design principle (depend on abstractions); DI is the technique of passing dependencies in rather than constructing them; an IoC container is tooling that wires DI for you. You can have DI without DIP, and DIP without a container.

CARD 11 · ANSWER

High-level policy should not depend on low-level detail; both depend on abstractions, and abstractions do not depend on details. In practice the consumer owns the interface, not the implementation.

CARD 14 · ANSWER

The wording is vague, the principles assume 1990s class-based OO, and they are easy to over-apply into indirection nobody asked for. Dan North's CUPID is one alternative, arguing for properties like composable and predictable over rules.

CARD 13 · ANSWER

Pass collaborators in as props, context or arguments - a component takes getUser(): Promise<User> instead of importing fetch or the SDK directly. Tests then hand it a fake, with no module mocking or network interception.

CARD 16 · ANSWER

Name the axis of change you are protecting and the price you are paying, because abstraction is not free and premature indirection is its own defect. Apply DIP at a volatile boundary such as a telecom or payments provider, and skip it for a stable one.

CARD 15 · ANSWER

SRP and ISP push toward high cohesion; OCP, LSP and DIP push toward loose coupling. Cohesion and coupling are the underlying qualities - SOLID is a set of heuristics for moving them in the right direction.