CSC/ECE 517 Fall 2009/wiki3 13 ncs: Difference between revisions
m (→Code example) |
|||
(14 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= Introduction = | = Introduction = | ||
Bertrand Meyer's principle of explicit interface states that when 2 modules A and B communicate, this must be obvious from the text of A or B or both. | [http://en.wikipedia.org/wiki/Bertrand_Meyer Bertrand Meyer]'s principle of explicit [http://en.wikipedia.org/wiki/Interface_(computer_science) interface] states that when 2 modules A and B communicate, this must be obvious from the text of A or B or both. | ||
In this article we will consider the Pro's and cons of this approach. When it does and does not make sense to follow this principle. | In this article we will consider the Pro's and cons of this approach. When it does and does not make sense to follow this principle. | ||
= Interface (Implicit vs Explicit)= | = Interface (Implicit vs Explicit)= | ||
A generic definition of an interface in programming context can be defined as a set of methods exposed that can be invoked by other objects. | A generic definition of an interface in programming context can be defined as a set of methods exposed that can be invoked by other objects. For most object oriented languages all protected and public methods of the Object will constitute to be the Object's interface. | ||
Most object oriented languages provide a means to specify a specific behavior that the objects can implement. | |||
For example If we wish to implement the behavior of automobile we could let each class that is an automobile have all the methods implemented without using an explicit interface or have a formal explicit interface defined that defines the automobile behavior and have each automobile object implement the well defined Automobile interface. | |||
each class that is an automobile have all the methods implemented without using an explicit interface or have a formal explicit interface defined that defines the automobile behavior | |||
and have each automobile object implement the well defined Automobile interface. | |||
== Code example == | == Code example == | ||
Line 20: | Line 16: | ||
Let us consider the Automobile class. We can either define all the shared methods and behaviors implicitly as methods within the class | Let us consider the Automobile class. We can either define all the shared methods and behaviors implicitly as methods within the class | ||
< | <code> | ||
class Automobile { | class Automobile { | ||
public String getMake() {} | public String getMake() {} | ||
public String getModel() {} | public String getModel() {} | ||
public String getYear() {} | public String getYear() {} | ||
public String getLicensePlate() {} | public String getLicensePlate() {} | ||
public String getLicenseExpiration() {} | public String getLicenseExpiration() {} | ||
public void turn() {} | public void turn() {} | ||
public void accelerate() {} | public void accelerate() {} | ||
public void stop() {} | public void stop() {} | ||
public String getSpeed() {} | public String getSpeed() {} | ||
public String getRPM() {} | public String getRPM() {} | ||
public String getFuelLevel() {} | public String getFuelLevel() {} | ||
} | } | ||
</code> | |||
Alternatively define behaviors explicitly and have the car and truck class implement them. | |||
<code> | |||
interface Autospec{ | interface Autospec{ | ||
public String getMake(); | public String getMake(); | ||
public String getModel(); | public String getModel(); | ||
public String getYear(); | public String getYear(); | ||
public String getLicensePlate(); | public String getLicensePlate(); | ||
public String getLicenseExpiration(); | public String getLicenseExpiration(); | ||
Line 54: | Line 63: | ||
interface OperateAuto { | interface OperateAuto { | ||
public void turn(); | public void turn(); | ||
public void accelerate(); | public void accelerate(); | ||
public void stop(); | public void stop(); | ||
} | } | ||
interface AutoDashboard{ | interface AutoDashboard{ | ||
public String getSpeed(); | public String getSpeed(); | ||
public String getRPM(); | public String getRPM(); | ||
public String getFuelLevel(); | public String getFuelLevel(); | ||
} | } | ||
class Automobile implements Autospec, OperateAuto, AutoDashboard{ | class Automobile implements Autospec, OperateAuto, AutoDashboard{ | ||
// AutoSpec | // AutoSpec | ||
public String getMake(){...} | public String getMake(){...} | ||
public String getModel(){...} | public String getModel(){...} | ||
public String getYear(){...} | public String getYear(){...} | ||
public String getOwner() {...} | public String getOwner() {...} | ||
public String getLicensePlate(){...} | public String getLicensePlate(){...} | ||
public String getLicenseExpiration(){...} | public String getLicenseExpiration(){...} | ||
// OperateAuto | // OperateAuto | ||
public void turn(){...} | public void turn(){...} | ||
public void accelerate(){...} | public void accelerate(){...} | ||
public void stop(){...} | public void stop(){...} | ||
// AutoDash | // AutoDash | ||
public String getSpeed(){...} | public String getSpeed(){...} | ||
public String getRPM(){...} | public String getRPM(){...} | ||
public String getFuelLevel(){...} | public String getFuelLevel(){...} | ||
} | } | ||
</ | |||
</code> | |||
= Advantages of using explicit interface = | = Advantages of using explicit interface = | ||
Line 90: | Line 122: | ||
== Understandability == | == Understandability == | ||
The behaviors are well understood and helps us understand the functionality as a set of smaller related operations. By documenting the behaviors it is easier to understand each set and | The behaviors are well understood and helps us understand the functionality as a set of smaller related operations. By documenting the behaviors it is easier to understand each set and the behavior individually and it is clear by looking at the Auto class that it implements these behavior. The interface exposed by the auto class can be easily understood. | ||
the behavior individually and it is clear by looking at the Auto class that it implements these behavior. The interface exposed by the auto class can be easily understood. | |||
== Continuity == | == Continuity == | ||
It is very easy to find the elements that a potential change can effect. In our example above if we have explicit interfaces to determine the impact of change in any of the interface | It is very easy to find the elements that a potential change can effect. In our example above if we have explicit interfaces to determine the impact of change in any of the interface methods or modifying an interface itself can be easily determined by the determining the sets of elements that either implement the interface or invoke it. | ||
== [http://en.wikipedia.org/wiki/Composability Composability and Decomposability]== | |||
Using simple interfaces to define behaviors helps us break the program down to smaller pieces that are easier to understand and manage. This also allows us to share this behavior across different classes there by increasing code reuseability. And since these behaviors are well understood it is easy to understand the behavior of objects that implement these behaviors. | |||
== Composability and Decomposability == | |||
It is easy to determine the impact if we have the need to decompose a module further. For example if we feel the need to split the specification interface into two one that deals with the specifications and the other that deals with DMV then any and all outside dependencies are clearly visible. We simply need to look at elements that use the Autospec interface only. | |||
=Disadvantages of using explicit interfaces = | =Disadvantages of using explicit interfaces = | ||
== Not really any == | == Not really any == | ||
The only case it might not make sense | The only case it might not make sense probably a specialized object with a specialized behavior that doesn't really make sense to be defined as an interface. For example | ||
<code> | |||
class LocalGreeter { | |||
public void greet () { | |||
System.out.println (Localizer.getLocalized("hello"); | |||
} | |||
} | |||
</code> | |||
We could define a greeter interface but then we don't see any reuse for it. | |||
= Conclusion = | = Conclusion = | ||
Bertrand Meyer's principle | Bertrand Meyer's principle of explicit interfaces helps us in the following ways | ||
* Decomposability - helps us make easier subprograms | |||
* Composability - helps reuse of code | |||
* Understandability - makes it easier and helps us better understand the programs | |||
* Continuity - improves coupling | |||
= References = | |||
* [http://www.eoinwoods.info/doc/spa2009_patterns_session.pdf Design Principles Mining Pattern DNA] | |||
* [http://se.ethz.ch/~meyer/publications/acm/eiffel_sigplan.pdf PROGRAMMING FOR REUSABILITY AND EXTENDIBILITY] | |||
* [http://www.uta.edu/cse/levine/fall99/cse5324/senotes3.pdf Software Engineering Analysis, Design, Creation] |
Latest revision as of 01:53, 18 November 2009
Introduction
Bertrand Meyer's principle of explicit interface states that when 2 modules A and B communicate, this must be obvious from the text of A or B or both.
In this article we will consider the Pro's and cons of this approach. When it does and does not make sense to follow this principle.
Interface (Implicit vs Explicit)
A generic definition of an interface in programming context can be defined as a set of methods exposed that can be invoked by other objects. For most object oriented languages all protected and public methods of the Object will constitute to be the Object's interface.
Most object oriented languages provide a means to specify a specific behavior that the objects can implement.
For example If we wish to implement the behavior of automobile we could let each class that is an automobile have all the methods implemented without using an explicit interface or have a formal explicit interface defined that defines the automobile behavior and have each automobile object implement the well defined Automobile interface.
Code example
Let us consider the Automobile class. We can either define all the shared methods and behaviors implicitly as methods within the class
class Automobile {
public String getMake() {}
public String getModel() {}
public String getYear() {}
public String getLicensePlate() {}
public String getLicenseExpiration() {}
public void turn() {}
public void accelerate() {}
public void stop() {}
public String getSpeed() {}
public String getRPM() {}
public String getFuelLevel() {}
}
Alternatively define behaviors explicitly and have the car and truck class implement them.
interface Autospec{
public String getMake();
public String getModel();
public String getYear();
public String getLicensePlate();
public String getLicenseExpiration();
}
interface OperateAuto {
public void turn();
public void accelerate();
public void stop();
}
interface AutoDashboard{
public String getSpeed();
public String getRPM();
public String getFuelLevel();
}
class Automobile implements Autospec, OperateAuto, AutoDashboard{
// AutoSpec
public String getMake(){...}
public String getModel(){...}
public String getYear(){...}
public String getOwner() {...}
public String getLicensePlate(){...}
public String getLicenseExpiration(){...}
// OperateAuto
public void turn(){...}
public void accelerate(){...}
public void stop(){...}
// AutoDash
public String getSpeed(){...}
public String getRPM(){...}
public String getFuelLevel(){...}
}
Advantages of using explicit interface
Let us consider the advantages of having explicit interfaces
Understandability
The behaviors are well understood and helps us understand the functionality as a set of smaller related operations. By documenting the behaviors it is easier to understand each set and the behavior individually and it is clear by looking at the Auto class that it implements these behavior. The interface exposed by the auto class can be easily understood.
Continuity
It is very easy to find the elements that a potential change can effect. In our example above if we have explicit interfaces to determine the impact of change in any of the interface methods or modifying an interface itself can be easily determined by the determining the sets of elements that either implement the interface or invoke it.
Composability and Decomposability
Using simple interfaces to define behaviors helps us break the program down to smaller pieces that are easier to understand and manage. This also allows us to share this behavior across different classes there by increasing code reuseability. And since these behaviors are well understood it is easy to understand the behavior of objects that implement these behaviors.
It is easy to determine the impact if we have the need to decompose a module further. For example if we feel the need to split the specification interface into two one that deals with the specifications and the other that deals with DMV then any and all outside dependencies are clearly visible. We simply need to look at elements that use the Autospec interface only.
Disadvantages of using explicit interfaces
Not really any
The only case it might not make sense probably a specialized object with a specialized behavior that doesn't really make sense to be defined as an interface. For example
class LocalGreeter {
public void greet () {
System.out.println (Localizer.getLocalized("hello");
}
}
We could define a greeter interface but then we don't see any reuse for it.
Conclusion
Bertrand Meyer's principle of explicit interfaces helps us in the following ways
- Decomposability - helps us make easier subprograms
- Composability - helps reuse of code
- Understandability - makes it easier and helps us better understand the programs
- Continuity - improves coupling