33. SOLID and object-oriented design patterns
Answer as submitted
“Yes — SOLID and classic design patterns are the foundation of my code and architectural decisions.”
Expanded answer
Yes, and I treat SOLID as a set of forces rather than a checklist. Single Responsibility: one reason to change per class — a service that prices, computes tax, persists, notifies and logs is five reasons to change and five reviewers for one file. Open/Closed: new behaviour arrives as a new implementation registered in the container, not as another else if in an existing method, so the class that passed review last month is not re-reviewed for a segment it never heard of. Liskov Substitution: an implementation that throws NotSupportedException from an inherited member has not satisfied the contract, and the fix is a narrower interface, not a better message — which is why the contract is stated as a test every implementation runs. Interface Segregation: a read port and a write port instead of a fourteen-member IRepository<T>, so a read-only screen depends on four members and every test double stops implementing methods it will never call. Dependency Inversion: high-level policy depends on abstractions it declares, and the composition root is the only file in the solution that names a concrete type. All five are what make the pattern catalogue usable rather than decorative: strategy, specification, decorator, adapter, factory, builder, facade, mediator, observer, template method, singleton through the container, CQRS and saga each resolve a specific force, and the same vocabulary transfers directly between .NET, Java/Spring and Python.
| Principle | The violation | The refactor |
|---|---|---|
| S — Single Responsibility | one service pricing, taxing, persisting, notifying and logging | one class per rule, one reason to change each |
| O — Open/Closed | a new else if per customer segment in a reviewed method | a strategy implementation registered in the container |
| L — Liskov Substitution | a subtype that throws from a member it inherited | narrower contracts, enforced by a shared contract test suite |
| I — Interface Segregation | a fourteen-member repository interface every client depends on | a read port and a write port, plus a query port per screen |
| D — Dependency Inversion | new SqlConnection(...) inside the business class | constructor injection of ports, resolved at the composition root |
| Patterns | patterns named in a document and applied nowhere | each entry in the catalogue names its application and the force it resolves |
Live SOLID refactor workflow proof
The running component below changes its principle/result view through real event binding. Select a principle to see the before/after contrast, the reasoning behind the refactor, and the number that changed.
Choose a principle
Select a principle to inspect the violation, the refactor and the evidence.
$ before: OrderService (pricing + tax + persistence + email + logging) → after: OrderPricing, TaxPolicy, IOrderRepository, INotifier
One reason to change per class. A service that prices an order, computes tax, writes to the database, sends the confirmation and logs is five reasons to change and five people touching one file. Splitting it gives the pricing rule one home and the persistence concern another, which is what makes either of them reviewable.
reasons to change in the pricing class: 1 (from 5) unit tests that need no database or mail server: 34 classes named Manager, Helper or Util: 0
What applying SOLID buys
Source files
Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the next two are the same class before and after the refactor, with each violation marked; the last is the pattern catalogue as data.
Acceptance criteria
- Shows each principle as a violation and its refactor, not as a definition.
- Quantifies the change, so the refactor is evidence rather than opinion.
- Shows an interactive proof of choosing a principle and reading the result.
- Names where each pattern is applied and which principle it serves.
- Verifies substitutability with contract tests rather than assuming it.