Loading...
Loading...
SOLID principles for object-oriented design — Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. Covers motivation, violations, fixes, and multi-language examples (PHP, Java, Python, TypeScript, C++) for building maintainable, extensible software.
npx skill4agent add krzysztofsurdy/code-virtuoso solid| Principle | Summary | Reference |
|---|---|---|
| S — Single Responsibility | A class should have only one reason to change | reference |
| O — Open/Closed | Open for extension, closed for modification | reference |
| L — Liskov Substitution | Subtypes must be substitutable for their base types | reference |
| I — Interface Segregation | Prefer many specific interfaces over one general-purpose interface | reference |
| D — Dependency Inversion | Depend on abstractions, not concretions | reference |
| Symptom | Likely Violated Principle | Fix |
|---|---|---|
| Class does too many things | SRP | Split into focused classes |
| Adding a feature requires editing existing classes | OCP | Introduce polymorphism or strategy |
| Subclass breaks when used in place of parent | LSP | Fix inheritance hierarchy or use composition |
| Classes forced to implement unused methods | ISP | Break interface into smaller ones |
| High-level module imports low-level details | DIP | Introduce an abstraction layer |
// BEFORE: Class handles both user data AND email sending
class UserService {
public function createUser(string $name, string $email): void { /* ... */ }
public function sendWelcomeEmail(string $email): void { /* ... */ }
}
// AFTER: Each class has one responsibility
class UserService {
public function __construct(private UserNotifier $notifier) {}
public function createUser(string $name, string $email): void {
// persist user...
$this->notifier->welcomeNewUser($email);
}
}
class UserNotifier {
public function welcomeNewUser(string $email): void { /* ... */ }
}interface DiscountPolicy {
public function calculate(float $total): float;
}
class PercentageDiscount implements DiscountPolicy {
public function __construct(private float $rate) {}
public function calculate(float $total): float {
return $total * $this->rate;
}
}
// Adding a new discount type requires NO changes to existing code
class FlatDiscount implements DiscountPolicy {
public function __construct(private float $amount) {}
public function calculate(float $total): float {
return min($this->amount, $total);
}
}// High-level policy depends on abstraction, not on database details
interface OrderRepository {
public function save(Order $order): void;
}
class PlaceOrderHandler {
public function __construct(private OrderRepository $repository) {}
public function handle(PlaceOrderCommand $cmd): void {
$order = Order::create($cmd->items);
$this->repository->save($order);
}
}