Sorry, but my brain has only one thread

Introduction

With the upcoming article series we are diving deeper in the world of good object oriented design. While you have learned about basic OO principles, we are taking a look at more advanced topics which will in turn have a much bigger impact on your code quality.

As the topic suggests I am going to talk about the so called SOLID principle.

In this particular writeup we are going to focus on the S part which stands for the Single Responsibility Principle. From now on called SRP.

The Problem with this problem

Did you ever find yourself in hacking onto the keyboard for a couple of hours and end up with 9572 lines of code in one class. I did. This one single class had the job of fetching, prioritizing, processing, converting and returning data via different channels. All while persisting every change of state. Have you tried to write good quality “Unit” tests for such a class? Well, good luck on that one! I would much rather try to freeze the sun, or try making time go backwards than to write tests for such a class.

Refactoring baby

Did you notice the enumeration of tasks my class had? If so, you are on the right track of understanding what the SRP is all about:

A class should have one and only one reason to change, meaning that a class should have only one job.

To simplify my horrifiying class a little let us break down the problem into smaller chunks:

  • Fetching data
  • Processing data
  • Sending processed data

Let’s say I want to look up a bunch of todays articles from different blogs or websites (fetching data), select the ones I am interested in (processing data), and send an eMail to myself with the all the great ones (sending processed data).

[pastacode lang=”java” manual=”public%20class%20ArticleService%20%7B%0A%0A%20%20%20%20%09public%20void%20findArticles()%20%7B%0A%20%20%20%20%09%09List%3CArticle%3E%20articles%20%3D%20fetchTodaysArticles()%3B%0A%20%20%20%20%09%09articles%20%3D%20filterInteresting(%22java%22%2C%20%22testing%22%2C%20%22clean%20coding%22%2C%20%22cats%22%2C%20%22lots%20of%20cats%22)%3B%0A%20%20%20%20%09%09sendMail(articles)%3B%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09private%20List%3CArticle%3E%20fetchTodaysArticles()%20%7B%0A%20%20%20%20%09%09%2F%2F%20getting%20all%20the%20great%20articles%20from%20today%20from%20simpleprogrammer.com%2C%20dzone.com%2C%20codeproject.com%2C%20et%20cetera.%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09private%20List%3CArticle%3E%20filterInteresting(String…%20buzzword%20)%20%7B%0A%20%20%20%20%09%09%2F%2F%20filter%20out%20all%20articles%20where%20the%20the%20topic%20does%20not%20contain%20any%20of%20the%20buzzwords%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09private%20void%20sendMail(List%3CArticle%3E%20articles)%20%7B%0A%20%20%20%20%09%09%2F%2F%20sends%20an%20eMail%20to%20myself%20containting%20a%20list%20of%20article%20topics%20and%20urls%0A%20%20%20%20%09%7D%0A%20%20%20%20%7D” message=”god class” highlight=”” provider=”manual”/]

Let’s assume I found a new great blog and want to add it into the list of articles to fetch data from. To do so i need to change ArticleService.class. Guess what class I need to change if I were to additionally send the eMail to my second address. Exactly. We need to change the same class for two reasons which sounds like a clear violation of the SRP.

But why bother anyways?, you might ask. What is wrong with changing one class for multiple reasons? A very good question. I actually asked myself this particular question about a hundred times before I started to realize the benefits of splitting classes apart and following the SRP. The main benefits are:

  • Reusablility
    Copying a class from one project to another and spending 2 hours adjusting the code only to make it work is frustrating and just a waste of time. Following the SRP will prevent that from happening. Copy + Paste a class from one project to another and BOOM. Works right out of the box.
  • Testability
    As mentioned before testing a class that is doing 12 things is a huge pain in the ass. You need to test every input parameter, every state, every possible outcome and so on. Whereas testing 12 single classes is pretty straight forward and makes sure that every single one is working perfectly fine (unit testing anyone?). On top of that there is no way of mocking, so every test ends up beeing an integration test. It is basically impossible to write good tests for such huge classes. Believe me, I tried. And failed big time.
  • Exchangeability
    By having each class beeing responsible for only one process it is way easier to change your desired behavior. We are living in the 21st century right. Who still sends eMails? Why not easily throw away your EmailSender.class, write a new one and let your oven read out the articles while you are watching the turkey getting ready? Try changing that in your 9572 lines of god.class (and make all your tests work again!)
  • Understandability
    The SRP helps you to think in an object oriented manner. It let’s you easily draw rectangles (classes) and connect them with arrows (flow of control). If you end up with a nice picture of every rectangle having one arrow in and one arrow out you did a great job of designing a low coupled model with light dependencies. This should be your ultimate goal. The moment you are in the need of connecting one rectangle multiple times you should rethink your architecture. Oh, and having one big rectangle with one arrow in and one out does not count.

So, how is SRP accomplished? Think about what your class is doing? In our example three main things. Fetching articles, filtering these and send them via mail. Split apart each working process into one class. We end up with three classes ArticleFetcher.class, ArticleFilter.class and EmailSender.class. But what about ArticleService.class? Isn’t it still doing 3 things? I would say no! Since all the work is done in each class separately, the ArticleService.class is only gluing the pieces together. Its only purpose is to make sure the code gets executed in the correct order. SRP, baby.

What have we learned?

The Single Responsibility Principle is all about separation of concern. A class should have only one reason to change. This is accomplished by separating every working process or task into one class. By doing so you get the benefits of low coupling, light dependencies, good testability, easy exchangeability and reusability.

Next time, we are looking at the SOLID – Open Closed Principle. Stay tuned.

 

Categories: Blog Posts