Skip to content
Skills Library
Programming · Review & audit

solid-principles

/solid-principles

Use when designing or refactoring classes, modules, or interfaces in any OO language — and whenever the user mentions SOLID, single responsibility / SRP, open/closed / OCP, Liskov substitution / LSP, interface segregation / ISP, dependency inversion or dependency injection / DIP/DI. Triggers explicitly on those names, AND implicitly whenever code shows the smells they target: a god class doing three jobs, a `switch`/`if-isinstance` on a type tag that grows with every feature, a subclass that throws "not supported", a fat interface whose callers use 2 of 11 methods, or a high-level class that `

Licence
MIT
Last repository change
26.10.2026

Assessment and security

87/ 100Class: good
Format20 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability17 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
9
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 26.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Use when designing or refactoring classes, modules, or interfaces in any OO language — and whenever the user mentions SOLID, single responsibility / SRP, open/closed / OCP, Liskov substitution / LSP, interface segregation / ISP, dependency inversion or dependency injection / DIP/DI. Triggers explicitly on those names, AND implicitly whenever code shows the smells they target: a god class doing three jobs, a `switch`/`if-isinstance` on a type tag that grows with every feature, a subclass that throws "not supported", a fat interface whose callers use 2 of 11 methods, or a high-level class that `

Triggers from the description

not supported
Original author description

