SOLID and DRY Required
Give each module one reason to change
Each class, module or function serves one actor and has one reason to change.
How to do it
Name the person or team who would ask for a change. If a class answers to two, such as finance and the design team, split it. Keep calculation, storage and presentation apart.
Example
// Bad: pricing, storage and email in one class
class OrderService {
public function place(Order $order): void { /* price, save, send email */ }
}
// Good: one reason to change each
final class OrderPricer { public function total(Order $order): Money { /* ... */ } }
final class OrderRepository { public function save(Order $order): void { /* ... */ } }
final class OrderMailer { public function sendConfirmation(Order $order): void { /* ... */ } }
How to check
In review, describe the module in one sentence without "and". A linter limit on class size, such as PHPMD ExcessiveClassLength, flags likely offenders.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/solid-and-dry/single-responsibility.