SOLID CODE: Single Responsibility Principle

Beribey
5 min readDec 31, 2020

--

To become a senior among millions of programmers!

Photo by Tim Mossholder on Unsplash

I already have a general article on the SOLID Principle, OOP design principles. Remind a little bit for you guys forgot.

These are the principles drawn by countless developers, drawn from thousands of successful and failed projects. A project that applies these principles will have easier to read, test, and clearer code. And the most important thing is that the maintenance code will be a lot easier.

Mastering these principles and applying them in the design + code will help you go one step further on the path to becoming a senior (a senior man from FPT Software used to tell me that).

SOLID includes the following 5 principles:

  1. Single Responsibility Principle
  2. Open / Closed Principle
  3. Liskov Substitution Principle
  4. Interface Segregation Principle
  5. Dependency Inversion Principle

Introduction

In the first article, I will talk about the Single Responsibility Principle.

A class should hold only one responsibility (Class can only be changed for a single reason)

Explain the principle

Photo by Michael Heng on Unsplash

We can roughly understand “responsibility” here as equivalent to “function.” Why should a class keep only one function ?? To understand this, look at the image below.

See the knife in the picture as a class with lots of functionality. This knife “seems” quite handy, but cumbersome and heavy. In particular, when one part is damaged, the whole knife must be removed to repair it. Repairs and improvements are complex, which can affect many different components.

A class with too many functions will also become cumbersome and complex. In the IT industry, the requirement was fickle, leading to code changes. If a class has too many functions, is too cumbersome, changing the code will be very difficult, take a long time, and easily affect other active modules.

Apply SRP to the knife above; we can split it into scissors, knife, open the cork, … separately, it’s done, fix it for something damaged. With the same code, we only need to design modules to be simple; a module with only one function is done (That said, defining and grouping functions is not easy).

SRP

Example

The code below is an example of the SRP violation. This error was often made when I first learned to code. The Student class has too many functions: storing student information, formatting information, and storing information.

public class Student {
public string Name {get; set;}
public int Age {get; set;}

// Format this class as text, html, json to print
public string GetStudentInfoText () {
return "Name:" + Name + ". Age:" + Age;
}
public string GetStudentInfoHTML () {
return "<span>" + Name + "" + Age + "</span>";
}
public string GetStudentInfoJson () {
return Json.Serialize (this);
}
// Store to database, down to file
public void SaveToDatabase () {
dbContext.Save (this);
}
public void SaveToFile () {
Files.Save (this, "fileName.txt");
}
}

Code like that is okay? It’s okay, but as the code gets bigger, more functions are added, the Student class will get bloated. If there are more other classes such as Person, Teacher v … v, the code to display/store information will be scattered in many classes, it isn't easy to repair and upgrade.

To solve this, we need to split into many classes; each class has its own function. When it comes to upgrading and repairing, it will take place in each class, not affecting the rest of the class.

// Student now contains only information
public class Student {
public string Name {get; set;}
public int Age {get; set;}
}

// This class only formats information to display student
public class Formatter {
public string FormatStudentText (Student std) {
return "Name:" + std.Name + ". Age:" + std.Age;
}
public string FormatStudentHtml (Student std) {
return "<span>" + std.Name + "" + std.Age + "</span>";
}
public string FormatStudentJson (Student std) {
return Json.Serialize (std);
}
}

// This class only takes care of storage
public class Store {
public void SaveToDatabase (Student std) {
dbContext.Save (std);
}
public void SaveToFile (Student std) {
Files.Save (std, "fileName.txt");
}
}

Note: This principle should not always be applied to code. One common cause is the Helper or Utilities class — these classes outright violate the SRP. If the number of functions is small, it is still possible to put all of these functions in a class; after all, all the helper functions are capable of handling small tasks.

// Class Helper violates SRP
// But because it's small, we can ignore it
public class Helper {
public string GetUser ();
public DateTime GetTime ();
public string GetCurrentLocation ();
public DbConnection GetDatabaseConnection ();
}

However, as Helper adds more functions, it becomes more complicated and cumbersome (My friend had a class with nearly 10,000 lines). At this point, we need to apply SRP to divide it into small modules for easy management.

// The helper is big, we need a split
public class Helper {
public string GetUser ();
// ... ..
public DateTime GetTime ();
// ... ..
public string GetCurrentLocation ();
// ... ..
public DbConnection GetDatabaseConnection ();
}

// Split helper into smaller helper
public class UserHelper {
}
public class TimeLocationHelper {
}
public class DatabaseHelper {
}

Conclusion

In essence, a principle is a principle; it is only a guide, not an absolutely unchanging rule. If you investigate carefully, you will find that there are still a few programmers who dissect, object, and point out these principles' flaws. However, understanding them still makes the code we write easier to read, understand, and manage.

SRP is the simplest principle to understand but also the most difficult to apply correctly. The difference between a good developer and the normal developer is that both know about the rules and principles, but a good developer will know when to apply, when not.

The rest of the SOLID principles will be introduced in the following articles. Have any questions or suggestions; please feel free to raise them in the comments; I will try to answer them.

References

--

--

Beribey

Always be nice to anybody who has access to my toothbrush.