CSC/ECE 517 Fall 2012/ch2b 2w22 sk: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 37: Line 37:
* Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance.
* Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance.


'''Why do we need this?'''
'''Why do we need this?'''<br>
Both methods - object composition and inheritance provide a means for code reuse which is one of the fundamental principles of OO programming. With inheritance the subclasses are tightly coupled to the parent classes which reduces the flexibility. Each subclass knows the internal representation of the parent class which break encapsulation. This creates a dependency between the subclass and the superclass which is not a desirable trait. This is why inheritance is generally referred to as '''''white box''''' reuse. In most scenarios you do not want to expose the internal implementation of the super class and that is where composition comes into play.
Both methods - object composition and inheritance provide a means for code reuse which is one of the fundamental principles of OO programming. With inheritance the subclasses are tightly coupled to the parent classes which reduces the flexibility. Each subclass knows the internal representation of the parent class which break encapsulation. This creates a dependency between the subclass and the superclass which is not a desirable trait. This is why inheritance is generally referred to as '''''white box''''' reuse. In most scenarios you do not want to expose the internal implementation of the super class and that is where composition comes into play.


'''Benefits'''
<pre>
Class Location {
  String name;
  ...
}
 
Class Journey {
  Location source, destination;
  double getDistance() {...}
  ...
}
 
Class Flight extends Journey {...}
Class Bus extends Journey {...}
 
</pre>
 
In the above example, instead of having a sub-class for Flight, class Journey can have a new field which is TransportMode which represents different modes of transport such as flight, bus, train etc.
<pre>
Class Location {
  String name;
  ...
}
 
Class TransportMode {
  TransportType type;
  double getCost(double distance) {...}
  ...
}
 
Class Journey {
  Location source, destination;
  TransportMode mode;
  double getDistance() {...}
  double getCost() { mode.getCost( getDistance() ) }
  ...
}
</pre>
 
'''Benefits'''<br>
To favour composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term. In other words, HAS-A can be better than an IS-A relationship.
To favour composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term. In other words, HAS-A can be better than an IS-A relationship.
Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business-domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.
Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business-domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.


'''Drawbacks'''
'''Drawbacks'''<br>
One drawback to using composition in place of inheritance is that all of the methods being provided by the composed classes must be implemented in the derived class, even if they are only forwarding methods. In contrast, inheritance does not require all of a base class's methods to be re-implemented within the derived class. Rather, the derived class need only implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.
One drawback to using composition in place of inheritance is that all of the methods being provided by the composed classes must be implemented in the derived class, even if they are only forwarding methods. In contrast, inheritance does not require all of a base class's methods to be re-implemented within the derived class. Rather, the derived class need only implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.



Revision as of 19:00, 18 November 2012

Requirements

The introduction to the GoF book gives three principles for writing reusable and flexible software.

  • Program to an interface, not an implementation.
  • Favor object composition over class inheritance.
  • Consider what should be variable in your design (originally, Encapsulate the behavior that varies).

Explain these principles, and illustrate them with original examples.

Program to an interface, not an implementation

This principle is really about dependency relationships which have to be carefully managed in a large app - Erich Gamma

In this principle, the word interface is more conceptual and should not be seen from the viewpoint of a language like Java or C# which has a keyword by the same name. Interface relates to the OO principle of capabilities that the object is able to support. So by this definition an object can have many types or interfaces, and objects of different classes can have the same interface or type. In this context, the main idea behind this principle is how to decouple the implementation from the interface so that the code can be extended polymorphically ie., to reduce the implementation dependencies. So this approach gives you flexibility, but it also separates the really valuable part, the design, from the implementation, which allows clients to be decoupled from the implementation.

Dynamic Binding, Polymorphism and Interfaces

The first principle of design patterns is also tied to polymorphism as noted above. Let us look at this part in more detail.

When we type an object, such as,

var myInstance:String;

we tend to think of String as a class type, but in fact it denotes a particular interface. “Any request that matches a signature in the object’s interface may be sent to the object” (GoF 13).

Bumping this up to user created classes, we type to the interface, which is found in the supertype relative to a subtype. That is, a subclasses’ type resides in the parent class. Because all knowledge of an object is known only through its interface, the request does not address the implementation. As a result, objects with different implementations can have the same interface.

Several different objects can have the same interface (primarily based on the superclass) but different implementations, and since the actual operation that is performed is dependent on both the request and receiving object’s name, the actual outcome occurs at run-time. Such an association between the a request and its operation at run-time is known as dynamic binding. The process of dynamic binding lets you substitute objects with identical interfaces at run-time. You probably know this process by another name, polymorphism.

Another way to look at this principle is that one should focus not only on developing one single version of an application, but to design it keeping in mind that one have to maintain and keep the API stable for a sustained period of time.

Just by following this rule, you get two very important benefits as stated in the GOF book:

  1. Clients remain unaware of the specific types of objects they use, as long as the objects adhere to the interface that the clients expect.
  2. Clients remain unaware of the classes that implement these objects. Clients only know about the base/abstract classes or interfaces (C# interface) defining the interface. And this greatly reduces the implementation dependencies.

Favor object composition over class inheritance

Definitions:

  • Object Composition is a way to combine simple objects or data types into more complex ones.
  • Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance.

Why do we need this?
Both methods - object composition and inheritance provide a means for code reuse which is one of the fundamental principles of OO programming. With inheritance the subclasses are tightly coupled to the parent classes which reduces the flexibility. Each subclass knows the internal representation of the parent class which break encapsulation. This creates a dependency between the subclass and the superclass which is not a desirable trait. This is why inheritance is generally referred to as white box reuse. In most scenarios you do not want to expose the internal implementation of the super class and that is where composition comes into play.

Class Location {
  String name;
  ...
}

Class Journey {
  Location source, destination;
  double getDistance() {...}
  ...
}

Class Flight extends Journey {...}
Class Bus extends Journey {...}

In the above example, instead of having a sub-class for Flight, class Journey can have a new field which is TransportMode which represents different modes of transport such as flight, bus, train etc.

Class Location {
  String name;
  ...
}

Class TransportMode {
  TransportType type;
  double getCost(double distance) {...}
  ...
}

Class Journey {
  Location source, destination;
  TransportMode mode;
  double getDistance() {...}
  double getCost() { mode.getCost( getDistance() ) }
  ...
}

Benefits
To favour composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term. In other words, HAS-A can be better than an IS-A relationship. Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business-domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.

Drawbacks
One drawback to using composition in place of inheritance is that all of the methods being provided by the composed classes must be implemented in the derived class, even if they are only forwarding methods. In contrast, inheritance does not require all of a base class's methods to be re-implemented within the derived class. Rather, the derived class need only implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.

Consider what should be variable in your design

REFERENCES

<references/> http://www.fatagnus.com/program-to-an-interface-not-an-implementation/
http://www.artima.com/lejava/articles/designprinciples.html
http://blogs.msdn.com/b/sachin/archive/2008/06/12/program-to-an-interface-not-an-implementation.aspx
http://pragmaticjava.blogspot.com/2008/08/program-to-interface-not-implementation.html
http://www.as3dp.com/2009/02/design-pattern-principles-for-actionscript-30-program-to-an-interface-not-an-implementation/
http://www.amazon.com/gp/product/0596007124?ie=UTF8&tag=fatagnus-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596007124
http://www.amazon.com/gp/product/0201633612?ie=UTF8&tag=fatagnus-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201633612