Reviewing S.O.L.I.D
Thomas J. Kennedy
1 Where We Started
During the first week of class under The Beginning in the orientation module we briefly discussed S.O.L.I.D. We split the acronym (i.e., S.O.L.I.D. into two parts).
S.O.L.I.D = (S.O.) + (L.I.D.)
S.O. can be discussed using only the knowledge from CS 250. Any extra knowledge from CS 330 or CS 361 is a bonus.
What is S.O.? No, it is not a sarcastic child.
- S - Single Responsibility Principle
- O - Open/Closed Principle
These emerge naturally out of how we write code. We want to write reusable functions and classes. We want to be able to extend those functions and classes without modifying the underlying code. Think about:
- C++
std::vector
std::list
std::unordered_map
std::iterator
- Java
java.util.List
java.util.Map
java.util.Iterator
We used these ADTs (in the case of Java) interfaces throughout our examples, discussions, and assignments.
2 What About the L.I.D?
What about the remaining three (3) letters?
- L - Liskov Substitution
- I - Interface Segregation
- D - Dependency Inversion
3 Combining Everything
Now that we have covered inheritance and subtyping, we can combine everything, including the L
:
-
S - Single Responsibility Principle
Every class, module, or interface has one responsibility (i.e., purpose).
-
O - Open/Closed Principle
It should be possible to extend a class, module, or function without modifying the original code.
-
L - Liskov Substitution
If I write a function to work with an
class
, orinterface
, any object that provides or specializes thatclass
orinterface
should work. Think about- Using
istream
instead ofifstream
orstd::cin
in our C++ discussions. - Using
ostream
instead ofofstream
orstd::cout
in our C++ discussions. - Replacing
ArrayList<Shape>
withList<Shape>
in the Java Shapes Case Study. - Replacing
.stream()
with.parallelStream()
in the Java Shapes Case Study. - The Java
Runnable
interface. - The Java
Listener
interface.
- Using
-
I - Interface Segregation
Fight the urge to throw in the kitchen sink. Focus on creating problem specific interfaces, not monolithic kitchen-sink-interfaces. This requires us to codify how to decompose a large problem (high-level design).
-
D - Dependency Inversion
Modules should not directly handle low-level calls and operations. Consider the C
FILE*
vs the C++ofstream
andifstream
.