Tech Point Fundamentals

Sunday, January 16, 2022

Interface Segregation Principle of SOLID | ISP

Interface Segregation Principle of SOLID | ISP

Interface-Segregation-Principle

SOLID Principles are one of the mandatory questions in each and every interview. This is the 5th part of the SOLID Design PrincipleIn this part, we will walk through the 4th SOLID Design Principle i.e Interface Segregation Principle (ISP) in detail with live real examples. 


Please read the previous parts here over the below links:


SOLID Design Principles

Single Responsibility Principle

Open Closed Principle

Liskov Substitution Principle


Watch our videos here




Introduction


In the SOLID acronym, the fourth letter "I" represents the "Interface Segregation Principle"Segregation means keeping things separated, and the Interface Segregation Principle is about separating the interfacesThis principle is related to the Single Responsibility Principle in that even interfaces also should have a single purpose.


Using interfaces is one of the best ways to allow the extensibility and testability of the application.  ISP is intended to keep a system decoupled so that it is easier to refactor, change, test and redeploy.


Interfaces should belong to clients, not to libraries or hierarchies. Application developers should favor thin and focused interfaces compared to "fat" interfaces that offer more functionality than a particular class or method needs.


Ideally, your thin interfaces should be cohesive, meaning they have groups of operations that logically belong together. This will prevent you from ending up with one-interface-per-method most of the time in real-world systems. Another benefit of smaller interfaces is that they are easier to implement fully, and therefore less likely to break the Liskov Substitution Principle by being only partially implemented.


In many OOPS languages like C#, interfaces can inherit from multiple other interfaces. So, if you need a larger interface in some parts of the application, but not in others, you can compose it from two or more other interfaces as well. 




Interface Segregation Principle (ISP)


The Interface Segregation Principle is the fourth SOLID Design Principle. Segregation means keeping things separated, and the Interface Segregation Principle is about separating the interfaces.


The Interface Segregation Principle was first used and formulated by Robert C. Martin while consulting for Xerox to help them build the software for their new printer systems. 


So in short the interfaces should also follow the first rule of  SOLID i.e Single Responsibility Principle. Similar to the Single Responsibility Principle, the goal of the Interface Segregation Principle is to reduce the side effects and frequency of required changes by splitting the software into multiple, independent parts.




Definition of ISP


Interface Segregation Principle splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them


According to Robert C. Martin:


Clients should not be forced to depend upon interfaces that they do not use.


In other words:


"Many client-specific interfaces are better than one general-purpose interface."


The Interface Segregation Principle states that no client should be forced to depend on methods that it does not useSo here this principle basically says two things:


a) No class should be forced to implement any method(s) of an interface they don’t use or are not related.

b) Instead of creating large or fat interfaces create multiple smaller interfaces so that the clients (class) should only think about the methods that are of interest to them (related).


Hence keep the interface as simple and small as possible. If required an interface can inherit from other interfaces to have the other behavior. On the other hand, the concrete class or client can also implement multiple interfaces as multiple interface inheritance are allowed.




Explanation


A client should never be forced to implement an interface that it doesn’t useor clients should not be forced to depend on methods they do not use. This is only achievable if you define your interfaces so that they fit a specific client or task.


So larger interfaces should be split into smaller ones. By doing so, we can ensure that implementing classes only need to be concerned about the methods that are of interest to them. The code that violates ISP is also known as ‘Interface Pollution’. 


An interface is implemented by the classes or clients. If the interface contains non-related methods then the client must have to implement those non-related or non required methods also whether they are required or not by the client or class. 


And according to the Liskov Substitution Principle, the child class or derived class should not keep any base class or interface method non-implemented.  So if you implemented an interface and you have to throw NotImplementedExceptions as you don't require those implementations you are probably doing something wrong and also violating both the Liskov Substitution Principle and Interface Segregation Principle.


When it comes to developing your own classes, think about the specific functionality needed and split that into different interfaces. This satisfies the ISP principle as classes that inherit the interfaces aren’t required to implement functionality they don’t need.




