SOLID is a default, not a religion.
Most articles teach the five principles with toy examples — a Square that violates LSP, a Logger that violates SRP. You finish having memorised five acronyms with no idea what to do on Monday morning when your real order service has 11 reasons to change and a switch statement on payment type.
So I took a real, ugly 60-line order-processing service that breaks every SOLID rule, and refactored it one principle at a time.
The starting point
public class OrderService
{
public void PlaceOrder(Order order)
{
// validate, apply discount, charge Stripe,
// open SqlConnection, send SMTP email,
// append to a log file
// 60 lines. 6 jobs. 3 hard-coded providers.
}
}
Untestable without a real Stripe key, a real database, and an SMTP server. Every change touches the same file.
One principle at a time
- S — Single Responsibility: 6 jobs in one method → 6 collaborators, each with one stakeholder (finance owns payments, marketing owns email, DBA owns schema).
- O — Open / Closed: a switch statement on payment type → strategy interface. Adding Apple Pay is one new class, zero edits to existing code.
-
L — Liskov Substitution: cash-on-delivery silently returning success from
ChargeAsync→ honestPaymentResultwith aDeferredToDeliverystatus. The type system tells the truth. -
I — Interface Segregation: a god
IPaymentMethodinterface forcing COD to throwNotSupportedExceptionfrom three methods → split into capabilities (IRefundable,IRecurringCapable,IDisputable). - D — Dependency Inversion: hard-coded Stripe + SQL + SMTP inside the service → injected abstractions. Now I can write a unit test that runs in 5 ms with zero infrastructure.
The honest disadvantages
SOLID has real costs:
- More files (6 classes instead of 1)
- More constructor parameters
- Harder for new devs to follow the flow (interface → implementation jumping)
- Premature abstraction is worse than no abstraction
Apply by default, break with a reason. Document the reason. That's the whole game.
Watch the 2-min walkthrough
Go deeper
The full guide has the complete side-by-side refactor, a 5-question pull-request checklist you can paste into your PR template, and the 6 honest disadvantages each principle costs you:
https://prepstack.co.in/blog/solid-principles-csharp-real-project-deep-dive
Which principle do you find yourself bending most often in real code? Drop your honest answer in the comments.
Top comments (0)