The SOLID design principles applied to an actual Swiss Army Knife
The term swiss army knife is thrown around a lot when discussing the SOLID principles. Dave, that class looks like a swiss army knife. We need to refactor that shit. Yeah. Whatever. You know what, how about we see how a real swiss army knife stands up against the SOLID principles, huh?! Then we'll see who needs refactoring.
Single Responsibility Principle
The Single Responsibility Principle states:
Every object should have a single responsibility, i.e. a single reason to change
When looked at in terms of software, this means that a class should only do one thing - log errors, or send email, or determine if a person's name is funny. A class that finds any irreverence in a person's name should not be worried about sending email - it should delegate that off to an email service, which will email anyone who thinks that the name Wang Liqin is funny.*
But what about the swiss army knife? Let's count it's responsibilities:
- Knife
- Flat head screwdriver
- Philips head screwdriver
- Can opener
- Nail filer
- Bottle opener**
- Scissors
- A relatively hefty item that can be used as a projectile
Look at all of those responsibilities! A screwdriver and scissors in one device?? Madness. The swiss army knife clearly violates the SRP.
Principles | Swiss Army Knife |
---|---|
SRP | |
OCP | |
LSP | |
ISP | |
DIP |
Open-Closed Principle
The Open-Closed Principle states:
Objects should be open for extension, but closed for modification
In OOP, once a class is finalized it should not be changed (except for bug fixes, of course). The reason behind this is to ensure that existing functionality does not break when maintaining/adding to the codebase. Further functionality should be implemented using inheritance.
Let's apply the OCP to a Swiss Army Knife.
Closed for modification
There are no visible ways to open or take apart a swiss army knife. There are no screws or notches to pop open the case. It's definitely closed for modification. (Unless you hit it with a rock, but I think that's circumventing the rules.)
Open for extension
Well, we determined that there are no screws or any way visible to take apart a swiss army knife. There are no ports or cables either. But there is often a keyring on it, so you can, like, hang a spatula from it? Sure.
Principles | Swiss Army Knife |
---|---|
SRP | |
OCP | |
LSP | |
ISP | |
DIP |
Liskov-Substitution Principle
The Liskov-Substitution Principle states:
You should be able to use any derived class in place of a parent class and it should behave in the same manner with no modification.
In software, this means there should be no custom code required when using a child class in place of the parent class.
Does the swiss army knife violate the LSP? Well, if we think of the swiss army knife as the child, it would have parents of a knife, a pair of scissors, a screwdriver, etc. You can use the swiss army knife in place of each of the parents with no modification. It might just take you a bit longer to slice that turkey with your 3 inch blade.
Principles | Swiss Army Knife |
---|---|
SRP | |
OCP | |
LSP | |
ISP | |
DIP |
Interface Segregation Principle
The Interface Segregation Principle states:
Clients should not be forced to depend on interfaces they do not use
If you create an interface, the interface should have clearly defined functionality, and any classes implementing that interface should implement all properties/methods without any NotImplementedExceptions
or fake return values. The goal is to get rid of monster interfaces and create interfaces with directly related functionality.
The swiss army knife does not implement any interfaces (it's a freakin knife, yoh).
Principles | Swiss Army Knife |
---|---|
SRP | |
OCP | |
LSP | |
ISP | |
DIP |
Dependency Inversion Principle
The Dependency Inversion Principle states:
Classes should depend on abstractions for their dependencies
Common terms used when discussing the DIP are Dependency Injection and Inversion of Control. Basically, they say that classes should rely on interfaces or abstract classes for any outside dependencies they need, and not instantiate concrete objects themselves.
What dependencies does a swiss army knife have? Well, two main ones are an operator and a sharpener.
It definitely does not instantiate it's own operator, and it definitely relies on abstractions because it doesn't care of a person or a dog or a tree is using it. It also doesn't care if it's being sharpened with a $1,000 wet stone or on a rock you grabbed out of the river.
Principles | Swiss Army Knife |
---|---|
SRP | |
OCP | |
LSP | |
ISP | |
DIP |
Conclusion
The swiss army knife did pretty well, scoring a 3/5. Think twice before calling my classes swiss army knifes, because I call that a passing grade.
* Which should be everyone.
** The most important, if you ask me.