CSC/ECE 517 Fall 2010/chd 6d isb: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(44 intermediate revisions by the same user not shown)
Line 1: Line 1:
= Introduction =
= Introduction =


The Interface Segregation Principle (ISP) focuses on the cohesiveness of interfaces with respect to the clients that use them. ISP is very similar to high cohesion principle of [http://en.wikipedia.org/wiki/GRASP_(object-oriented_design) GRASP]. ISP helps developers to change, refactor and redeploy their code easily. This principle alleviates the disadvantages of "fat" or "polluted" interfaces. [1] ISP is considered as the eye of the [http://en.wikipedia.org/wiki/Solid_(object-oriented_design) SOLID] design principle. Two main ISP guidelines are: Classes should not be forced to depend on methods that they do not use, and the dependency of one class to another one should depend on the smallest possible interface. [3]
The Interface Segregation Principle (ISP) focuses on the [http://en.wikipedia.org/wiki/Cohesion_(computer_science) cohesiveness] of interfaces with respect to the clients that use them. ISP is very similar to [http://en.wikipedia.org/wiki/Cohesion_(computer_science) high cohesion] principle of [http://en.wikipedia.org/wiki/GRASP_(object-oriented_design) GRASP]. ISP helps developers to change, refactor and redeploy their code easily. This principle alleviates the disadvantages of "fat" or "polluted" interfaces. [1] ISP is considered as the eye of the [http://en.wikipedia.org/wiki/Solid_(object-oriented_design) SOLID] design principle. Two main ISP guidelines are: Classes should not be forced to depend on methods that they do not use, and the dependency of one class to another one should depend on the smallest possible interface. [3][5]


= Source Code Control System =


The very first version control system[5] is the Source Code Control System, which was originally written by [http://www.informit.com/authors/bio.aspx?a=AFAC0A13-A141-47D6-B508-04A03D7B4634 Marc J. Rochkind] in 1972 at Bell Labs, NJ. It was designed to help programming projects control changes to source code. SCCS provides facilities for storing, updating and retrieving all versions of modules by version number, and it records: who made software change, when and where it was made as well as the reason of the change. The first two implementations of SCCS were: one for IBM 370 under OS and other one for PDP 11under UNIX. [2][3]


Source Code control System can be categorized under file versioning tools. It only versions individual files. SCCS is an effective method for small projects. One Source file results in one SCCS history file. It is easy to understand format of the history files that allows manual intervention. Also, checksums and forward [http://docstore.mik.ua/orelly/unix/upt/ch20_13.htm deltas] grant file integrity and immediate detection of corruption. It was the major form of source code control especially on UNIX platforms until the release of Revision Control Systems.
= Brief Introduction to Interfaces in OOP =


= Revision Control System=
In Object Oriented languages, an interface separates the implementation and defines the structure.  Apart from that, an interface is very useful when the implementation changes frequently. Interface can be used to define a generic template and then one or more abstract classes to define partial implementations of the interface. Generally, interfaces are used as a group of related methods with empty bodies. Interfaces form a "contract" between the class and the outside world, and this contract is enforced at build time by the compiler. Interfaces are widely used in Object Oriented Languages such as [http://en.wikipedia.org/wiki/Java_(programming_language) Java],[http://en.wikipedia.org/wiki/C_Sharp_(programming_language) C#] and [http://en.wikipedia.org/wiki/C%2B%2B C++]. [4][7]


Revision Control System[7] is the successor to SCCS and written by [http://www.ipd.uni-karlsruhe.de/~tichy/ Walter F. Tichy] (now a faculty of University Karlsruhe, Germany) in 1982 at Purdue University. Just like SCCS, RVS is a file versioning tool. The fundamental storage unit is a revision group. Also it supports branches within a file. Unlike SCCS it supports merges. RCS storage on the mainline uses reserve deltas: The latest revision is stored intact but earlier revisions are stored as deltas from the latest. On branches, revisions are stored as forward deltas. Thus checking out branches is slow. For Example:Main line of code has 100 revisions. Assume that there is branch at revision 10. This branch has 80 revisions. To check out the branch tip, RCS must do the followings:


* Retrieve mainline revision 100
* Retrieve and apply reverse deltas from 99 down to 10
* Retrieve and apply 80 forward deltas on the branch


Additionally, in the early 80s, when RCS was released, there were also competitors such as: IBM CLEAR/CASTER, AT&T SCCS, and CMU Software Development control system.
= Fat Interfaces=


As stated above, ISP is used to overcome the problems introduced by "fat interfaces".  In order to clarify this term, consider the example given below. [6]


=Concurrent Version System=
[[Image:fatinterface.jpg |center| Fat Interface Example]]


CVS was originally created by [http://www.cs.vu.nl/~dick/ Dick Grune] of VU University of Amsterdam between 1984 and 1985 and was open sourced in 1986. However the code that eventually evolved into the widely used CVS was started by Brian Berliner in early 1989. By late 1990, with help from several others, the first edition was up for distribution. [9]
Car, Motorcycle and/or Aircraft classes implement the Abstract Vehicle interface that defines methods : TurnLeft, TurnRight, DriveForwards and DriveBackwards. All these methods are going to be used by the classes which implements this interface. There will not be any problems if Car class implements this interface, since every car turns left, turns right, drives forwards and drive backwards. Assume that Aircraft class also implements Vehicle Interface. Any aircraft can turn left, turn right and drive forwards. On the other hand, no aircraft can drive backwards by itself (without and help of a special helper). Another example: if a Motorcycle class implements the Vehicle abstract interface, it has to use DriveBackwards method, although it cannot drive backwards by itself.
Here, The Abstract Vehicle Interface is an example of a "fat interface". One of the side-effects of fat interfaces is that any class that implements the interface ends up doing too many things and this can clearly violate the [http://en.wikipedia.org/wiki/Single_responsibility_principle Single Responsibility Principle].


CVS , while using RCS underneath, is a lot more powerful tool and can control a complete source code tree. It can be greatly customized with scripting languages like PERL, Korn and bash shells. [10]
==ISP for " Fat Interfaces "==


CVS offers the following significant advantages over RCS:
By breaking interfaces down into smaller chunks, we potentially reduce the responsibilities of a class and thus provide higher cohesion between the methods of a particular interface. This also provides the benefit of making a clear statement to consumers of the interface of what minimum functionality is required to be implemented: everything. There uncertainty of whether a particular method or property needs to be implemented vanishes, reducing the factor of surprise. The Vehicle interface could be decomposed into ForwardMovingVehicle and BackwardMovingVehicle. If there are classes that require both functionalities, they would implement both interfaces. Alternatively, if only one interface were required, for example for Aircraft, then only the ForwardMovingVehicle interface would be implemented, avoiding giving way to empty declarations with NotImplementedException exceptions as their implementation.  
* It can run scripts which log CVS operations or enforce site-specific polices.
If we apply ISP to the above example, new "thin" interfaces would be like below.
* CVS enables developers from different geographical location to function as a single team. Information is stored on a single central server and the client machines have a copy of all the files. The client- server connection must be up to perform CVS operations but need not be up to edit or manipulate the current versions of the files.  
* It can merge changes from non-CVS vendor branches.
* Allows more than one developer to work on the same file at the same time
* CVS servers run on most OS including unix-variants, Windows and OS/2 etc


=Subversion=
[[Image:thininterface.jpg |center| Thin Interface Example]]


In early 2000 work began on Subversion by  Karl Fogel, the author of Open Source Development with CVS (Coriolis, 1999) and his friend Jim Blandy with the backing of [http://www.collab.net CollabNet, Inc]. And by late 2001, it started being deployed. [11]
==Interface Pollution==


Subversion is the next-in-line of  version control system. CVS has a number of problems, primarily caused by its dependency on the RCS file format for versioning files. These and other issues addressed by Subversion include the following [12] [13] [14] [15]:
Interface Pollution term is used interchangeable with Fat Interfaces. Whenever an interface is added to base class, that base class does not need, base class is polluted with that interface. In other words, base class' interface has been polluted. [1]
* In CVS, atomicity is not guaranteed. Subversion ensures atomicity.
* CVS has no way to rename files and save versioning history. In Subversion, the common history of file1 and file2 is conserved. Additionally, Subversion can be used for versioning a lot of different things. Directories and file metadata, as well as renamed or copied files, all have their own versioning.
* In CVS, [http://en.wikipedia.org/wiki/Branch_(software) branching] and [http://en.wikipedia.org/wiki/Trunk_(software) tagging] are expensive operations for big repositories and directory trees, which have a cost proportional to the number of files being branched or tagged. Subversion has made both branching and tagging constant time operations. They are implemented simply by copying the directory being tagged.
* CVS is not binary file friendly. Any change to a binary file results in the replacement of the old file. Subversion uses a different approach to provide efficient binary diffing which means it can store pdfs and other binary files efficiently.
* If we change a file locally using CVS, and we want to know the difference, then the entire file has to be sent to the server. When we change a file using Subversion repository, a copy of the latest repository revision is made locally. The differences are sent in both directions, which mean a lot less use of bandwidth.


=Distributed Revision Control=


The first truly distributed version control system was the BitKeeper, which was developed by [http://en.wikipedia.org/wiki/Linus_Torvalds Linus Torvalds] in December 1999. Distributed revision control (DVCS) is a fairly new concept in revision control. With it's peer-to-peer approach, each peer's copy of the code base is a bona-fide repository. It synchronizes by exchanging patches between peers. It's advantages over centralized revision control include [16][17]:
=ISP in Action=


* By default, only the working copy of the code base exist.
Consider the following example in order to better understand The Interface Segregation Principle. A Security system includes Door objects which has the methods given below. Now, consider a Timer class which is used to sound an alarm when the door has been left open for too long. TimedDoor object communicates Timer class to do so.
* Since, communication with a central server is not required, common operations are much more faster. Peers need to communicate only when pushing or pulling changes with other peers.
* Each working copy exists as a remote backup of the code base.


Open systems are the most recent phenomenon in distributed revision control. They are characterized by their support for independent branches, and heavy reliance on merge operations. It is generally characterized by the following features -
[[Image:Interface1.jpg |left| Door Class]]


* Peers are free to join as and when they wish without going through any elaborate approval process
[[Image:Interface2.png |center| Timer Class]]
* Each working copy works like a branch
* Selective changes can be "cherry-picked", pulling them from specific peers.


One of the first closed source DVCS was the [http://en.wikipedia.org/wiki/Sun_WorkShop_TeamWare Sun WorkShop TeamWare] which was widely used in enterprise settings.[18]


Whenever an object wants to be informed about an timeout, it calls Register function of the Timer class. The problem is how can the TimerClient class communicate with the TimedDoor class? Common solution is inheriting from TimerClient class.


[[Image:CVCSvsDVCS.png |center| Distributed VCS versus Centralized CVS]]
[[Image:Interface3.jpg |center| Inheritance]]


The Door class depends upon TimerClient, but not all types of Door need timing.  Moreover, all the applications that use those derivatives will include TimerClass methods, even though they are not using them (Interface Pollution).


[http://en.wikipedia.org/wiki/Bazaar_(software) Bazaar] is one of the most famous open distributed style tree versioning tool. In addition to Bazaar (Mar,2005), many other distributed version control software are available. They include: [http://en.wikipedia.org/wiki/Darcs Darcs] (Nov, 2004), [http://en.wikipedia.org/wiki/Monotone_(software) Monotone](Apr, 2003), [http://en.wikipedia.org/wiki/Mercurial Mercurial](Apr, 2005), [http://en.wikipedia.org/wiki/Git_(software) Git](Apr, 2005).  
SInce Door and TimerClient represent interfaces for different clients. They should be separated.  


Comparison of version control systems can be found [http://en.wikipedia.org/wiki/Comparison_of_revision_control_software here].
==Separation Through Delegation==


= Summary =
Adapter pattern can be used to solve the problem above. The solution can be implemented by creating an adapter object that derives from TimerClient and delegates to TimedDoor. When the TimedDoor wants to register a timeout request with Timer, it creates a DoorTimerAdapter and registers with Timer class. If Timer sends the Timeout to DoorTimerAdapter, it delegates that message back to the TimedDoor.
 
[[Image:Interface5.jpg |center| Inheritance]]
 
The Interface Segregation Principle has been applied above. By doing so, the coupling of Door clients to Timer has been prevented. Even if Timer is changed, Door objects will not be affected.
 
==Separation Through Multiple Inheritance==
 
If the language developer uses supports [http://en.wikipedia.org/wiki/Multiple_inheritance Multiple Inheritance], the Interface Segregation Principle can be applied through multiple inheritance. TimedDoor can inherit from both Door and TimerClient.
 
[[Image:Multiple.jpg |center|Multiple Inheritance]]


Using VCS has many benefits. For example: if a team conducts the project, there will be harmony among the team members, and no one will write over other people’s code. Moreover, every change (version) will be stored in VCS repository. This will enable team members to see the differences between versions of the same file, and they will know the time of the changes as well as the responsible team member. Furthermore, Development can be spit into different branches, each branch, lets say keeping track of the fixes associated with a software release. Then file versions can be obtained with a branch and can be applied to the same fix to multiple branches. Another benefit is that, VCS repository can be useful to understand how good the project was: How many lines changed from the previous version? Which are the most and least productive days of the week? Which team member made the most contribution? [8]


The Disadvantages of "fat interface" can be alleviated by using Adapter pattern either through Delegation or Multiple inheritance.


= References =
[http://www.objectmentor.com/resources/articles/isp.pdf] The Interface Segregation Principle, Engineering Notebook for C++, 1996.


[http://en.wikipedia.org/wiki/Interface_segregation_principle] Interface Segregation Principle, Retrieved April, 2010.


[http://www.rajivnarula.com/blog/2009/02/14/interface-segregation-principle-isp/] Ravij Narula, 2010.
= Summary =


[http://svnbook.red-bean.com/en/1.5/svn.intro.whatis.html] Collins-Sussman, Ben, Fitpatrick, Brian W. and Pilato, C. Michael, Version Control with Subversion (for Subversion 1.5). O'Reilly Media Inc., California, 2004.
The Interface Segregation Principle is very simple at heart and although it states something that would seem somewhat obvious, it is many times ignored. By abiding to ISP, we can improve the quality of our code by making sure that we not only comply with the exact requirements of an interface by implementing everything defined in the contract, but we also aim for reducing the responsibilities of a class by minimizing an interface, and thus complying with the Single Responsibility Principle.[1][2][3]


[http://www.pushok.com/soft_svn_vscvs.php] SVN vs CVS, 2005. Retrieved September, 2010.
= References =
1 [http://www.objectmentor.com/resources/articles/isp.pdf The Interface Segregation Principle, Engineering Notebook for C++, 1996]


[http://www.linux.ie/articles/subversion/] Neary, David, Subversion Building a better CVS.Linux Magazine, (30), 59-63.
2 [http://en.wikipedia.org/wiki/Interface_segregation_principle Interface Segregation Principle, Retrieved April, 2010]


[http://www.differencebetween.net/technology/difference-between-cvs-and-subversion/] Amitash, Difference between CVS and Subversion. Retrieved September, 2010.
3 [http://www.rajivnarula.com/blog/2009/02/14/interface-segregation-principle-isp/ Interface Segregation Principle, Ravij Narula, 2010.]


[http://en.wikipedia.org/wiki/Apache_Subversion] Apache Subversion, 2010. Retrieved September, 2010.
4 [http://download.oracle.com/javase/tutorial/java/concepts/interface.html What is an Interface? The Java Tutorials by Oracle, 2010]


[http://en.wikipedia.org/wiki/Revision_control] Revision control, 2010. Retrieved September, 2010.
5 [http://www.oodesign.com/interface-segregation-principle.html Interface Segregation Principle, OOPDesign.com, 2009]


[http://en.wikipedia.org/wiki/Distributed_revision_control] Distributed revision control, 2010. Retrieved September, 2010.
6 [http://dotnetcenter.it/articles/10/SOLID-5-simple-principles-Interface-Segregation-Principle-Part-1.html Hariri, H. ,December 18, 2009]


[http://www.infoq.com/articles/dvcs-guide] Auvray S., Distributed Version Control Systems: A Not-So-Quick Guide Through, May 07, 2010
7 [http://martinfowler.com/bliki/RoleInterface.html Role Interface, Fowler Martin]

Latest revision as of 18:41, 16 November 2010

Introduction

The Interface Segregation Principle (ISP) focuses on the cohesiveness of interfaces with respect to the clients that use them. ISP is very similar to high cohesion principle of GRASP. ISP helps developers to change, refactor and redeploy their code easily. This principle alleviates the disadvantages of "fat" or "polluted" interfaces. [1] ISP is considered as the eye of the SOLID design principle. Two main ISP guidelines are: Classes should not be forced to depend on methods that they do not use, and the dependency of one class to another one should depend on the smallest possible interface. [3][5]


Brief Introduction to Interfaces in OOP

In Object Oriented languages, an interface separates the implementation and defines the structure. Apart from that, an interface is very useful when the implementation changes frequently. Interface can be used to define a generic template and then one or more abstract classes to define partial implementations of the interface. Generally, interfaces are used as a group of related methods with empty bodies. Interfaces form a "contract" between the class and the outside world, and this contract is enforced at build time by the compiler. Interfaces are widely used in Object Oriented Languages such as Java,C# and C++. [4][7]


Fat Interfaces

As stated above, ISP is used to overcome the problems introduced by "fat interfaces". In order to clarify this term, consider the example given below. [6]

Fat Interface Example
Fat Interface Example

Car, Motorcycle and/or Aircraft classes implement the Abstract Vehicle interface that defines methods : TurnLeft, TurnRight, DriveForwards and DriveBackwards. All these methods are going to be used by the classes which implements this interface. There will not be any problems if Car class implements this interface, since every car turns left, turns right, drives forwards and drive backwards. Assume that Aircraft class also implements Vehicle Interface. Any aircraft can turn left, turn right and drive forwards. On the other hand, no aircraft can drive backwards by itself (without and help of a special helper). Another example: if a Motorcycle class implements the Vehicle abstract interface, it has to use DriveBackwards method, although it cannot drive backwards by itself. Here, The Abstract Vehicle Interface is an example of a "fat interface". One of the side-effects of fat interfaces is that any class that implements the interface ends up doing too many things and this can clearly violate the Single Responsibility Principle.

ISP for " Fat Interfaces "

By breaking interfaces down into smaller chunks, we potentially reduce the responsibilities of a class and thus provide higher cohesion between the methods of a particular interface. This also provides the benefit of making a clear statement to consumers of the interface of what minimum functionality is required to be implemented: everything. There uncertainty of whether a particular method or property needs to be implemented vanishes, reducing the factor of surprise. The Vehicle interface could be decomposed into ForwardMovingVehicle and BackwardMovingVehicle. If there are classes that require both functionalities, they would implement both interfaces. Alternatively, if only one interface were required, for example for Aircraft, then only the ForwardMovingVehicle interface would be implemented, avoiding giving way to empty declarations with NotImplementedException exceptions as their implementation. If we apply ISP to the above example, new "thin" interfaces would be like below.

Thin Interface Example
Thin Interface Example

Interface Pollution

Interface Pollution term is used interchangeable with Fat Interfaces. Whenever an interface is added to base class, that base class does not need, base class is polluted with that interface. In other words, base class' interface has been polluted. [1]


ISP in Action

Consider the following example in order to better understand The Interface Segregation Principle. A Security system includes Door objects which has the methods given below. Now, consider a Timer class which is used to sound an alarm when the door has been left open for too long. TimedDoor object communicates Timer class to do so.

Door Class
Door Class
Timer Class
Timer Class


Whenever an object wants to be informed about an timeout, it calls Register function of the Timer class. The problem is how can the TimerClient class communicate with the TimedDoor class? Common solution is inheriting from TimerClient class.

Inheritance
Inheritance

The Door class depends upon TimerClient, but not all types of Door need timing. Moreover, all the applications that use those derivatives will include TimerClass methods, even though they are not using them (Interface Pollution).

SInce Door and TimerClient represent interfaces for different clients. They should be separated.

Separation Through Delegation

Adapter pattern can be used to solve the problem above. The solution can be implemented by creating an adapter object that derives from TimerClient and delegates to TimedDoor. When the TimedDoor wants to register a timeout request with Timer, it creates a DoorTimerAdapter and registers with Timer class. If Timer sends the Timeout to DoorTimerAdapter, it delegates that message back to the TimedDoor.

Inheritance
Inheritance

The Interface Segregation Principle has been applied above. By doing so, the coupling of Door clients to Timer has been prevented. Even if Timer is changed, Door objects will not be affected.

Separation Through Multiple Inheritance

If the language developer uses supports Multiple Inheritance, the Interface Segregation Principle can be applied through multiple inheritance. TimedDoor can inherit from both Door and TimerClient.

Multiple Inheritance
Multiple Inheritance


The Disadvantages of "fat interface" can be alleviated by using Adapter pattern either through Delegation or Multiple inheritance.


Summary

The Interface Segregation Principle is very simple at heart and although it states something that would seem somewhat obvious, it is many times ignored. By abiding to ISP, we can improve the quality of our code by making sure that we not only comply with the exact requirements of an interface by implementing everything defined in the contract, but we also aim for reducing the responsibilities of a class by minimizing an interface, and thus complying with the Single Responsibility Principle.[1][2][3]

References

1 The Interface Segregation Principle, Engineering Notebook for C++, 1996

2 Interface Segregation Principle, Retrieved April, 2010

3 Interface Segregation Principle, Ravij Narula, 2010.

4 What is an Interface? The Java Tutorials by Oracle, 2010

5 Interface Segregation Principle, OOPDesign.com, 2009

6 Hariri, H. ,December 18, 2009

7 Role Interface, Fowler Martin