SOLID Principles
Apply SOLID design principles for maintainable, flexible code architecture.
The Five Principles
1. Single Responsibility Principle (SRP)
A module should have one, and only one, reason to change
Elixir Pattern
TypeScript Pattern
Ask yourself: "What is the ONE thing this module does?"
2. Open/Closed Principle (OCP)
Software entities should be open for extension, closed for modification.
Elixir Pattern (Behaviours)
TypeScript Pattern (Composition)
Ask yourself: "Can I add new functionality without changing existing code?"
3. Liskov Substitution Principle (LSP)
Subtypes must be substitutable for their base types
Elixir Pattern (LSP)
TypeScript Pattern (LSP)
Ask yourself: "Can I replace this with its parent/interface without breaking behavior?"
4. Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they don't use.
Elixir Pattern (ISP)
TypeScript Pattern (ISP)
Ask yourself: "Does this interface force implementations to define unused methods?"
5. Dependency Inversion Principle (DIP)
Depend on abstractions, not concretions
Elixir Pattern (DIP)
TypeScript Pattern (DIP)
Ask yourself: "Can I swap implementations without changing dependent code?"
Application Checklist
Before writing new code
- Identify the single responsibility
- Design for extension points (behaviours, interfaces)
- Define abstractions before implementations
- Keep interfaces minimal and focused
During implementation
- Each module has ONE reason to change (SRP)
- New features extend, don't modify (OCP)
- Implementations honor contracts (LSP)
- Interfaces are minimal (ISP)
- Dependencies are injected/configurable (DIP)
During code review
- Are responsibilities clearly separated?
- Can we add features without modifying existing code?
- Do all implementations fulfill their contracts?
- Are interfaces focused and minimal?
- Are dependencies abstracted?
Common Violations in Codebase
SRP Violation
- GraphQL resolvers that also contain business logic (use command handlers)
- Components that fetch data AND render (use hooks + presentation components)
OCP Violation
- Long if/else or case statements for types (use behaviours/polymorphism)
- Hardcoded provider logic (use dependency injection)
LSP Violation
- Raising exceptions in implementations when base would return nil/error tuple
- Changing return types between implementations
ISP Violation
- Fat GraphQL types requiring all fields (use fragments)
- Monolithic component props (split into focused interfaces)
DIP Violation
- Direct calls to external services (wrap in behaviours)
- Hardcoded Repo calls (inject repository)
Integration with Existing Skills
Works with
boy-scout-rule: Apply SOLID when improving codetest-driven-development: Write tests for each responsibilityelixir-code-quality-enforcer: Credo enforces some SOLID principlestypescript-code-quality-enforcer: TypeScript interfaces support ISP/DIP
Remember
SOLID is about managing dependencies and responsibilities, not about creating more code.
Good design emerges from applying these principles pragmatically, not dogmatically.


