Back to System Design
System Design
easy
mid

What are the SOLID principles and how do they apply to frontend code?

Five OOP design principles: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. They aim for maintainable, decoupled code. In frontend they map to: focused components/hooks, extension via props/composition, consistent contracts, minimal prop interfaces, and depending on abstractions.

5 min read·~6 min to think through

SOLID is five object-oriented design principles for maintainable, loosely-coupled code. Know each — and be ready to map them to frontend/React, since that's the real test.

The five

S — Single Responsibility Principle. A class/module/component should have one reason to change — one job. Frontend: a component that fetches data, manages form state, and renders a chart is doing three jobs — split it; extract logic into custom hooks.

O — Open/Closed Principle. Software should be open for extension, closed for modification — add behavior without editing existing code. Frontend: a Button you extend via props and composition (variant, children, render props) instead of editing its internals for every new case.

L — Liskov Substitution Principle. Subtypes must be substitutable for their base type without breaking expectations. Frontend: a custom <Input> wrapper should honor the standard input contract (accept value/onChange, forward refs) — a consumer swapping it in shouldn't get surprised. Component variants should keep a consistent contract.

I — Interface Segregation Principle. Don't force clients to depend on interfaces they don't use — prefer small, focused interfaces. Frontend: don't give a component a giant 20-prop interface; keep prop APIs minimal and focused, split big components.

D — Dependency Inversion Principle. Depend on abstractions, not concretions; high-level modules shouldn't depend on low-level details. Frontend: a component depends on a data-fetching abstraction (a hook, an injected service, Context) — not directly on axios or a specific endpoint — so it's testable and swappable.

The point of them

They all push toward the same goals: low coupling, high cohesion, easy to change, easy to test. They're guidelines, not laws — applying them dogmatically leads to over-abstraction. Use judgment.

The honest caveat

SOLID is OOP-rooted; frontend is increasingly functional/component-based. The spirit — focused units, extension over modification, depend on abstractions — translates well; the literal OOP framing less so. A senior says this rather than reciting class-based examples.

The framing

"Single Responsibility — one reason to change; in React, focused components and extracting logic into hooks. Open/Closed — extend via props and composition, don't modify internals. Liskov — variants and wrappers honor a consistent, substitutable contract. Interface Segregation — small, focused prop APIs, not 20-prop monoliths. Dependency Inversion — depend on a data abstraction like a hook or Context, not directly on axios. They all serve low coupling and testability — but they're guidelines, and since they're OOP-rooted, I apply the spirit to component-based frontend rather than the literal class framing."

Follow-up questions

  • Give a React example of the Single Responsibility Principle.
  • How does the Open/Closed Principle apply to a component library?
  • What does Dependency Inversion look like in a React app?
  • When can applying SOLID too strictly hurt?

Common mistakes

  • Reciting the acronym with only abstract OOP definitions, no frontend mapping.
  • Applying them dogmatically into over-abstraction.
  • Confusing Single Responsibility with 'one function per file'.
  • Not acknowledging SOLID's OOP origins vs functional frontend.

Performance considerations

  • Not a performance topic — but SRP-driven component splitting can help re-render scoping, and dependency inversion makes performance-sensitive parts swappable/mockable.

Edge cases

  • A component that legitimately has a couple of related responsibilities.
  • Over-abstracting a small app 'to be SOLID'.
  • Premature interface segregation creating prop-drilling.

Real-world examples

  • Extracting data-fetching logic into a custom hook (SRP).
  • A design-system Button extended purely through props/variants (OCP).

Senior engineer discussion

Seniors define each principle crisply, map every one to a concrete React pattern, frame them as coupling/cohesion/testability guidelines rather than laws, and honestly note the OOP-to-functional-frontend translation gap.

Related questions