Use when designing or refactoring classes, modules, or interfaces in any OO language — and whenever the user mentions SOLID, single responsibility / SRP, open/closed / OCP, Liskov substitution / LSP, interface segregation / ISP, dependency inversion or dependency injection / DIP/DI. Triggers explicitly on those names, AND implicitly whenever code shows the smells they target: a god class doing three jobs, a `switch`/`if-isinstance` on a type tag that grows with every feature, a subclass that throws "not supported", a fat interface whose callers use 2 of 11 methods, or a high-level class that `

How it works

  1. Before you reach for this: do you even need it?
  2. Route First
  3. The five, in one breath
  4. How the five reinforce each other
  5. Red flags — stop and reconsider
  6. Completion criteria
Original SKILL.md headings · 122 lines, 1,126 words
SKILL.md preview
---
name: solid-principles
description: >
  Use when designing or refactoring classes, modules, or interfaces in any OO language —
  and whenever the user mentions SOLID, single responsibility / SRP, open/closed / OCP,
  Liskov substitution / LSP, interface segregation / ISP, dependency inversion or dependency
  injection / DIP/DI. Triggers explicitly on those names, AND implicitly whenever code shows
  the smells they target: a god class doing three jobs, a `switch`/`if-isinstance` on a type
  tag that grows with every feature, a subclass that throws "not supported", a fat interface
  whose callers use 2 of 11 methods, or a high-level class that `new`s a concrete database /
  mailer / HTTP client inside itself. Teaches all five principles with bad→good examples in
  both TypeScript and Python, a cross-cutting anti-pattern catalog (including over-applying
  SOLID), and one notification-dispatcher system refactored to honor all five together.
  Skip for throwaway scripts and genuinely simple CRUD/glue where an interface per dependency
  is pure ceremony — misapplied SOLID is needless indirection.
metadata:
  last_updated: "2026-06-25"
---

# SOLID Principles

Use this skill to make object-oriented code that **absorbs change** instead of resisting it:
classes with one job, new behavior added without editing what already works, parts that
substitute cleanly, narrow seams between collaborators, and dependencies that point at
abstractions rather than concrete details.

**Core principle:** SOLID is five facets of *one* goal — high cohesion and low coupling. The
acronym is a memory aid, not five unrelated rules. SRP gives you small, focused units; ISP
keeps the seams between them narrow; DIP points those seams at abstractions; OCP and LSP let
you add and swap implementations behind them without editing or breaking callers. Applied
together they make change *local* — the whole point.

One worked domain — a **notification dispatcher** (format → send → record, across email / SMS
/ push channels) — runs through the two integrated example files so the five principles
visibly compose instead of floating as disconnected snippets.

## Before you reach for this: do you even need it?

SOLID buys flexibility by adding abstraction, and abstraction has a cost (indirection,
more files, more to hold in your head). It pays off in code that **changes and grows**. It is
overkill for code that won't.

| Signal | Lean toward |
| --- | --- |
| A class/module that keeps growing, gets edited for unrelated reasons, or is hard to test in isolation | Apply SOLID — start with SRP |
| New variants keep arriving (payment types, report formats, channels) and each one edits the same `switch` | OCP + a polymorphic seam |
| You swap implementations in tests, or want to (real DB vs. fake, SMTP vs. capture) | DIP — inject an abstraction |
| A throwaway script, a spike, a one-off migration | Write it plain; don't abstract |
| Genuinely simple CRUD — store it, show it, edit it, no real rules | Plain handlers; an interface per dependency is ceremony |
| You're adding an interface that will have exactly one implementation forever | Stop — that's `anti-patterns.md`'s over-engineering trap |

If the answer is "this won't change," say so and keep it simple. **Misapplied SOLID is worse
than none** — see the over-applying section of `references/anti-patterns.md`.

## Route First

Pick the principle (or file) that matches the task. Read the most specific one first.

| Task | Read |
| --- | --- |
| A class doing too much / many reasons to change / god class — split by responsibility | `references/single-responsibility.md` |
| A growing `switch`/`if-isinstance` per feature — extend without editing existing code | `references/open-closed.md` |
| A subclass that breaks its base's contract, throws "not supported", or surprises callers | `references/liskov-substitution.md` |
| A fat interface forcing callers/implementers to depend on methods they don't use | `references/interface-segregation.md` |
| High-level policy welded to a concrete DB / mailer / client — invert and inject the dependency | `references/dependency-inversion.md` |
| Recognizing and fixing SOLID gone wrong — both violations AND over-engineering | `references/anti-patterns.md` |
| A complete, copy-paste-ready system honoring all five, in TypeScript | `references/typescript-examples.md` |
| A complete, copy-paste-ready system honoring all five, in Python | `references/python-examples.md` |

## The five, in one breath

1. **Single Responsibility (SRP)** — a class should have one reason to change: one actor, one
   axis of change. *Kills:* the god class that computes, formats, persists, and emails.
   *Gives you:* small units you can test, name, and change in isolation.

2. **Open/Closed (OCP)** — open for extension, closed for modification: add new behavior by
   adding code, not editing working code. *Kills:* the `switch (type)` you reopen for every
   new variant. *Gives you:* new variants behind a stable seam, existing code untouched.

3. **Liskov Substitution (LSP)** — a subtype must be usable anywhere its base is, honoring the
   base's *behavioral* contract (preconditions, postconditions, invariants, exceptions) — not
   just its signatures. *Kills:* `Square extends Rectangle`, `Penguin.fly()` throwing.
   *Gives you:* polymorphism you can trust; OCP that actually holds.

4. **Interface Segregation (ISP)** — clients shouldn't depend on methods they don't use; many
   small role interfaces beat one fat one. *Kills:* the `Worker`/`Machine` interface forcing
   `eat()`/`scan()` no-ops. *Gives you:* narrow seams that don't drag unrelated changes along.

5. **Dependency Inversion (DIP)** — high-level policy and low-level details should both depend
   on abstractions; details depend on the abstraction, not the reverse. *Kills:*
   `new SmtpMailer()` inside your service. *Gives you:* swappable implementations, testable
   policy, dependencies pointing inward (the same rule `domain-driven-design` enforces).

## How the five reinforce each other

They are one system, not a checklist:

```
SRP   → small, single-purpose classes ............ the units worth wiring together
ISP   → narrow role interfaces between them ....... the shape of each seam
DIP   → those interfaces are the dependencies ..... arrows point at abstractions, inward
OCP   → add a new implementation behind the seam .. without editing existing callers
LSP   → the new implementation is substitutable ... so OCP's promise actually holds
```

Skip SRP and your interfaces (ISP) describe blobs. Skip DIP and OCP has nowhere to plug new
variants in. Violate LSP and OCP's "just add a subclass" silently breaks callers. You rarely
apply one in isolation — a good refactor moves several at once, as the example files show.

## Red flags — stop and reconsider

- "I'll add the new case to the `switch`/`if-isinstance` again." → OCP/SRP; the type tag wants
  to be a polymorphic seam. See `references/open-closed.md`.
- "This class is named `*Manager`/`*Util`/`*Helper` and does five things." → god class; split
  by responsibility. See `references/single-responsibility.md`.
- "The subclass overrides this to throw `NotSupportedError`." → LSP violation (refused
  bequest); the hierarchy is wrong. See `references/liskov-substitution.md`.
- "Implementing this interface means stubbing six methods I don't need." → fat interface;
  segregate into roles. See `references/interface-segregation.md`.
- "My service does `new PostgresRepo()` / `new HttpClient()` in its constructor." → concrete
  dependency; invert and inject. See `references/dependency-inversion.md`.
- "I added an interface, a factory, and a DI binding for something with one implementation
  that never changes." → over-engineering; do the simple thing. See `references/anti-patterns.md`.

## Completion criteria

Before considering a class/module design done:

- Each class has **one reason to change** — you can name its single responsibility in a phrase.
- New variants can be added by **adding** a class/implementation, not editing a growing
  conditional in existing code.
- Every subtype is **substitutable** for its base: it strengthens no preconditions, weakens no
  postconditions, throws no surprises, breaks no invariants.
- Clients depend only on the **methods they use**; no implementer stubs out methods it doesn't
  need.
- High-level policy depends on **abstractions**, with concrete details injected — not
  `new`-ed inside.
- Every abstraction you introduced is **justified by real, expected change** — not a
  speculative interface around a thing with one forever-implementation.
Files in this package (9)
  • SKILL.md 9 KB
  • references/anti-patterns.md 9 KB
  • references/dependency-inversion.md 7 KB
  • references/interface-segregation.md 5 KB
  • references/liskov-substitution.md 6 KB
  • references/open-closed.md 5 KB
  • references/python-examples.md 9 KB
  • references/single-responsibility.md 6 KB
  • references/typescript-examples.md 9 KB

Versions

RepositoryScoreLicence
This page · joeblackwaslike/agent-skills87MIT
pantheon-org/tekhne100MIT
claude-dev-suite/claude-dev-suite100MIT
florianbuetow/claude-code100MIT
jeremymorgan/code-review-skills100CC0-1.0
decebals/claude-code-java95MIT
khaledsaeed18/dotclaude90MIT

Database snapshot: 13.11.2026 · package version 111861f65835 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 90SOLID Principles Code Review
    Review Python code for adherence to SOLID principles (SRP, OCP, LSP, ISP, DIP). Use when reviewing Python code for maintainability, testability, and design quality.
  • 100solid-review
    SOLID design-principles review (SRP / OCP / LSP / ISP / DIP) on a file/directory/glob. Review-only. Triggers on `/solid-review`, \"SOLID review\", \"design review\", \"design principles\", \"SOLID 검증\", \"디자인 리뷰\", \"원칙 검증\", or `/deep-test` running it as the Advisory Gate.
  • 100solid
    Use when applying or evaluating SOLID object-oriented design principles — Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. USE FOR: class design, interface design, dependency management, evaluating OO design quality,…
  • 90solid
    SOLID design review rules (SRP, OCP, LSP, ISP, DIP) for code reviews: what counts as a real design finding, what is only taste, how to cite it and how severe it is. Use when reviewing a diff, a pull request or recent changes for design problems, when asked for a "SOLID review",…
  • 100solid-principles-code-review-compliance
    Use this skill when review object-oriented architectures for compliance with SOLID software design principles.
  • 100apply-solid
    Use when a class or module violates SOLID — an edit forces unrelated edits, a dependency needs a mock everywhere, an abstraction leaks — and you must apply the five principles at the class level.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.