The SOLID design principles applied to an actual Swiss Army Knife

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.

PrinciplesSwiss 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.

PrinciplesSwiss 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.

PrinciplesSwiss 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).

PrinciplesSwiss 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.

PrinciplesSwiss 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.