CSC/ECE 517 Fall 2009/wiki3 8 ISPPSI: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(48 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''''Interface Segregation Principle vs. Principle of Small Interfaces'''''
'''''Interface Segregation Principle vs. Principle of Small Interfaces'''''
----
__TOC__
 
=Introduction=
=Introduction=
This page tries to review Integrated Development Environments for Ruby such as Aptana,Rubymine and Netbeans. Also the IDEs are compared with respect to certain dimensions such as facilities, ease of use, system requirements, and support for the Ruby way of thinking.
OO languages are inherently modular in structure. The functioning mechanism of the code is via the interaction of each of these modules or blocks (also known as Interfaces) with each other. The design of the modules is driven by the following restrictions imposed on them:
 
1.'''Modular Decomposability''' – A software construction method satisfies Modular Decomposability if it helps in the task of decomposing a software problem into a small number of less complex sub-problems, connected by a simple structure, and independent enough to allow further work to proceed separately on each item.
 
2.'''Modular Composability''' – A software construction method satisfies Modular Composability if it favors the production of software elements which may then be freely combined with each other to produce new systems, possibly in an environment quite different from the one in which they were initially developed.
 
3.'''Modular Understandability''' – A software construction method satisfies Modular Understandability if it helps produce software which a human reader can understand each module without having to know the others, or, at worst, by having to examine only a few of the others.
 
4.'''Modular Continuity''' – A software construction method satisfies Modular Continuity if, in the software architectures that it yields, a small change in the problem specification will trigger a change of just one module, or a small number of modules.
 
5.'''Modular Protection''' – A software construction method satisfies Modular Protection if it yields architectures in which the effect of an abnormal condition occurring at run time in a module will remain confined to that module, or at worst will only propagate to a few neighboring modules.
 
Of these the last two talk about the size and scope of the Interfaces. In this article we will try to cover and explain two principles that give developer a guideline on the size content of an Interface and the redundancy in the methods that one should avoid so that we get a loosely coupled architecture flexible in enough to work with minimal code change.
 
Please refer the sections below.


=Interface Segregation Principle=  
=Interface Segregation Principle=  
    * “Many client specific interfaces are better than one general purpose interface“
The principle states that:
    * “The dependency of one class to another one should depend on the smallest possible interface“
"The Interface Segregation Principle states that clients should not be forced to implement interfaces they don't use."
    * “Make fine grained interfaces that are client specific.“
    * “Clients should not be forced to depend upon interfaces that they don’t use. This principle deals with the disadvantages of fat interfaces. Fat interfaces are not cohesive. In other words the interfaces of classes should be broken into groups of member functions.“
 


=Comparision of Aptana,Netbeans and Rubymine=
The rational for the principle can argued by the following points.


Three IDEs namely Aptana's Radrails, Netbeans and Rubymine are compared in the following sections.
* “Many client specific interfaces are better than one general purpose interface“
==System Requirements==
* “The dependency of one class to another one should depend on the smallest possible interface“
* “Make fine grained interfaces that are client specific.
* “Clients should not be forced to depend upon interfaces that they don’t use. This principle deals with the disadvantages of fat interfaces. Fat interfaces are not cohesive. In other words the interfaces of classes should be broken into groups of member functions.“


This principle results in a large number of interfaces, but that is fine if it makes the code modular and loosely coupled.


     
Here is an example of a real system where the Interface-Segregation Principle is required to make the client usage simple.
==Features for Ruby==


s]'''General'''
Consider a User interface for ATM machine with a UI that allows conducting a
{| class="wikitable" border="1"
|-
!
! Radrails
! Netbeans
! Rubymine
|-
|  Price
|  Free
|  Free
|  $99
|-
|  License Type
|  Open Source
|  Open Source
|  Commercial
|-
|  Available Standalone or as Eclipse Plugin
|  Available
|  Not Available
|  Not Available
|}


'''Editing'''
1) Deposit Transaction,


