SOLID is a popular term in the world of laymen's software engineering. It's just a rewrite of basic OOP concepts - there's nothing new in it. But it was made from terms rummaged from the past 30 years, and those are fun. It's not an acronym - the letters don't stand for a phrase. It's 5 different things, in 5 different styles.
As a reference, and to explain what I mean about them being just a rewrite, let''s review the basics of modern OOP. This is the stuff you know after a year-long freshman programming class:
Classes should be designed by first making an interface describing how others can use it. They should be large enough to be useful, but not so large they're cumbersome. They should be abstract - write setDisabled() instead of changeColorToDisabled(). Roughly that gives us encapsulation and loose coupling. If you want multiple versions of a class to use as plug-ins, have them all inherit from a base class.
A real explanation has details and examples - chapters of them, but that paragraph is the outline. Small encapsulated classes taking advantage of base classes to communicate. On to the 5 things in SOLID:
The "D" is "Dependency Inversion". This is an old phrase aimed at 1970's programmers. It essentially says to take the way you programmed back then, and flip it on it's head - totally invert it. So clearly, not much help to non-1970's coders, but looking back is really interesting:
Old-style programs were centered on the exact format of the data. Space was tight - memory sizes were a few hundred kilobytes with reel-to-reel tape as a back-up. We needed to preplan to cram our data. We used tricks like compressed formats, "just knowing" lengths, 1/2-bytes, rounding, and double-using slots as numbers or letters. CPU's were slow, so every other part of the program needed to know that formats to be able to pull data in the fastest way.
As we know, memory and speed started doubling every few years. Also, as we know, writing a program where every part needs to know how every other parts works is really, really hard. It's what we use encapsulation to avoid. So things quickly flipped. We stopped using that super-efficient data-first style, and switched to a modular/OOP style of today. We "waste" a bunch of memory and speed, in exchange for fewer bugs and not needing all geniuses and 5 years to write one program.
To summarize: all code used to need to know everything about data, now we hide that on purpose. That's the inversion, so Dependency Inversion just means encapsulation.
S stands for "single responsibility principle". It's a nice term. When we're breaking our program into classes we need a guide as to where and how many. SRP says to make classes just big enough to have one responsibility. Responsibility is a nice word for "maybe a bunch of stuff, but it all goes together".
But it's not helpful. Responsibility is too slippery a word, and isn't a computer term anyway. For real, you make classes on a practical basis, based on your exact program. If three particular things always go together, one class handling them all is fine, even preferred. Normally we split managing data into a different class from showing data; but if there's only one way to show it, a single class that can display itself is better. If we have places where we need to use only 1/2 of some class, that's where we split it into two. Stopping to think "is that one responsibility?" won't help with any of that.
I is the "Interface Segregation Principle". It says not to make your interfaces too big - you should segregate them into smaller ones. But an interface is how you talk to a class, so it's just another way of saying not to make classes too big, which SRP already says. This rule is a repeat. We could eliminate it and turn solid into SOLD. But this term is more fun history:
Today, Java uses
interface as an official word for a
type of class. It's very object oriented. But we
used interfaces long before that. An API - application programming
interface - is just a collection of functions. Way back, one file with normal
functions, working together to do something - that was an interface.
If you were working back then, and wanted to say "don't pile up too much
different stuff together", you complained about the interface being too big.
The common examples of ISP violations with too-big interfaces are a little strange. They're about functions where anyone would need to supply dummy values. For example, an animal creation function requiring flight speed, eggs laid, and frequency of shedding skin - no animal has them all. That's not wrong, but the more common problem is just too many functions for too many types of things, where you have trouble figuring out the one you want. The animal thing isn't even really a problem - we often write a bird-creating function that fills in a 0 for shedding.
"L" is the only one about polymorphism, but about one small part of it. Suppose you use a Button class with a placeButton() function. Say there are two types of buttons, which are sub-classes. A button variable could point to either of them. That's a pretty basic set-up. Suppose one overrides placeButton() and lets it hang off the edge of the screen, while the other shrinks it to fit. Neither way is wrong, but since we could substitute one for the other, they combination is wrong. We need them to be consistent.
The official name is Liskov Substitution Principle. Who Liskov is, is more cool history:
In the 80's software engineering conferences were inventing object oriented programming - trying to figure out how it would work in a real computer language. That involves lots of math and proofs and making up new terms. A paper from Barbara Liskov described the consistency problem, said the subtypes need to be able to substitute for each other, then had lots of math explaining what that meant. Like most things, OOP was invented by dozens of PhD's, over years of meetings.
There's only one example of LSP on the internet, which isn't really an example. Start with a resizable Rectangle class - width and height and functions to set them. Have Square inherit from Rectangle. Square's set functions need to be overriden to keep it square - setWidth(4) also changes the height to 4. That's the example, and the wrong part is how r1.setWidth(4) might also change the height, or not, since it might be a Square or not. But that's just wrong class design. LSP is really about where the design is fine and you made a mistake with some functions.
That square/rectangle is a good example, but of a different thing: don't try to make classes based how things seem in real-life. Just think whether you want an adjustable rectangle variable, which could also point to something which keeps itself square. You probably don't.
The O rule is about not messing with tested general-purpose code. Especially, don't change it so it can do one thing differently for this one case you have. That tends to add bugs to completely different parts of the program, where someone was innocently using that code. There's even a word for it: regression testing finds "something broke that I swear I didn't touch" bugs.
The standard, old-fashioned OOP way to change a class is by making a child class, overriding some functions to make the changes. It's also common to add spots for plug-in functions. To make a "changeable" function, just try to give it useful options - placeButton() can have an optional alignHow parameter, and so on.
The official phrase is "Open/Closed Principle" - open to extension (another word for inheritance), closed to changes. Those are from a paper where open and closed had technical definitions. The problem is they aren't actionable. There's nothing you do to make something closed to changes - just ask people not to change it. The more useful you make it, the less they'll want to. And that's all "open" really means - options to use it and tweak it in more ways.
So, SOLID is a way to explain basic OOP. Except it's in the wrong order, uses awkward outdated terms, leaves a lot out, and is light on examples. But you knew that. You didn't think this was the first time in history a complex system was reduced to 5 ideas that made a cool word, and that turned out to be useful. I mean, SOLID is just "5 tips for ...". And we know how useful those are.
Comments. or email adminATtaxesforcatses.com