Europe: +41 78 715 83 09 - Asia: +84 ‎975 112 112
contact@finix.asia

Blog

1 Jan 2018

SOLID: Single Responsibility Principle

//
Comments0

Technologies used:   Kotlin 1.2.10 | Maven 3.3.9

Object-Oriented Terminology

In object-oriented programming (Kotlin, among other languages, follows this paradigm), you will often hear terms such as robustness, cohesion, coupling etc. Cohesion is a way to measure how much the code segments within one module (methods of a class, classes inside a package…) belong together. The higher the cohesion – the better, since high cohesion implies easier maintenance and debugging greater code functionality and reusability. The term cohesion is sometimes contrasted with the concept of coupling, and often, loose coupling of modules is related to high cohesion.

Another widely used term is robustness, which could be defined as the ability of a computer system or algorithm to handle mistakes and malfunctions (which could be caused by various factors such as programmer’s mistake or incorrectly formatted user input). A robust system is one that can handle these unwanted situations elegantly. There are various ways for a software engineer to achieve robustness, such as testing the code for different kinds of inputs, but generally, in order to achieve robustness (and high cohesion), programmers follow a certain set of rules and principles for better organization of object-oriented programs. One such principle is the single responsibility principle.

Single Responsibility Principle

The single responsibility principle revolves around the claim that a certain code module (most often, a class) should only have responsibility over one part of the functionality provided by the software. In software engineering books, this is sometimes also defined like this: the module should only have one reason to change. This means that a division of concerns is performed in the program, and the methods for every concern should be completely encapsulated by a single class. Now it is obvious that this approach contributes to the high cohesion – since methods related to the same concern (same part of the functionality) will be members of the same class, and robustness – since this reduces the possibility of error. Furthermore, if an error does occur, the programmer will be more likely to find the cause, and finally, solve the problem.

The single responsibility principle is founded on one of the basic, general ideas of object-oriented programming – the so-called divide and conquer principle – solving a problem by solving its multiple sub-problems. This approach prevents the creation of “God objects” – objects that “know too much or do too much“.

The classes you write, should not be a swiss army knife. They should do one thing, and to that one thing well.

BAD Example

Let’s consider this bad example of Object who can print himself

package guru.springframework

class Text {
    var text: String? = null
    var author: String? = null
    var length: Int = 0

    /*methods that change the text*/
    internal fun allLettersToUpperCase() {
        text = text!!.toUpperCase()
    }

    /*method for formatting output*/
    internal fun printText() {
        println(text)
    }
}

At first glance, this class might look correctly written. However, it contradicts the single responsibility principle, in that it has multiple reasons to change: we have tho methods which change the text itself, and one which prints the text for the user. If any of these methods is called, the class will change. This is also not good because it mixes the logic of the class with the presentation.

A Better Example

A Better way to write the above example is to separate the responsibility like that:

package guru.springframework

class Text {
    var text: String? = null
    var author: String? = null
    var length: Int = 0

    /*methods that change the text*/
    internal fun allLettersToUpperCase() {
        text = text!!.toUpperCase()
    }

}

class PrintText constructor(var text: Text) {

    /*method for formatting output*/
    internal fun printText() {
        println(text)
    }
}

Even though it’s not that noticeable in this example (since it is small), this kind of approach allows you to see the “bigger picture” and not lose yourself in the code; it makes programs easier to upgrade and expand, without the classes being too extensive, and the code becomes confusing.

Leave a Reply

Translate »