solid
Apply SOLID principles to write flexible, maintainable, and testable code. Use when designing classes, interfaces, and module boundaries. Covers Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion with practical TypeScript examples and detection heuristics.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/solid/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How solid Compares
| Feature / Agent | solid | Standard Approach |
|---|---|---|
| Platform Support | multi | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Apply SOLID principles to write flexible, maintainable, and testable code. Use when designing classes, interfaces, and module boundaries. Covers Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion with practical TypeScript examples and detection heuristics.
Which AI agents support this skill?
This skill is compatible with multi.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# SOLID Principles
Five principles for building software that is easy to understand, extend, and
maintain. They reduce coupling, increase cohesion, and make code testable.
## When to Apply
Reference these principles when:
- Designing new classes, modules, or interfaces
- Refactoring code with too many responsibilities
- Reviewing PRs for architectural concerns
- Breaking apart god objects or fat interfaces
- Deciding where to draw module boundaries
- Making code more testable
## Quick Reference
| Principle | One-Liner | Red Flag |
| --------- | --------- | -------- |
| **S**RP | One reason to change | "This class handles X *and* Y *and* Z" |
| **O**CP | Add, don't modify | Growing `if/else` or `switch` chains for types |
| **L**SP | Subtypes are substitutable | Type-checking or special-casing in calling code |
| **I**SP | Small, focused interfaces | Empty method implementations or `throw new Error("Not implemented")` |
| **D**IP | Depend on abstractions | `new ConcreteClass()` inside business logic |
See `references/PRINCIPLES.md` for detailed explanations and TypeScript examples.
## Detection Checklist
Ask these questions for every class and module:
| Question | Violated Principle |
| -------- | ------------------ |
| Does this class have multiple reasons to change? | SRP |
| Do I need to modify existing code to add a new variant? | OCP |
| Does calling code need type-checks or special cases for subtypes? | LSP |
| Are implementors forced to stub out unused methods? | ISP |
| Does high-level logic directly instantiate infrastructure? | DIP |
## Applying SOLID at Different Scales
| Scale | SRP | OCP | LSP | ISP | DIP |
| ----- | --- | --- | --- | --- | --- |
| **Function** | Does one thing | — | — | — | Takes abstractions as params |
| **Class** | One reason to change | Extend via composition | Subtypes honor contracts | Implements only what it uses | Constructor injection |
| **Module** | One bounded context | Plugin architecture | Interchangeable implementations | Thin public API | Depends inward |
| **Service** | Single domain | New features = new services | API contract stability | Minimal API surface | Abstractions at boundaries |
## Relationships Between Principles
- **SRP + ISP**: Splitting responsibilities often means splitting interfaces too
- **OCP + DIP**: Depending on abstractions is what makes extension without modification possible
- **LSP + OCP**: If subtypes are substitutable, you can extend behavior by adding new subtypes
- **DIP + ISP**: Small focused interfaces make dependency inversion practical
## Common Anti-Patterns
| Anti-Pattern | Violated Principles | Fix |
| ------------ | ------------------- | --- |
| God class doing everything | SRP | Extract focused classes |
| `switch` on type across codebase | OCP, LSP | Replace with polymorphism |
| Subclass that throws "not supported" | LSP, ISP | Redesign hierarchy, split interface |
| Fat interface with 20 methods | ISP | Split into role-based interfaces |
| Business logic importing DB driver | DIP | Inject repository interface |
| Service creating its own dependencies | DIP | Constructor injection |
## Best Practices
### DO
- Start with SRP — it's the foundation for all others
- Use interfaces to define boundaries between components
- Let violations emerge from real problems, then fix them
- Prefer composition over inheritance for extending behavior
- Keep interfaces small and role-specific
- Inject dependencies through constructors
### DON'T
- Apply SOLID dogmatically to trivial code (a 5-line utility doesn't need an interface)
- Create abstractions before you have at least two implementations
- Confuse SRP with "single method" — it's about reasons to change, not size
- Force Liskov compliance on classes that shouldn't be in the same hierarchy
- Over-segregate interfaces into single-method fragments when a cohesive group makes sense