A week ago, I twitted:
"SOLID of uncle Bob, How I see them?"
And got a nice like from Uncle Bob :)
I am a big fan of SOLID!
Not only that, time after time, I elaborated my own words to express SOLID principles. And as you can see below, I noticed it is almost all about embracing the #change, mastering the #change and anticipating the #change..
[S]: a Unique decider of #change!
Whenever you pack some of your code into a module (i.e: function, class, package..), there must be a unique thing(often a business department or tech dependency), that will force you to #change the code of that module.
One, and not two, or twenty, only one!
[O]: Minimize touched code if you HAVE to #change
"Open for extension / closed for modification", right?
Well, there is nothing which is open AND closed at the same time, you know! Your code will be ALWAYS open for modification, otherwise, let's apply TripleDES encryption on each of our classes and then delete the key. Thus we have a really closed module.
That's why I believe "closed to modification" should be suffixed with: "except the very tiny piece that will be used to connect the old code with the newly added one"
[L]:Your problem is not mine
Ok this principle has the scariest words, but from my point of view what it wants us to avoid is writing subclasses which add rules to the ones it inherits from. (that's rude right?)
Hence my way to see it as a "Your problem is not mine".
Suppose you ship a package to your customers, who are developers in this case. And one day you provide them a new version consisting of a submodule of the old one, but with a bunch of silent restrictions and rules. You only did that to solve some of your own code problems some where..
How would you imagine the face of that poor developer trying to figure out WHY are you doing this? Don't you think that "Your problem is not his problem" ?
[I]: Don't pull all your eggs in one basket
The official version of the principle is:
“Clients should not be forced to depend upon interfaces that they do not use.”
Again, my intuitive question here is: Nice, but why? or, what does it try to troubleshoot?
And my answer is: it clearly fights those hasty guys (including me sometimes :)) who write those allknowing interfaces having a dozen of methods. Some ultimate interface and called IReadWriteCompress or ReadWriteCompressInterface..
Without even looking into the code, we feel the instinct and the urge to split that BigTank into three small speed-boats, for instance: WriteInterface, ReadInterface and CompressInterface.
So one should not pull all his eggs in one basket, or all his methods in one interface!
[D]: Rely on the least #changing dependency
"High-level modules should not depend on low-level modules. Both should depend on abstractions"
Ok, but why?
The answer I could come up with is: "no one wants to depend on loosely changing element right?"
And this makes it obvious to go for dependency on abstractions rather than dependency on implementations (aka low-level modules).
Low-Level usually has way more details and information to tell than abstractions. Abstractions only expose the big picture which is supposed to last.
Abstractions have less details, which means adapting to their #changes is always easier.
So, that was it, and I would be glad if you could also share your own SOLID versions with me :)