Every good software is based on fundamental principles, every developer should know. This article explains the single responsibilities principle using a simple example. It introduces a new diagram to identify responsibilities of a class and a simple refactoring to get rid of multiple responsibilities.
What are Principles?
If you want to develop proper software, you must have an idea what *proper* means. Sometimes this idea is rough and intuitive. But to teach such an idea or to communicate about it, this idea should be manifested in a more concrete form: a principle. Principles are the very fundamentals of developing good software. You should either know them, or have an intuitive understanding of them. Without applying them, you can never claim, that you wrote good software. Many people do so anyway 🙂
In this post I want to explain one principle of Object Oriented Design (OOD) on a simple example.
The S in S.O.L.I.D.
There are lots of written principles for every programming paradigm. For Object Oriented Design, S.O.L.I.D. is an acronym summarizing for five of these principles. This post is about the first of those principles: The Single Responsibility Principle. It can be abbreviated with SRP itself.
The original wording sounds as
There should never be more than one reason for a class to change. – Robert C. Martin
This sentence is a little bit hard to grasp. An easier understandable version would be
A class shouldn’t have more than one responsibility. – Waog (probably not the first who says that)
I won’t describe why it is a good or useful principle, but we can discuss this in the comments if you think different.
A simple Example
So lets take a look at this simple example class:
We have a Car class here, with two private variables (second compartment) and four methods (third compartment). The class violates the Single Responsibility Principle because it has more than one Responsibility.
Without applying principles, you can never claim, that you wrote good software. Many people do so anyway 🙂
Identifying the Responsibilities
Intuitively it’s easy to grasp that the above Car class has multiple responsibilities, because we already have a good intuition for cars. It’s a little bit more tricky to identify the exact responsibilities by intuition.
But you don’t want to learn something about my fancy Car-Class, but something which you can apply to your future code. So a good intuition for the class in question can’t be assumed. Instead we need some general rules to identify the responsibilities.
For this we use another graphical notation to represent the same class. (I don’t know if this notation has a special name, I came up with it on my own. Please tell me if you know):
This diagram contains some information which wasn’t visible in the class diagram before: the dependencies between it’s content. In this diagram, each responsibility got one color: yellow and blue. They can be identified by finding the so-called connected components. Between the blue and the yellow components there are no connections, so each of them is one responsibility.
Removing the first Responsibility
Now if you found a class with multiple responsibilities, it’s bad software. You have to pull the additional responsibilities out of the class. In our Car-example we pull out all the blue components into a new Engine class:
We could also have pulled out the yellow components into a DoorLight class. Now we’re ready. Or not?
Removing the second Responsibility
Our Car still has multiple responsibilities. Intuitively said, it has the responsibility to manage the Door-&-Light-Stuff and the responsibility to aggregate other objects. This can be seen with the previous rules, if we don’t draw the composition as an edge, but as an attribute:
Now we can again apply the second diagram type to the new Car:
And we can pull out the yellow connected component this time:
Now our Car only has one responsibility, right?
Coming to an End
If we stoically apply the previous rules, the Car still has two responsibilities.
But here we have to come to an end instead. The additional rule we need is: don’t pull out single components. They would only introduce a Middle Man. So instead we’re just finished with our three classes: Car, DoorLight and Engine, each with exactly one responsibility.
The example and refactoring are overly simplified to give you a first Idea of the Single Responsibility Principle. Applying my method to identify the responsibilities will give you a good first hint in your future examples. Applying the refactoring and especially the end-criterion won’t make sense on more complex examples, but gives you a first hint how to think about the topic.
After a short motivation why we need principles, the Single Responsibility Principle was defined. A new diagram was introduced, to identify responsibilities of a class. Also a simple exemplary refactoring to reduce multiple responsibilities was shown.