Dissection of an Application Framework - Black-Box Frameworks
(Page 6 of 7 )
Black-box frameworks consist of concrete and ready-to-use classes and services. Although developers can extend the existing framework components to achieve customization in a black-box framework, they more often adapt the framework by combining a number of components to create the desired result. A black-box framework may contain many common spots, and it employs the composition approach to enable its hot spots. Figure 2-8 illustrates a black-box framework.

Figure 2-8. A black-box framework
Because of the composition approach in a black-box framework, it provides a greater range of flexibility than that of a white-box framework. Developers can pick and choose different components to achieve specific application requirements with infinite possibilities. Unlike white-box frameworks, where a developer often needs to know the detailed implementation of the framework component for adaptation, black-box frameworks consist of components that hide their internal implementation. Adaptation of such components is done through well-defined interfaces, such as certain public methods and properties. Developers need to be familiar with only these public members in order to use the framework.
Compared with white-box frameworks, black-box frameworks are harder to develop. Encapsulating business-domain expertise into components that are generic enough to be used in many application scenarios is not an easy task. Encapsulating too much will lead the domain expertise inside the component becoming less fit in many application scenarios. Encapsulating too little will lead to developers having to work with a large number of components and more complex coordination logic in order to build the application.
The extra flexibility of black-box frameworks doesn’t come for free. When using a black-box framework, developers must implement their own process flow and coordination logic needed to link multiple components together. Because developers now control how and what components need to work together, they are responsible for the extra workload on “wiring” the components together along with the extra flexibility provided by the black-box framework. In contrast, white-box frameworks automatically handle the “wiring” for you in the template methods of their components.
Although developers don’t have to deal with learning the internal implementation of the abstract class as they do with a white-box framework, they do have to be familiar with a greater number of components and their use when using a black-box framework, since the developer now has more “moving” parts to deal with in order to combine them into something they need.
When developing an application framework, there is no requirement that the framework contain either all abstract classes or all concrete classes. In fact, neither pure white-box nor black-box frameworks are practical in the real world. Having a mix of both the inheritance approach and composition approach gives you the freedom to use whatever approach is best for the design of a particular component. By mixing white-box frameworks and black-box frameworks, you effectively create a gray-box framework.
Gray-Box Frameworks Gray-box frameworks take both inheritance and composition approach, is usually made up with combination of abstract classes and concrete classes. The approach of enabling its common spots and hot spots is determined on a component-by-component basis. Figure 2-9 shows a gray-box framework.
| NOTE Because a concrete class that contains virtual methods can either be used directly or inherited by another class that overrides the virtual methods to alter its behavior, it is possible for a gray-box framework to consist of only concrete classes, as long as the approach taken by the classes is a combination of composition and inheritance. |
In the real world, the application frameworks you will be developing will most likely be gray-box frameworks. The decision whether a given components will follow the inheritance approach or composition approach is decided by which approach is best suited for what the component is trying to accomplish and how developers will likely use the component in their business applications.
As we are choosing the inheritance approach, the composition approach, or a mix of the two, we should consistently keep in mind the tradeoffs and implications for performance, maintenance, and usability with each approach.

Figure 2-9. A gray-box framework
From the performance point of view, the composition approach tends to be slower than the inheritance approach, primarily because of the extra components it has to load and access at run time to produce the desired results. As you are gathering the features from multiple components, you may also add a number of extra calls to bridge different components. In the inheritance approach, however, an inherited class often contains most of the required features within itself, hence reducing the number of objects the program needs to create and access to produce the same results and eliminating as well much of the extra code that would be needed to bridge different components if the composition approach were used.
Maintenance is another area in which we see the tradeoffs in both approaches. In the composition approach, developers work with a set of highly decoupled framework components, which makes their application more adaptive to changes, and hence more flexible and extensible. However, after the application is deployed, those who provide postproduction support will have to deal with many more “moving parts,” which leads to extra maintenance effort. For example, a change in a business requirement may result in the modification of framework components. With a composition approach, such requirement changes may potentially affect a series of framework components that participate in a certain business feature, since the business requirement is supported by the collaboration of a number of components. Such changes in multiple components may also multiply the effort in testing and deployment of the application framework. On the other hand, the inheritance approach may be less flexible than the composition approach, but in compensation, it introduces fewer moving parts. When business features are served by a hierarchy of classes, a change in business requirements can often be resolved with changes to far fewer classes on the hierarchical tree. Of course, the real maintenance cost of your application framework depends on the design of the framework as well as the type of business-requirement changes involved. But generally speaking, you have less overhead on maintenance if you have fewer moving parts to deal with.
Usability is yet another area you need to consider in designing the application framework. The framework component that takes on the inheritance approach usually hides the complex coordination logic and process flow inside the parent class or abstract class, so the developer often needs only to implement or override a few methods to achieve the desired result. Hence, inheritance provides very good usability as long as developers aren’t required to learn overwhelming details of the parent class or abstract class they inherit. Usability for the composition approach, on the other hand, depends considerably on how much composition developers have to support to achieve certain results. Having a set of highly decoupled components often requires developers to learn and code their own coordination logic and process flow to wire such components together to produce the desired results. However, if you are willing to sacrifice flexibility and create a few coarse-grained components so that developers need to work with only a small number of components to get what they want, then the framework will become easier to use and developers will be much more productive, since the composition approach significantly reduces the coordination logic developers have to learn and write.
As you approach many framework design decisions, you must keep in mind that there is no silver bullet. There is often a tradeoff between different approaches. It is your job to decide how to balance them and create an application framework that fits your objectives.
This chapter is from Developing Application Frameworks in .NET by Xin Chen (Apress, 2004, ISBN: 1590592883). Check it out at your favorite bookstore today. Buy this book now.
|
Next: Design Patterns >>
More .NET Articles
More By Apress Publishing