{{announcement.body}}
{{announcement.title}}

Single Responsibility Principle: SOLID as a Rock

DZone 's Guide to

Single Responsibility Principle: SOLID as a Rock

In this article, we will see an example of the Single Responsibility Principle in C++ along with its benefits and generic guideline.

· Agile Zone ·
Free Resource

This article is the first part of a five-part series about the SOLID as Rock design principle series. The SOLID design principles focus on developing software that is easy to maintainable, reusable, and extendable. In this article, we will see an example of the Single Responsibility Principle in C++ along with its benefits and generic guideline.

Intent

 A class should have only one reason to change 

In other words, SRP states that classes should be cohesive to the point that it has a single responsibility, where responsibility defines as "a reason for the change." 

Violating the Single Responsibility Principle

C++
 




x
24


 
1
class Journal {
2
    string          m_title;
3
    vector<string>  m_entries;
4
 
          
5
public:
6
    explicit Journal(const string  andtitle) : m_title{title} {}
7
    void add_entries(const string  andentry) {
8
        static uint32_t count = 1;
9
        m_entries.push_back(to_string(count++) + ": " + entry);
10
    }
11
    auto get_entries() const { return m_entries; }
12
    void save(const string  andfilename) {
13
        ofstream ofs(filename); 
14
        for (auto  ands : m_entries) ofs << s << endl;
15
    }
16
};
17
 
          
18
int  main() {
19
    Journal journal{"Dear XYZ"};
20
    journal.add_entries("I ate a bug");
21
    journal.add_entries("I cried today");
22
    journal.save("diary.txt");
23
    return EXIT_SUCCESS;
24
}


  • Above C++ example seems fine as long as you have a single domain object i.e. Journal. but this is not usually the case in a real-world application. 
  • As we start adding domain objects like Book, File, etc. you have to implement save method for everyone separately which is not the actual problem.
  • The real problem arises when you have to change or maintain save functionality. For instance, some other day you will no longer save data on files  and adopted database. In this case, you have to go through every domain object implementation  and need to change code all over which is not good. 
  • Here, we have violated the Single Responsibility Principle by providing Journalclass two reason to change i.e. 
    • Things related to Journal 
    • Saving the Journal
  • Moreover, code will also become repetitive, bloated  and hard to maintain.

Single Responsibility Principle Example

C++
 




xxxxxxxxxx
1
27


 
1
class Journal {
2
    string          m_title;
3
    vector<string>  m_entries;
4
 
          
5
public:
6
    explicit Journal(const string  andtitle) : m_title{title} {} 
7
    void add_entries(const string  andentry) {
8
        static uint32_t count = 1;
9
        m_entries.push_back(to_string(count++) + ": " + entry);
10
    } 
11
    auto get_entries() const { return m_entries; }
12
    //void save(const string  andfilename)
13
    //{
14
    //    ofstream ofs(filename); 
15
    //    for (auto  ands : m_entries) ofs << s << endl;
16
    //}
17
};
18
 
          
19
struct SavingManager {
20
    static void save(const Journal  andj, const string  andfilename) {
21
        ofstream ofs(filename);
22
        for (auto  ands : j.get_entries())
23
            ofs << s << endl;
24
    }
25
};
26
 
          
27
SavingManager::save(journal, "diary.txt");


  • Journal should only take care of entries  and things related to the journal. 
  • And there should be one separate central location or entity which does the work of saving. In our case, its  SavingManager.
  • As your SavingManager grows, you have all the saving related code will be at one place. You can also templatize it to accept more domain objects.

Benefits of Single Responsibility Principle 

=> Expressiveness

  • When the class only does one thing, its interface usually has a small number of methods which is more expressive. Hence, It also has a small number of data members.  
  • This improves your development speed and makes your life as a software developer a lot easier. 

=> Maintainability

  • We all know that requirements change over time  and so does the design/architecture. The more responsibilities your class has, the more often you need to change it.  If your class implements multiple responsibilities, they are no longer independent of each other. 
  • Isolated changes reduce the breaking of other unrelated areas of the software. 
  • As programming errors are inversely proportional to complexity, being easier to understand makes the code less prone to bugs and easier to maintain.

=> Reusability

  • If a class has multiple responsibilities and only one of those needs in another area of the software, then the other unnecessary responsibilities hinder reusability. 
  • Having a single responsibility means the class should be reusable without or less modification.

Yardstick to Craft SRP Friendly Software

  • SRP is a double-edged sword. Be too specific  and you will end up having hundreds of ridiculously interconnected classes, that could easily be one. 
  • You should not use SOLID principles when you feel you are over-engineering. If you boil down the Single Responsibility Principle, the generic idea would be like this:

The SRP is about limiting the impact of change. So, gather together the things that change for the same reasons. Separate those things that change for different reasons.

  • Adding more to this, If your class constructor has more than 5-6 parameters then it means either you are not followed SRP or you are not aware of builder design pattern.

Conclusion

The SRP is a widely quoted justification for refactoring. This is often done without a full understanding of the point of the SRP and its context, leading to fragmentation of codebases with a range of negative consequences. Instead of being a one-way street to minimally sized classes, the SRP is actually proposing a balance point between aggregation and division.

Topics:
agile ,c++ ,coding ,design pattens ,programming ,solid design principles examples

Published at DZone with permission of Vishal Chovatiya . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}