CSC/ECE 517 Fall 2010/ch6 6f ag: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
Line 21: Line 21:
==Implications of the emphasis==
==Implications of the emphasis==
<ol>
<ol>
<li>This principle provides guidelines to write our interfaces. When we write our interfaces we should take care to add only methods that should be there. If we add methods that should not be there the classes implementing the interface will have to implement those methods as well.
<li>This principle provides guidelines to write our interfaces. When we write interfaces we should avoid the temptation to bunch together several different methods in one interface. If we add methods that should not be there the classes implementing the interface will have to implement those methods as well.
</li>
</li>
<li>The interfaces that are designed should not be fat, i.e the interface should not have too many methods which often do not get used together.  
<li>The interfaces that are designed should not be fat, i.e the interface should not have too many methods which often do not get used together.  
Line 33: Line 33:
</li>
</li>
</ol>
</ol>
==Results of following ISP==
==Results of following ISP==
Designing software by adopting ISP will yield many simple interfaces that are more specific in nature which in turn will make the classes more cohesive.
Designing software by adopting ISP will yield many simple interfaces that are more specific in nature which in turn will make the classes more cohesive.

Revision as of 00:07, 18 November 2010

Interface Segregation Principle

Introduction

Design phase is a very important phase in the entire process of [1] object-oriented software development. The need for a good design of software is to accommodate change into the software, a definite attribute of any software. For the benefit of the developers of these software, certain principles are laid out which ensure that the outcome of development phase is an easily manageable software rather than a rigid and fragile software. The principles of object-oriented software development are listed differently in different sources. The most commonly accepted and recognized is the [2]SOLID object oriented principles.

  1. SRP- The Single Responsibility Principle - A class should have one, and only one, reason to change.
  2. OCP- The Open Closed Principle - You should be able to extend a classes behavior, without modifying it.
  3. LSP- The Liskov Substitution Principle - Derived classes must be substitutable for their base classes.
  4. DIP- The Dependency Inversion Principle- Depend on abstractions, not on concretions.
  5. ISP- The Interface Segregation Principle- Make fine grained interfaces that are client specific.

In this chapter we focus on Interface segregation principle (ISP).

Interface Segregation Principle

Interface Segregation Principle emphasizes on

  • MANY CLIENT SPECIFIC INTERFACES ARE BETTER THAN ONE GENERAL PURPOSE INTERFACE
  • CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DON'T USE.

Implications of the emphasis

  1. This principle provides guidelines to write our interfaces. When we write interfaces we should avoid the temptation to bunch together several different methods in one interface. If we add methods that should not be there the classes implementing the interface will have to implement those methods as well.
  2. The interfaces that are designed should not be fat, i.e the interface should not have too many methods which often do not get used together. The idea here is to avoid loading all the methods into a single interface, instead segregate the methods in the interface such that all the methods that contribute towards offering a single type of service (or single type of clients) are grouped under one single interface. Thereby dealing with a bulky interface that might be difficult to manage is avoided.
  3. The interface should be specific. The methods in the interface should be the ones that contribute towards offering only a specific type of service. For example, if there is an interface that offers methods that provide mathematical services to its clients, then the same interface should not contain methods that accomplish totally different types of tasks say, like a database functionality implementation.

    The main reason behind such interfaces being discouraged is that if a class decides to (or has to) implement that interface, then, it has to provide an implementation even for those methods that it doesn’t intend to use. Even though such implementations may be empty methods, it is not convenient and also distorts the readability of the code.

Results of following ISP

Designing software by adopting ISP will yield many simple interfaces that are more specific in nature which in turn will make the classes more cohesive.

How ISP can be implemented in the design

Segregation through Delegation

The object form of the ADAPTER Pattern can be used to delegate the responsibility of implementing the thin interface to the class that is the client of the interface.

Segregation through multiple inheritance

The methods that are to be included into the interfaces are grouped into interfaces such that all the methods in the interface are directed towards accomplishing a certain type of service. When a class has to use the methods in the interface, it has to implement the interface. When the class is required to implement methods from many interfaces, the class will have to inherit multiple light interfaces and also implement the methods in the interfaces.

Example

Consider an example of Course registration system which allows students to enroll in courses, similar to the one we have at NCSU. Let us assume we have a student base class which other specialized student classes inherit from.

A full time student is allowed to register for a class. He can also choose to audit a particular class.

Lets say we have an interface called IEnroll. The IEnroll interface exposes two methods viz. registerClass() which should allow a student to register himself for a class, and auditClass() which allows a student to audit a class he has registered for. The FullStudent class is used to represent full time students. It extends the Student class and implements this IEnroll interface.





interface IEnroll {
   public void registerClass();
   public void auditClass();
}
class FullStudent extends Student implements IEnroll {
   public void registerClass()
   {
       //allow a student to register for a particular class
   }
   public void auditClass()
   {
       //allow a student to audit an enrolled class
   }
}

Now lets suppose, NCSU decided not to allow part time students to audit a class once they have registered. The PartStudent class represents the part time students. It extends the Student class. Now PartStudent class can either implement IEnroll to provide the registration facility. But in that case, PartStudent is forced to implement the auditClass method.





class PartStudent extends Student implements IEnroll {
   public void registerClass()
   {
       //allow a student to register for a particular class
   }
   public void auditClass()
   {
       //do nothing since we didn't want this method in the first place!
   }
}

The other option is to define a new interface with just registClass method and use it in PartStudent class. But this defeats the purpose of having a common interface.

This is a good example of how our interface has become 'Fat' or 'Polluted'. It is exposing 2 different methods which its clients are forced to honor. This violates the ISP.

Lets see how we can correct this.

We separate out the 2 functions into different interfaces now,


interface IRegisterClass {
   public void registerClass();
}
interface IAuditClass {
   public auditClass();
}

This allows the FullStudent and PartStudent to be defined as following:





class FullStudent extends Student implements IRegisterClass, IAuditClass
{	
   public void registerClass()
   {
      //allow a student to register for a particular class
   }
   public void auditClass()
   {
      //allow a student to audit an enrolled class
   }
}







class PartStudent extends Student implements IRegisterClass
{
   public void registerClass()
   {
       //allow a student to register for a particular class
   }
}

This gives a clean and correct way in which the PartStudent class is not forced to depend on an interface it does not want.


Conclusion

  1. Fat Interfaces are the interfaces that are not specific to a single client. Fat interfaces lead to unintended couplings between clients that ought otherwise to be isolated. By making use of the ADAPTER pattern, through multiple inheritance (class form), fat interfaces can be segregated into abstract base classes that resolve the unwanted coupling between clients. Thus maintaining loose coupling and high cohesion, which is an essential attribute of good software design.
  2. Interfaces containing methods that are not specific to a particular type of service are called polluted or fat interfaces. These must be avoided.

See Also

  1. Design principles
  2. Three Sources of a Solid Object-Oriented Design
  3. Principles of OOD
  4. Hanselminutes episode on SOLID

External References

  1. The Interface Segregation Principle
  2. Design Principles and Design Patterns, Robert C Martin
  3. 2009 Gotham Ruby Conference, presentation on SOLID Object Oriented Design by Sandi Metz, Duke University.