solid

SKILL.md

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
SRP One reason to change "This class handles X and Y and Z"
OCP Add, don't modify Growing if/else or switch chains for types
LSP Subtypes are substitutable Type-checking or special-casing in calling code
ISP Small, focused interfaces Empty method implementations or throw new Error("Not implemented")
DIP 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
Weekly Installs
21
GitHub Stars
3
First Seen
Feb 17, 2026
Installed on
opencode21
github-copilot21
codex21
gemini-cli20
amp20
kimi-cli20