Tuesday, December 10, 2013

Interface Segregation Principle

This Principle states that :

Client must not be forced to use Interfaces that it does not use

Interface Segregation Principle advocates spliting of large interfaces with many methods of varying behaviour into smaller interfaces. These splitted smaller interfaces are also known as 'Role Interfaces'  where the large interface is also known as 'Fat Interface' or 'Polluted Interface'.

What is Achieved

ISP is intented to keep the code easy to read, refactor and manage. This essentially promotes a High Cohesion of the classe responsibilities.

How to find if a given Object Structure Violates ISP

If a class implements an interface but some of the interface methods are not required and hence contain 'NIL' implementation.

This simply means that, If a class implements an interface then all the methods of the inteface MUST and MUST have a behavioural impact on the given class. Each method implemented must certainly define a concrete behaviour for the class. A method must NOT be implemented just for the sake of meeting some 'Structural requirements' of code design. By Structural requirements, I mean, that some methods are just added ( implemented ) to classes because classes need to conform to a particular Type and not because the classes need a particular Behaviour.

So interfaces address two concerns :
  1. Interface defines a Type for the classes. They are used to achieve polymorphism as well  tocontrol the structural design aspects of the Object structure, like loose coupling, etc
  2. Intefaces also define necessary behaviour of the classes.
Use of point#1 together with the neglect of point#2 gives rise to VIOLATION of Interface Segregation Principle.

How to avoid this Violation

Simpy separate the methods of the Interface into more that one smaller interfaces, taking care that each interface does not contain any unsed methods. Classes can implement few of these smaller interfaces and thus ascertain that they do  not have any 'NIL' implementation.

Code Examples

Lets consider a Issue Workflow system. The system allows  creation of Issues ( can be compared to Jira Issue ) . Once created, an Issue can be feed into a Workflow system. This workflow system allows the Issues to move from one stage to another. Each stage of workflow consists of allowing an User  to add some additional Inputs, like file attachments or comments or code reviews. This workflow system also allows the Issue to revert back to a previous stage.

Below is the workflow interface. addInput() and stopProgress() methods depend upon Attributable interface. The Attributable interface represents abstraction for set of atributes that can be added at any given workflow statge.

interface Workflow {
 void startProgress();

 void stopProgress(Attributable attr);

 void addInput(Attributable attr);

 void revert();

 boolean isInProgress();
There are Two concrete classes that Implement the Workflow interface.
Class NormalWorkflow : It is an Implementation of Workflow that supports all the behaviours defined by Workflow interface. This interface, apart from other operation, can also be reverted and hence implements revert() method.

Class DecisiveWorkflow : This class is very similar to the NormalWorkflow in behaviour, but unlike NormalWorkflow class, this class does NOT support revert behaviour. But since DecisiveWorkflow implements Workflow hence it contains a 'NIL' implementation for revert() method.

class DecisiveWorkflow implements Workflow {

 // Other part of Code Omitted

  * This method not supported by this class. NIL Implementation
 public void revert() {
  // Do nothing

class NormalWorkflow implements Workflow {

 // Other part of Code Omitted

  * This method not supported by this class. NIL Implementation
 public void revert() {
  // Logic for Reverting a Workflow stage

Here Workflow Interface is an example of a Polluted Interface. Clearly this Design VIOLATES Interface Segregation Principle as DecisiveWorkflow class is forced to Implement 'revert()' method, though it no usable behaviour for it !!

To make a ISP compliant design, Workflow interface must be split into two interfaces. Since revert() method is not a generalisation of the Differernt kinds of Workflows ( as there can be Workflows that do not need a revert behaviour, like the DecisiveWorkflow class of the above example ) hence revert() method is taken out and made a part of a different Interface.

So after split we get two Role Interfaces, which we can name like RevertableWorkflow and NonRevertableWorkflow

Now the above Design structure is ISP compliant. DecisiveWorkflow class no longer forced to implement revert() method.

Clearly DecisiveWorkflow class is now more readable  and maintainable and adheres to High Cohesion principle.

S          O          L             I           D

No comments:

Post a Comment