Let's examine the two design approaches with the following scenario. You are tasked to design a schema for a 35mm camera. Here's what a sample camera instance looks like:
Here's how you might design your schema: Suppose that a little while later your requirements expand to require your schema to support cameras with mini-disks to hold the image (i.e., a digital camera) as well as cameras that use 35mm film. One approach is to create a type hierarchy (SLR - single lens reflex - represents the original 35mm film camera): Let's suppose that later your requirements expand further to require you to support cameras with large-format film (3 x 5). Continuing with the hierarchical design methodology we now have: Suppose next you need to support cameras with infrared film, and then ... Over time you may need to support cameras with dozens of different recording-mediums, and the hierarchy will expand accordingly.There are two major disadvantages of this approach:
1. Complexity: suppose that camera derives from optical-device. Consider now what is involved with understanding a SRL:
To understand a SLR you must understand the camera. But to understand the camera you must understand the optical-device (white box reuse). In a long hierarchical chain it can be exceedingly difficult to understand an element because this approach forces you to understand the entire chain.2. Tight Coupling: all the different kinds of cameras are tightly bound together by a common root. If the root should change then everything below it is potentially impacted. This is contrary to the principle of designing systems comprised of loosely coupled components. Thus, this approach leads to brittle, unmodifiable designs.
A better approach is to recognize upfront that requirements typically expand. "Find what varies and encapsulate it." [1] In our scenario it is the requirement for different types of recording-mediums that keeps growing. It should be encapsulated. Create a component for each type of recording-medium. Design the camera so that each recording-medium component may be plugged into the camera:
When a new recording-medium is required you simply encapsulate it, and it is ready to be used in the camera. Contrast this with the hierarchical approach where it was necessary to create a new subclass which gets linked into an ever-increasingly complex type tree.Let's look at the XML Schema representation of the camera:
The film element has been replaced by a reference to an abstract recording-medium element: The 35mm, disk, and 3x5 components are simply declared as standalone elements which may be substituted for the abstract recording-medium element: The advantages of the design-by-composition approach are:1. Simplicity: all of the components are stand-alone. They can be understood and developed independently, in isolation (separation of concerns, black box reuse).
2. Decoupled, changeable parts: this approach focuses on creating a collection of independent, loosely coupled components. This enables robust, modifiable, plug-and-play designs.
Note: the solution shown above is just one way to implement design-by-composition. Let's consider other approaches:
The important point is that an application can process the camera by delegating to each of its subordinate elements.
Design by composition is the preferred approach. It yields simpler, robust, modifiable, plug-and-play designs.
"Favoring element composition over type inheritance helps you keep each element encapsulated and focused on one task. Your type hierarchies will remain small and will be less likely to grow into unmanageable monsters." [2]
Editorial comment: it is my observation after analyzing many XML Schemas that the community is overusing design-by-subclassing approach. The community is heading down the same path that the Object-Oriented (OO) community headed down in its early phases. Just as the OO community eventually recognized that "composition is to be favored" [3], so too must XML Schema designers recognize that composing elements is to be favored.
If you do use subclassing I recommend that you follow these simple rules:
[1] Design Patterns Explained by Shalloway and Trott
[2] Paraphrase from Design Patterns by Gamma et al
[3] Paraphrase from Design Patterns by Gamma et al