Interface Segregation Principle: SOLID Design Principles

Share the Article

What is Interface Segregation Principle

Interface Segregation Principle is one of the important principle for object oriented class designing. It is also contributing fourth letter “I” in SOLID acronym where I stands for Interface Segregation. This principle helps to build future modifiability and maintainability. It ensures that future extension and reusability becomes easy with less efforts.

Firstly, it is clear from name, “Interface Segregation” insists to segregate or separate interfaces of the abstract classes. This is needed so that derived classes need to know only required interfaces.

Basically, we should not have irreverent interfaces in the abstract base classes which derived class do not requires. Instead, we should group our interfaces into relevant hierarchy. “Interface Segregation” principle works very closely with “Single Responsibility” principle. If we have lots of interfaces which client do not requires, it will pollute the system. We should group interfaces based on features so that future extension of classes should be easy and more reliable.

Why

Lets us understand the need of “Interface Segregation” principle by taking an example of a School application which is constructing School and displaying its contents.

While designing School application we have taken reference of High School which is having below :

  • Student
  • Teachers
  • Facilities – Games
  • Faclity – Daycare

Below is the abstract base class School with interfaces for future school also:

class School { protected: int m_student; int m_teachers; string m_gameFacility; bool m_DayCare; public: virtual void setStudent(int count)=0; virtual void setTeacher(int count)=0; virtual void setGameFAcility( string game)=0; virtual void setDaycare(bool daycare)=0; virtual void showSchoolDetails()=0; };

Example not using Interface Segregation Principle

Lets create sample application for displaying High School:

#include<iostream> //main header for io #include<string> //for string using namespace std; //for namespace class School { protected: int m_student; int m_teachers; string m_gameFacility; bool m_DayCare; public: virtual void setStudent(int count)=0; virtual void setTeacher(int count)=0; virtual void setGameFAcility( string game)=0; virtual void setDaycare(bool daycare)=0; virtual void showSchoolDetails()=0; }; class HighSchool: public School { public: void setStudent(int count) { m_student=count; } void setTeacher(int count) { m_teachers=count; } void setGameFAcility( string game) { m_gameFacility=game; } void setDaycare(bool daycare) { m_DayCare=daycare; } void showSchoolDetails() { cout<< "Number of Students "<<m_student<<endl; cout<< "Number of Teachers "<<m_teachers<<endl; cout<< "Games supported "<<m_gameFacility<<endl; cout<< "Daycare facility "<<m_DayCare<<endl; } }; int main() { HighSchool s1; s1.setDaycare(true); s1.setGameFAcility( " Race jump swimming "); s1.setStudent(100); s1.setTeacher(10); s1.showSchoolDetails(); return 0; }

Now suppose, we have one more school in town Model School without games and daycare facility. Basically, this school is only having student and teachers. Since we have School abstract class so we have now derived new class Model School from School.

class ModelSchool: public School { public: void setStudent(int count) { m_student=count; } void setTeacher(int count) { m_teachers=count; } void setGameFacility(string game) { //Empty Member } void setDaycare(bool daycare) { //Empty Member } void showSchoolDetails() { cout<< "Number of Students "<<m_student<<endl; cout<< "Number of Teachers "<<m_teachers<<endl; cout<< "Games supported " << m_gameFacility << endl; cout<< "Daycare facility " <<m_DayCare<<endl; } };

As seen above, unnecessary setGameFacility( ) and setDaycare( ) interface got exposed for Model School also. Therefore, the client is now forced to implement this also which is not relevant for him. Actually, we are violating here “Interface Segregation” principle . With interface segregation principle we will get more modular and usable classes with less burden on client. Even sometime irrelevant interface can introduce unexpected behavior also in system.

How

Lets us try to update above application with interface segregation principle. Need to follow below rule :

Intelligently Group features as Abstract Base classes

For School we will create 2 groups. One group shall provide basic needs (i.e., student and Teacher). The other group shall provide luxury needs (i.e., games and daycare).

class School //GROUP 1 { protected: int m_student; int m_teachers; public: virtual void setStudent(int count)=0; virtual void setTeacher(int count)=0; }; class SchoolFacility //GROUP 2 { protected: string m_gameFacility; bool m_DayCare; public: virtual void setGameFAcility(string game) = 0; virtual void setDaycare(bool daycare) = 0; };

Derive classes from the main Base class

Based on Client need derived classes

class HighSchool: public School, public SchoolFacility class ModelSchool: public School

Below is the updated application:

#include<iostream> //main header for io #include<string> //for string using namespace std; //for namespace class School { protected: int m_student; int m_teachers; public: virtual void setStudent(int count)=0; virtual void setTeacher(int count)=0; }; class SchoolFacility { string m_gameFacility; bool m_DayCare; public: virtual void setGameFacility( string game) { m_gameFacility=game; } virtual void setDayCare(bool daycare) { m_DayCare=daycare; } virtual string getGameFacility() { return m_gameFacility; } virtual bool getDayCare() { return m_DayCare; } }; class HighSchool: public School, public SchoolFacility { public: void setStudent(int count) { m_student=count; } void setTeacher(int count) { m_teachers=count; } void setGameFacility( string game) { SchoolFacility::setGameFacility (game); } void setDayCare(bool daycare) { SchoolFacility::setDayCare(daycare); } void showSchoolDetails() { cout<<"High School Details "<<endl; cout<< " Number of Students "<<m_student<<endl; cout<<"Number of Teachers "<<m_teachers<<endl; cout<<" Games supported " << SchoolFacility::getGameFacility() <<endl; cout<<" Daycare facility " <<SchoolFacility::getDayCare() <<endl; } }; class ModelSchool: public School { public: void setStudent(int count) { m_student=count; } void setTeacher(int count) { m_teachers=count; } void showSchoolDetails() { cout<<"Model School Details "<<endl; cout<< " Number of Students "<<m_student<< endl; cout<<"Number of Teachers "<<m_teachers<< endl; } }; int main() { HighSchool s1; s1.setDayCare(true); s1.setGameFacility( " Race jump swimming "); s1.setStudent(100); s1.setTeacher(10); s1.showSchoolDetails(); ModelSchool sm; sm.setStudent(30); sm.setTeacher(5); sm.showSchoolDetails(); return 0; }

As seen above, now the interfaces are separated in 2 classes. It is upto Client’s need to derive accordingly. Finally, unnecessary burden of Luxury features such as games and daycare is removed from Model School.

Pros & Cons of Interface Segregation Principle

Pros:

  • Firstly, it ensures Modular design.
  • Secondly, it it causes low burden on client in terms of technical debt
  • Thirdly, Unit testing is easy.
  • Finally, future maintainability and reusability.

Cons:

  • If not applied intelligently, this may drastically increase the number of interfaces. Ironically, this may lead to increased maintenance and low readability

Main Funda: Interface Segregation enables classes to have many smaller interfaces and not one big interface.

Advanced C++ Topics

Single Responsibility Principle
Open Closed Principle
Liskov’s Substitution Principle
Singleton Design Pattern
Factory Method Design Pattern
Builder Design Pattern
How std::forward( ) works?
How std::move() function works?
What is reference collapsing?

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *