SOLID Made Easy – Single Responsibility Principle

The SOLID principles are a foundation of good OOP practices. In order to develop high-quality software applications, it is essential for every developer to understand and to practice them.

SOLID stands for:

S – Single Responsibility Principle
O – Open/Closed Principle
L – Liskov’s Substitution
I –  Interface Segregation
D – Dependency Inversion

Single Responsibility Principle

Any object should only have a single responsibility and should only have one reason to change.

I read somewhere that some people applied this by having one function per class which is, of course, incorrect. A class can have multiple functions as long as the functions are all in relation to the responsibility of the class.

The responsibility of the class would depend on the context of the object. The context refers to the depth and the scope of the object. For example in a restaurant POS, we have a Manager model and the manager can perform transactions but cannot void transactions. In that example, the only time that we will change the Manager model is when the owner decides to say that the manager can void transactions.

A clear violation of the single responsibility principle is a god object. A god object is an object that does and knows too much. Here is an example of a god object:

This is an example of a god object because the RestaurantPOS class will be responsible for everything that is related to it. In the example, performing a transaction and managing the menu are shown but it would also include other modules like managing the employee, generating sales reports, etc. The class will get really complex and bloated. Once the system is finished this class will surely have thousands of lines of code.

Maintaining and debugging this class will be extremely hard. Imagine if something goes wrong in the processing of the transaction, you need to dig through this huge class in order to find and fix what’s wrong. Technically, in context, the RestaurantPOS is responsible for all the methods it has. What went wrong here is not on how it was defined but on how it was designed and implemented.

By creating separate interfaces for the transaction and the menu management and implementing them in separate classes will make the code more maintainable and easier to debug. If something goes wrong in the Menu class, we can easily navigate to it without seeing the code for the transactions that we don’t care about at the moment.

Also, we will be more confident that when we need to change something in the menu that it will only affect that object. If the owner says that we should be able to update an item on the menu then we need to change the interface and let the class implement it.

The single responsibility principle must be followed every time as it will immediately make our code better. It will make it more maintainable, extensible and testable. Before adding a property to a model, a method to a class, a set of new business logic to a method, ask yourself, is the object responsible for this?

If you have an opinion, feedback, or thoughts, do leave a comment. I’d love to read them.