Click here to Skip to main content
15,879,474 members
Articles / Desktop Programming / WPF

Object Composition Over Inheritance

Rate me:
Please Sign up or sign in to vote.
4.75/5 (5 votes)
2 May 2011CPOL4 min read 28.2K   287   15   4
This article explains the use of Composition in WPF applications, but it can very well be used in others as well.

Introduction

From the early days of object oriented programming, there is a practice of using (rather abusing) inheritance. Many developers are comfortable defining abstract class with common code implemented as virtual in base class. The major reason behind having this notion is to use override feature to modify behavior if required and to support code reusability. But by doing so, they make the code fragile over a period as the base class starts to have more and more virtual methods which may not be required by all its derived classes. In this article, we will first see what we mean by having composition in class designing. We will see how composition avoids the chronic ‘object pollution issue’, a byproduct of incorrect inheritance. This article explains the use of Composition in WPF applications, but it can very well be used in others as well.

Problem

Let’s try to create a system having different types of users (Manager, Coder, and Leader). All users should have printer related operation access. System should support features as: Print, Fax, Scan, Email.

Mapping between users and printer functionalities should be as follows:

  • Manager: Print, Fax, Scan, Email
  • Leader: Print, Scan
  • Coder: Print

Composition Solution

Let’s try to solve this problem following composition. From the above problem definition, we can imagine some software entities and interfaces that could be used in the implementation.

  • Interfaces: IPrinter, IEmployee
  • Classes: SuperPrinter, AvergePrinter, BasicPrinterManagerCoder, Leader

All the above mentioned inferences are plain representations of actors and actions defined in functional specifications. Nowhere in functional specification will you find reference of printer as a plug-in for user operations. But if you carefully go through the spec, you can imagine interface ‘IPrinterEnabled’ which would expose Printer interface as property allowing the user to plug concrete printer object at construction time.

This kind of plug and play allows the system to stay flexible for future changes as the user may reorder relationship between user and printer. (E.g. Allowing Leader to use SuperPrinter)
Please refer to the below class diagram explaining the same:

Image 1

You can also refer to the attached WPF example depicting an implementation of it.

Inheritance Solution

I want to explain how we could have gone with the inheritance approach to solve the above problem. Note that the application will behave exactly the same for the end user, oblivious to the rigidity that the system develops for change. I don’t want to get into descriptions of the implementation, you can check the class diagram and the attached code for understanding.

Image 2

Referring to the above diagram and code, you will find that concrete user classes have been polluted by additional knowledge of printer features. Though they may internally use printer object to divert calls to appropriate execution, it makes compulsion on the developer to either come with a base class to have these printer signatures implemented and make them virtual so that can be overridden by derived classes or implement interface on all concrete classes. Developers generally go for base class approach thinking that if ‘IPrinterCommand’ interface changes over time, they would just be required to create the appropriate virtual method in the base class. This is an insane mistake smelling the rottenness of design, as it requires modifying existing (& working) base class source code and updating all derived classes depending on the specific changes.

Conclusion

As you have seen, both the approaches have a few common classes, but subtle variations in the way user classes are using printer functionality. In the inheritance approach, the printer functionality is inherited into derived user object showing tight coupling between users and print functionality. Whereas in Composition, user classes are made printer enabled by allowing them to be inherited from ‘IPrinterEnabled’ interface, giving the developer the advantage of assigning printer functionality as a plug-in to user objects. And we can very well say that user objects in composition approach are not polluted by printing functionality.

Note: I have used the above example as a random scenario. This may not be a practical scenario. Given the fact that all developers are used to hearing crazy requirements, this example won’t drive you crazy.

History

  • 1st May, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionnice Pin
BillW3313-Dec-11 3:22
professionalBillW3313-Dec-11 3:22 
GeneralMy vote of 5 Pin
Mico Perez9-May-11 15:34
Mico Perez9-May-11 15:34 
GeneralDuplicate Article Pin
AspDotNetDev2-May-11 9:59
protectorAspDotNetDev2-May-11 9:59 
GeneralRe: Duplicate Article Pin
User-Rock2-May-11 16:15
User-Rock2-May-11 16:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.