SOLID Principles — 1. Single Responsibility

Andrew MacMurray
4 min readMay 10, 2018

--

Having done very little Object Oriented programming before, I soon realised that the SOLID principles are considered very important — a guiding light for designing Object Oriented software.

SOLID is a subset of principles promoted by Robert.C.Martin, SOLID being an acronym for:

“five design principles intended to make software designs more understandable, flexible and maintainable.” — [1]

I’m used to writing in a more functional style, and my first attempts at writing my Java Tic Tac Toe application borrowed a little too much from FP (I was trying to write my application as if it were Elm!).

This was a mistake —Changing things quickly became difficult, and reading up on how my code was violating all the principles, my code started to feel like a courtroom drama! I have no interest in programming like it were an episode of Judge Judy; time to figure out what this whole SOLID thing is about.

Bianca Del Rio as Judge Judy, judging your code

And an important side note from my mentor — “don’t fight the language”

The S in SOLID

The S in solid stands for the “Single Responsibility Principle”. What does this mean? Robert Martin defines a responsibility as “a reason to change”.

“If you can think of more than one motive for changing a class, then that class has more than one responsibility.” — [2]

He uses the example of a rectangle class that’s responsible for calculating its area and drawing itself on a screen:

In this diagram the Rectangle is used by two different applications — the Graphical Application and the Geometry Application. The problem here is that the Geometry Application never uses the draw() method, but the Graphical Application might use both draw() and area() (and definitely uses draw()).

Robert Martin suggests that this design violates the Single Responsibility Principle and comes with a few nasty problems.

  • We have to include the GUI in the Geometry Application, even though we don’t use it, this seems like a large pointless dependency.
  • If changes in Graphical Application affect the Rectangle class, this means we would have to rebuild, retest and redeploy the Geometry Application. What if we forget to do this? Our Geometry application might break in unexpected ways.

How can we avoid these problems?

Robert Martin suggests splitting the Rectangle up into two separate classes: a Geometric Rectangle and a Rectangle:

A nice property of this design is that the Rectangle can ask the Geometric Rectangle for the calculations it needs but the Geometric Rectangle no longer needs to depend on the Graphical Application or the GUI.

This simple change has profound and pleasant effects on our code! Changes to our Graphical Application no longer affect our Geometry Application.

Beware Separating for the Sake of it

I think it’s important to emphasise the risk of going too far in the opposite direction. If we follow SRP beyond its limit we may reach tiny classes that all do what we think may be “one thing” our application could soon become a pain to work with.

I encountered this problem fairly quickly with my Tic Tac Toe application, for example:

My application needed to display the game via the command line. My initial thought was to separate out the UI into parts that could Read input from the user and Show output on the console:

// UIShow.javapublic interface UIShow {

void greetUser();

void showBoard(Board board);

void showFinalResult();

...
}
// UIRead.javapublic interface UIRead {

int requestMove(Player player);

int requestBoardSize();

...

}

This worked out nicely at first, but it soon became irritating when I needed to show a result of reading user input. Maybe read and show should have actually been together in the first place — the UI is responsible for both.

Sandi Metz in notes on SRP that:

“SRP doesn’t require that a class do only one very narrow thing or that it change for only a single nitpicky reason, instead SRP requires that a class be cohesive — that everything the class does be highly related to its purpose” — [3]

Keeping a class cohesive seems to be the most important takeaway here: classes can do a number of things but they should all be highly related to their purpose. This principle helps us design applications that are easy and pleasant to extend and change:

“Design is more the art of preserving changeability than it is the act of achieving perfection.” — [3]

Conclusion

I find it amazing how a deceptively simple principle can have a massive impact on how easy it is to extend my code. I’m sure it will be a continual tightrope walk finding the right balance for classes to have too much or too little responsibility.

References

[1] — SOLID (Object Oriented Design) — Wikipedia

[2] — Agile Principles, Patterns, and Practices in C# by Robert C. Martin, Micah Martin

[3] — Sandi Metz — Practical Object Oriented Design in Ruby

--

--