Interface Segregation Principle vs. Single Responsibility Principle


The goal of both the Interface Segregation Principle and Single Responsibility Principle is pretty much the same i.e ensuring small, focused, and highly cohesive software components.


The only difference is that the Single Responsibility Principle is concerned with classes, while the Interface Segregation Principle is concerned with interfaces. 


In Object-Oriented Programming, we normally use an interface to be implemented by the classes, if our interface follows the ISP, the implementing class is automatically going to adhere to the SRP.


When applying the ISP to software development, we separate interfaces into their functional areas similar to the SRP.  Where SRP is applied to classes and methods, ISP applies to interfaces.




Real Example of Interface Segregation Principles in the .Net Framework


The Interface Segregation Principle is used very effectively in the .NET Framework. One of the keys to making LINQ work is the IQueryable<T> interface and it is defined as:


IQueryable

As you can see, IQueryable<T> inherits from three other interfaces and these three separate interfaces have only required and related methods only. For example, IEnumerable<T> defines the enumerator over generic collections while IEnumerable over non-generic collections.


Similarly, some other examples of ISP like Array, String, DateTime, Int32, and Delegate are as below:


ISP-In-dot-net




Example


Consider a Repository interface having only two methods to read and write data. So classes can implement to read and write data from different sources like SQL database, MySQL database, Oracle database, or XML file. Sometimes we need to read some configuration or property data from the XML file. But it is not for external users i.e it is read-only.


interface IRepository
{
	void Write(object data);
	object Read();
}


public class DatabaseRepository : IRepository
{
	public object Read()
	{
		//Logic to read data from the database 
		return new object();
	}

	public void Write(object data)
	{
		//Logic to write data into the Database
	}
}

public class XMLRepository : IRepository
{
	public object Read()
	{
		//Logic to read data from the XML 
		return new object();
	}

	public void Write(object data)
	{
		//Don't allow a user to write data to the XML Repository.
		throw new NotImplementedException();
	}
	}
}

The developer has moved both Read() and Write() methods in a single IRepository interface. The above interface probably contains the related or you can say logically related methods. But as per the client's need (XMLRepository class), the Write() method is not relevant. So it is violating the ISP as XMLRepository implementing an interface whose methods actually don't require by it.



Also if you think this implementation is for the future perspective, this is not extensible. For example, in the future, it might be possible that there is a Master-Slave database architecture:

a)  All the write operations must be associated with the WriteOnlyDatabase i.e master database. Likewise, scalability can often be improved by queuing commands (for write operations) rather than executing them immediately. 

b) All the read operations must be served by the ReadOnlyDatabase i.e slave database. A common performance pattern for database reads it so add a caching layer, but this generally only makes sense only for read operations. 

So now it makes sense to separate these two methods separately and follow the ISP. Thus, having an IRepository interface composed of an IReadOnlyRepository and an IWriteOnlyRepository would allow base implementations that go against a data store and separate implementations that employ caching and queuing, as well.
 

interface IReadOnlyRepository
{
	object Read();
}

interface IWriteOnlyRepository
{
	void Write(object data);
}

public class DatabaseRepository : IReadOnlyRepository, IWriteOnlyRepository
{
	public object Read()
	{
		//Logic to read data from the database 
		return new object();
	}

	public void Write(object data)
	{
		//Logic to write data into the Database
	}
}

public class XMLRepository : IReadOnlyRepository
{
	public object Read()
	{
		//Logic to read data from the XML 
		return new object();
	}
}
}

So now our code follows the ISP and also our approach is more extensible compared to the previous implementation.



Recommended Articles


Method Overloading and Overloading Dilemma - Part 2
Static Polymorphism C#
Interface Virtual Method in C#
Method Overriding in C#




Thanks for visiting this page. Please follow us on Twitter, Facebook, LinkedIn, Telegram, Youtube, and Quora for regular updates.






External Reference Links


Principles of OOD

GRASP Principles

SOLID Principles

Single Responsibility Principle


No comments:

Post a Comment

Please do not enter any HTML. JavaScript or spam link in the comment box.