{| class="wikitable" border="1"
2) Withdrawal Transaction, and
|-
!
! Radrails
! Netbeans
! Rubymine
|-
|  Code completion
|  Available
|  Available
|  Available
|-
|  Syntax Highlighting
|  Available
|  Available
|  Available
|-
|  Code analysis (warnings/errors/hints)
|  Available
|  Available
|  Available
|-
|  spell checking support
|  Available
|  Available
|  Available
|-
|  Type Hierarchy View
|  Available
|  Not Available
|  Available
|-
|  Smart Indent
|  Available
|  Available
|  Available
|}


[http://tnlessone.files.wordpress.com/2007/02/eclipse_rails_environment_snapshot.png snapshot for Aptana Radrails editing features]
3) Transfer Transaction.


[http://tnlessone.files.wordpress.com/2007/02/netbeans_rails_environment_snapshot.png snapshot for Netbeans editing features]
The end goal is to have a seamless user experience for a user with a fast turnaround time. You would definitely separate these 3 interfaces from each other so that one type of transaction does not depend on functions it does not need and in turn cause confusion to the final client.  


[http://www.jetbrains.com/ruby/index.html snapshot for Rubymine features]
When clients are forced to depend upon interfaces that they don’t use, then those clients are subject to changes to those interfaces. This results in an inadvertent coupling between all the clients. Said another way, when a client depends upon a class that contains interfaces that the client does not use, but that other clients do use, then that client will be affected by the changes that those other clients force upon the class. We would like to avoid such couplings where possible, and so we want to separate the interfaces where possible.


'''Refactoring'''
==Clients Should not be forced to use Interface they don't use==


Refactoring is a disciplined technique for improving the structure of existing code without changing the observable behavior. Refactoring improves the design of software. Refactoring makes software easier to understand. Refactoring makes software easier to maintain. Refactoring helps you find bugs. Refactoring helps you program faster.
To explain this consider the following Java Code


{| class="wikitable" border="1"
Consider an Interface shown below
|-
  interface Iworker{
!
        public void work();
! Radrails
        public void eat();
!  Netbeans
  }
!  Rubymine
|-
|  Renaming
|  Available
|  Available
|  Available
|-
|  Extract method
|  Available
|  Available
| Available
|-
|  Extract partial
|  Not Available
|  Not Available
|  Available
|-
|  Inline class
|  Available
|  Not Available
|  Available
|-
|  Inline method
|  Available
|  Not Available
|  Available
|-
|  Safely Delete
|  Not Available
|  Available
|  Available
|}


[http://wiki.netbeans.org/RubyRefactoring  Netbeans refactoring  features]
If we try to implement a class worker using above interface, the worker is allocated some time for working during which <code>work()</code> is used and during lunch break <code>eat()</code> is used. But if we try to implement a robot, then we are forced to use <code>eat()</code> on robot also though it is not using it. We are forcing robot to use <code>eat()</code> which is not being used.


[http://blogs.jetbrains.com/ruby/tag/refactoring/  Rubymine refactoring  features]
So we have to use different type of interface which doesn't force interfaces on clients which are not used. The following code explains it.


interface IWorker extends Feedable, Workable {
}
interface IWorkable {
public void work();
}
interface IFeedable{
public void eat();
}
class Worker implements IWorkable, IFeedable{
public void work() {
// ....working
}
public void eat() {
//.... eating in launch break
}
}
class Robot implements IWorkable{
public void work() {
// ....working
}
}
class SuperWorker implements IWorkable, IFeedable{
public void work() {
//.... working much more
}
public void eat() {
//.... eating in launch break
}
  }
class Manager {
Workable worker;
public void setWorker(Workable w) {
worker=w;
}
public void manage() {
worker.work();
}
}


'''Version Control Integration'''
=Principle of Small Interfaces=
The principle states that:


Netbeans IDE directly supports CVS root types.In Netbeans SVN access is via custom protocol to an SVN server. Netbeans supports Git [http://www.kenai.com kenai.com] subversion ,mercurial,and Git repositories.Even we can specify our external source code. 
  “If two modules communicate, they should exchange as little information as possible”


Rubymine has CVS installed and turned on automatically. Git integration is enabled. It supports SVN repositories too along with perforce( one of the subversions) integration
This principle is driven by the earlier mentioned rules of ''Modular Protection'' and ''Modular Continuity''. If a system communicating with a client by using an Interface, exposes methods to fetch more information than needed, then there is chance of corruption of the common data that is not required by the system. Consider the following example which will illustrate the concept:


Radrails has the feature to install the three things as plugins.
public class EmployeeLookupService {
    public List getEmployeesForNameDOB(String lastName, Date birthDate)
        // implementation …
    }
    public Employee getEmployeeForID(int employeeId) {
        // implementation…
    }
    public void saveEmployee(Employee emp) {
        // implementation…
    }
}


This class helps in looking up an employee of the company. This is a simple example which adheres to the principle of small interfaces. The business requirements are to provide two search methods based on employee ID and Last Name – Date of Birth.


{| class="wikitable" border="1"
==Violation of Modular Continuity==
|-
!
! Radrails
! Netbeans
! Rubymine
|-
|  [http://en.wikipedia.org/wiki/Subversion_(software) SVN]
|  Available
|  Available
|  Available
|-
| [http://en.wikipedia.org/wiki/Git_(software) Git]
|  Available
|  Available
|  Available
|-
| [http://en.wikipedia.org/wiki/Concurrent_Versions_System CVS]
|  Available
|  Available
|  Available
|}


'''Debugging Features'''
Consider the following code snippet which is another implementation of the similar business requirement.


All the Three IDE's supports ruby-debuggers.
public class EmployeeLookupService {
    private Connection dbConnection;
    public Connection getDbConnection() {
        return dbConnection;
    }
    public void setDbConnection(Connection newDBConnection) {
        dbConnection = newDBConnection;
    }
    public List getEmployeesForNameDOB(String lastName, Date birthDate) {
        // implementation …
    }
    public Employee getEmployeeForID(int employeeId) {
        // implementation…
    }
    public void saveEmployee(Employee emp) {
        // implementation…
    }
}


Netbeans supports classic debugger which is slow and ruby debugger, which is fast and only works with native ruby interpreter.
In this above code the <code>dbConnection</code> of the type ''java.sql.connection'' is needed but for the internal usage of the Service. There is no need for the clients to be aware of it, or implement the getter and setter methods. If say one is using [http://java.sun.com/docs/books/tutorial/jdbc/ JDBC], then the connection object makes sense, but if a business decided to use [http://en.wikipedia.org/wiki/Mainframe_computer Mainframes] or any other [http://stackoverflow.com/questions/677253/what-are-alternatives-to-sql-database-storage-for-a-web-site non SQL] databases (like [http://hadoop.apache.org/ Hadoop]), may not need this SQL Connection object at all.  


Radrails also supports classic and ruby debugger. Classic is a pure ruby debugger based on debug.rb script. Classic 1.8.0 and 1.8.2 works on windows. It also offers ability to run a debugger using ruby debug gem as background.
This example is the called as violation of Modular Continuty, as the change in the business requirements has an impact of the client classes whereas if the Service was designed based on Principle of Small Interfaces, redundant communication channels could have been not developed, making the code resuable and more flexible.


Rubymine offers ruby debugging. Rubymine has convenient user interface. It allows smart and flexible breakpoint insertions. It also allows remote debugging features. It has Built in [http://www.jetbrains.com/ruby/features/ruby_debugger.html#Built-in_Expression_Evaluator Expression Evaluator].
==Violation of Modular Protection==


[http://www.jetbrains.com/ruby/features/ruby_debugger.html Debugging using Rubymine]
This violation is caused by giving access to common or more data than required by exposing methods by an interface. Consider the code snippet below.


[http://www.netbeans.org/kb/60/ruby/debugger-screencast.html Debugging using netbeans]
public class EmployeeLookupService {
    private HashMap employeeMap;
    public HashMap getEmployeeMap() {
        return employeeMap;
    }
    public List getEmployeesForNameDOB(String lastName, Date birthDate) {
        // implementation …
    }
    public Employee getEmployeeForID(int employeeId) {
        // implementation…
    }
    public void saveEmployee(Employee emp) {
        // implementation…
    }
}


[http://vimeo.com/channels/radrails#6450292 Debugging using radrail
In this case the method <code>getEmployeeMap</code> will return the entire Hashmap of the employees where as all was required was a search operation based on some criteria. This exposes more data than is required by the clients and will allow them to access it and modify it case of [http://www.javaranch.com/journal/2003/04/immutable.htm mutable objects].


==Features for Ruby on Rails==
This is a violation of the principle of Modular Protection which could have been avoided by blocking the communication channel via the <code>getEmployeeMap</code>, based on the Principle of Small Interfaces.


=Compare and Conclude=
At the outset it seems both the principles deal in recommend in using small interfaces by giving different guidelines. But a finer comparison can be made based on the code in [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2009/wiki3_8_ISPPSI#Violation_of_Modular_Protection section 3.2].


1) Interface Segregation Principle:


=Other Features available in IDE's=
By applying the Interface Segregation Principle, the need for removal of the <code>getEmployeeMap</code> cannot be argued. The method can be used by the clients to make one Database request and save it with the client so that the lookup can be done without any further call (The flip side is though client may not have an updated list of employees, which in any case will not change frequently.).


In addition to Ruby support the IDE's offer support to other scripting languages also. The Features available are listed below in each of the three IDE's under consideration
2) Principle of Small Interfaces:


{| class="wikitable" border="1"
By applying Principle of Small Interfaces, we have already identified that the <code>getEmployeeMap</code> method is not required. If the client needs the list of employees, then there could be as many database calls as required and make its own list of required employees and not have redundant data.
|-
!
! Radrails
! Netbeans
! Rubymine
|-
|  HTML
|  Available
|  Available
|  Available
|-
|  CSS
|  Available
|  Available
|  Available
|-
|  JavaScript
|  Available
|  Available
|  Available
|-
|  JavaScript
|  Available
|  Available
|  Available
|-
|  XML
|  Available
|  Available
|  Available
|-
|  SQL
|  Available
|  Available
|  Not Available
|}


=Conclusion=
=References=
1. [http://www.oodesign.com/interface-segregation-principle.html OODesign.com]


The Three IDE's have been compared for different features. It is very difficult to conclude which IDE is best suited for Ruby. All the three IDE's provide many features in Ruby.
2. [http://www.objectmentor.com/resources/articles/isp.pdf The Interface Segregation Principle on the ObjectMentor.com]
Radrails is available as a plugin for eclipse. Users comfortable working with Eclipse can use this plugin and use Ruby on Eclipse.
Netbeans provide support for other languages like Java, C++, etc along with Ruby. It is best suited if users like to use other languages along with Ruby.
RubyMine is designed only for Ruby. RubyMine provides many Refactoring Tools which are not available in Radrails and Netbeans


=References=
3. [http://davidhayden.com/blog/dave/archive/2005/06/15/1482.aspx David Hayden's blog]
 
4. [http://www2.lib.ncsu.edu/catalog/record/NCSU960289 Object-Oriented Software Construction. by Meyer, Bertrand]


1.[http://www.jetbrains.com/ruby/docs RubyMine Documentation]
4. [http://www.mihswat.com/2008/11/27/good-software-modularity-what-exactly-is-it/ "Good software modularity. What exactly is it?" by Otavio Ferreira]
2.[http://tnlessone.wordpress.com/2007/02/28/ruby-rails-ide-comparison-idea-netbeans-radrails/ Different IDE comparisions ]
3.[http://wiki.netbeans.org/RubyOnRails Netbeans Wiki]
4.[http://www.netbeans.org/ruby Netbeans.org]
5.[http://www.aptana.com/rails Aptana.com]
6.[http://en.wikipedia.org/wiki/RadRails Radrails wiki]
7.[http://www.infoworld.com/d/developer-world/lab-test-climb-aboard-ruby-rails-851?page=0,0 Reviews on different IDE's ]


Information from different IDE's help section is also considered for creating this wiki document.
5. [http://userpages.umbc.edu/~khoo/survey2.html "A Survey of Major Software Design Methodologies"]

Latest revision as of 05:00, 21 November 2009

Interface Segregation Principle vs. Principle of Small Interfaces

Introduction

OO languages are inherently modular in structure. The functioning mechanism of the code is via the interaction of each of these modules or blocks (also known as Interfaces) with each other. The design of the modules is driven by the following restrictions imposed on them:

1.Modular Decomposability – A software construction method satisfies Modular Decomposability if it helps in the task of decomposing a software problem into a small number of less complex sub-problems, connected by a simple structure, and independent enough to allow further work to proceed separately on each item.

2.Modular Composability – A software construction method satisfies Modular Composability if it favors the production of software elements which may then be freely combined with each other to produce new systems, possibly in an environment quite different from the one in which they were initially developed.

3.Modular Understandability – A software construction method satisfies Modular Understandability if it helps produce software which a human reader can understand each module without having to know the others, or, at worst, by having to examine only a few of the others.

4.Modular Continuity – A software construction method satisfies Modular Continuity if, in the software architectures that it yields, a small change in the problem specification will trigger a change of just one module, or a small number of modules.

5.Modular Protection – A software construction method satisfies Modular Protection if it yields architectures in which the effect of an abnormal condition occurring at run time in a module will remain confined to that module, or at worst will only propagate to a few neighboring modules.

Of these the last two talk about the size and scope of the Interfaces. In this article we will try to cover and explain two principles that give developer a guideline on the size content of an Interface and the redundancy in the methods that one should avoid so that we get a loosely coupled architecture flexible in enough to work with minimal code change.

Please refer the sections below.

Interface Segregation Principle

The principle states that:

"The Interface Segregation Principle states that clients should not be forced to implement interfaces they don't use."

The rational for the principle can argued by the following points.

  • “Many client specific interfaces are better than one general purpose interface“
  • “The dependency of one class to another one should depend on the smallest possible interface“
  • “Make fine grained interfaces that are client specific.“
  • “Clients should not be forced to depend upon interfaces that they don’t use. This principle deals with the disadvantages of fat interfaces. Fat interfaces are not cohesive. In other words the interfaces of classes should be broken into groups of member functions.“

This principle results in a large number of interfaces, but that is fine if it makes the code modular and loosely coupled.

Here is an example of a real system where the Interface-Segregation Principle is required to make the client usage simple.

Consider a User interface for ATM machine with a UI that allows conducting a

1) Deposit Transaction,

2) Withdrawal Transaction, and

3) Transfer Transaction.

The end goal is to have a seamless user experience for a user with a fast turnaround time. You would definitely separate these 3 interfaces from each other so that one type of transaction does not depend on functions it does not need and in turn cause confusion to the final client.

When clients are forced to depend upon interfaces that they don’t use, then those clients are subject to changes to those interfaces. This results in an inadvertent coupling between all the clients. Said another way, when a client depends upon a class that contains interfaces that the client does not use, but that other clients do use, then that client will be affected by the changes that those other clients force upon the class. We would like to avoid such couplings where possible, and so we want to separate the interfaces where possible.

Clients Should not be forced to use Interface they don't use

To explain this consider the following Java Code

Consider an Interface shown below

interface Iworker{
       public void work();
       public void eat();
}

If we try to implement a class worker using above interface, the worker is allocated some time for working during which work() is used and during lunch break eat() is used. But if we try to implement a robot, then we are forced to use eat() on robot also though it is not using it. We are forcing robot to use eat() which is not being used.

So we have to use different type of interface which doesn't force interfaces on clients which are not used. The following code explains it.

interface IWorker extends Feedable, Workable {
}
interface IWorkable {
	public void work();
}

interface IFeedable{
	public void eat();
}

class Worker implements IWorkable, IFeedable{
	public void work() {
		// ....working
	}

	public void eat() {
		//.... eating in launch break
	}
}

class Robot implements IWorkable{
	public void work() {
		// ....working
	}
}

class SuperWorker implements IWorkable, IFeedable{
	public void work() {
		//.... working much more
	}

	public void eat() {
		//.... eating in launch break
	}
 }

class Manager {
	Workable worker;

	public void setWorker(Workable w) {
		worker=w;
	}

	public void manage() {
		worker.work();
	}
}

Principle of Small Interfaces

The principle states that:

“If two modules communicate, they should exchange as little information as possible”

This principle is driven by the earlier mentioned rules of Modular Protection and Modular Continuity. If a system communicating with a client by using an Interface, exposes methods to fetch more information than needed, then there is chance of corruption of the common data that is not required by the system. Consider the following example which will illustrate the concept:

public class EmployeeLookupService {
    public List getEmployeesForNameDOB(String lastName, Date birthDate)
        // implementation …
    }
    public Employee getEmployeeForID(int employeeId) {
        // implementation…
    }
    public void saveEmployee(Employee emp) {
        // implementation… 
    }
}

This class helps in looking up an employee of the company. This is a simple example which adheres to the principle of small interfaces. The business requirements are to provide two search methods based on employee ID and Last Name – Date of Birth.

Violation of Modular Continuity

Consider the following code snippet which is another implementation of the similar business requirement.

public class EmployeeLookupService {
    private Connection dbConnection;

   public Connection getDbConnection() {
       return dbConnection;
   }
   public void setDbConnection(Connection newDBConnection) {
       dbConnection = newDBConnection;
   }
    public List getEmployeesForNameDOB(String lastName, Date birthDate) {
        // implementation …
    }
    public Employee getEmployeeForID(int employeeId) {
        // implementation…
    }
    public void saveEmployee(Employee emp) {
        // implementation…
    }
}

In this above code the dbConnection of the type java.sql.connection is needed but for the internal usage of the Service. There is no need for the clients to be aware of it, or implement the getter and setter methods. If say one is using JDBC, then the connection object makes sense, but if a business decided to use Mainframes or any other non SQL databases (like Hadoop), may not need this SQL Connection object at all.

This example is the called as violation of Modular Continuty, as the change in the business requirements has an impact of the client classes whereas if the Service was designed based on Principle of Small Interfaces, redundant communication channels could have been not developed, making the code resuable and more flexible.

Violation of Modular Protection

This violation is caused by giving access to common or more data than required by exposing methods by an interface. Consider the code snippet below.

public class EmployeeLookupService {
   private HashMap employeeMap;

   public HashMap getEmployeeMap() {
       return employeeMap;
   }
   public List getEmployeesForNameDOB(String lastName, Date birthDate) {
       // implementation …
   }

   public Employee getEmployeeForID(int employeeId) {
       // implementation…
   }

   public void saveEmployee(Employee emp) {
       // implementation…
   }
}

In this case the method getEmployeeMap will return the entire Hashmap of the employees where as all was required was a search operation based on some criteria. This exposes more data than is required by the clients and will allow them to access it and modify it case of mutable objects.

This is a violation of the principle of Modular Protection which could have been avoided by blocking the communication channel via the getEmployeeMap, based on the Principle of Small Interfaces.

Compare and Conclude

At the outset it seems both the principles deal in recommend in using small interfaces by giving different guidelines. But a finer comparison can be made based on the code in section 3.2.

1) Interface Segregation Principle:

By applying the Interface Segregation Principle, the need for removal of the getEmployeeMap cannot be argued. The method can be used by the clients to make one Database request and save it with the client so that the lookup can be done without any further call (The flip side is though client may not have an updated list of employees, which in any case will not change frequently.).

2) Principle of Small Interfaces:

By applying Principle of Small Interfaces, we have already identified that the getEmployeeMap method is not required. If the client needs the list of employees, then there could be as many database calls as required and make its own list of required employees and not have redundant data.

References

1. OODesign.com

2. The Interface Segregation Principle on the ObjectMentor.com

3. David Hayden's blog

4. Object-Oriented Software Construction. by Meyer, Bertrand

4. "Good software modularity. What exactly is it?" by Otavio Ferreira

5. "A Survey of Major Software Design Methodologies"