SOLID principles

Code is not hard to write. It is hard to change. The first version of any class is fine. The trouble starts at the ninth feature request, when a small change to tax rounding breaks PDF export and nobody can explain why those two things were connected.

SOLID is five rules of thumb about that. Robert C. Martin collected them around 2000, and Michael Feathers noticed a few years later that the first letters spell a word. Each rule makes one kind of change cheap.

Your answer

Think of a file in a codebase you have worked on that everyone was afraid to touch. What made it scary? Write two specific things.

The five, on one screen

PrincipleIn one lineThe smell that tells you it is broken
SSingle responsibilityOne class, one team with a reason to change it.A file that shows up in every pull request.
OOpen closedAdd behaviour by adding code, not by editing code that works.An if ladder that grows by one rung per feature.
LLiskov substitutionA subclass works anywhere its parent works.A method that throws “not supported”.
IInterface segregationNobody depends on methods they do not use.Empty methods written to satisfy an interface.
DDependency inversionBusiness logic depends on interfaces, not on the database.new on a database or an API client inside business logic.
The picture to keep
A restaurant that survives a busy Sunday

The chef only cooks (S). A new dish goes on the menu without rebuilding the kitchen (O). A substitute cook can cover any shift (L). The waiter gets the menu, not the supplier invoices (I). And the kitchen is built around the gas connection, not around one brand of stove (D). Every page in this section goes back to one of those five sentences.

In one line: Each principle makes one kind of change cheap: who asks for it, how it is added, what can be swapped, what you must know, and what you depend on.

How they fit together

They are not five independent rules. Open closed is the goal: new behaviour should arrive as new code. Dependency inversion and Liskov substitution are how you get there, because you can only plug in a new class if callers depend on an interface, and only if every class behind that interface really honours it. Single responsibility and interface segregation keep the pieces small enough for that to work, one for classes and one for interfaces.

If you have read the OOP pages, you have already used most of this. Polymorphism is the mechanism. SOLID tells you where to put it.

These are not laws

Apply all five to a 40 line script and you get nine files, four interfaces, and a reader who cannot find where anything happens. The principles fix pain that comes from change. Where nothing is changing, there is no pain to fix. My rule: write the plain version first, and reach for a principle the second time a change hurts in the same place.

Name the principle

Read the symptom, say the letter, then reveal
OrderService creates its own MySQL connection, so its tests need a real database.
Adding a festival surcharge means editing a 190 line fee function that already has nine rules.
Invoice.ts is edited by the finance team, the design team and the platform team.
CashOnDelivery extends PaymentMethod and its refund() throws an error.
A Rider class has cook() and serve() methods that exist only because the Staff interface demanded them.
A square that extends rectangle changes its height when you set its width.

The five pages

Checkpoint

Checkpoint

1. Which principle is most directly about being able to add a feature without editing existing, working code?

2. A subclass overrides a method to throw "not supported". Which principle does that break, and why does it matter?

3. You are writing a 60 line script that will run once to migrate data. How much SOLID does it need?

Say this in 60 seconds

SOLID is five principles for keeping code cheap to change. Single responsibility: a class should have one reason to change, meaning one team that asks for changes to it. Open closed: new behaviour should come as new code, not as edits to code that works. Liskov substitution: a subclass has to work anywhere its parent does, with no surprises. Interface segregation: keep interfaces small so nobody implements or depends on methods they do not use. Dependency inversion: business logic depends on interfaces, and the database and vendors plug into those. They work together, open closed is the goal and the other four make it possible, and they are guidelines for code that changes, not rules for every file.

IndGeek provides solutions in the software field, and is a hub for ultimate Tech Knowledge.