ironments -- unless you base it on an application framework that already embodies the basic solution.
Frameworks
are skeletons that define the basic design of an application. They provide well-bred code fragments as the foundation of the application. But frameworks are much more than mere class libraries. They consist of large sets of code components and include the glue that lets these classes cooperate. In other words, frameworks are sets of abstract classes with predefined interfaces and problem-adopted event handling.
The first frameworks were developed to support GUI applications, including Apple's MacApp and Next's NextStep in the 1980s. One of the better-known framework projects was Taligent's CommonPoint, which Apple and IBM suspended last year (although some of the results of the research may be used in IBM's VisualAge development environment). Some experts also refer to the Microsoft Foundation Classes (MFC) as a framework, although there's no general consensus on this point of view.
"Frameworks are sets of cooperating classes that define the architecture
to solve a particular problem," says Erich Gamma of IFA (Zurich), co-developer of ET++, a popular framework for user-interface design. "This means that a framework defines how to decompose a problem into objects." For example, MFC and ET++ both not only contain user-interface elements but also define the complete logic and default behavior of a graphics application.
Using frameworks offers several benefits over traditional ways of developing software. "The degree of reuse in working with frameworks is significantly higher," notes Walter Bischofsberger of UBILab, the Union Bank of Switzerland's software-research laboratory. "In frameworks, code reuse is based on design reuse."
Frameworks are not just sets of reusable classes; they contain a reusable system design. Design reuse is most important, because a program's design is often more difficult and expensive to come up with than its detailed coding. "Frameworks avoid reinventing the wheel and thus provide a solid ground of tested code," says Cuno
Pfister, managing director of Oberon Microsystems (Zurich).
Frameworks Save Money
A framework saves money by isolating a developer from the nitty-gritty details of an OS, event handling, and interprocess communications (IPC). And it's much easier to understand the logic of an application constructed with frameworks than it is to understand one with a proprietary design.
Moreover, with plain software libraries it's often costly to retrieve, evaluate, and adapt the appropriate routines. Because frameworks separate the generic and specific aspects of a problem and include dynamic behavior and functional control, once developers break up the problem according to the framework, they can produce code more quickly.
Despite all the above advantages, designing a framework is a difficult and often expensive endeavor. A framework typically has no complete specification unless it's eventually included in a commercial product. Developers of frameworks usually start with a concrete prob
lem and gradually move toward a more general and abstract design that may also fit the needs of other problems.
The flexibility to solve a set of related problems is one of the strengths of frameworks. However, this flexibility can tempt framework developers to lose focus. "Part of the reason why Taligent's CommonPoint didn't succeed is that it went too far with flexibility," says Erich Gamma, who worked for Taligent before joining IFA. "From the client's perspective, very flexible and powerful frameworks are often hard to understand."
Frameworks and OOP
All frameworks are implemented in object-oriented programming (OOP) languages and strongly rely on inheritance, polymorphism, and encapsulation. Their basic parts are not simply objects (i.e., abstract classes) but rather sets of cooperating objects. These cooperating, abstract classes, also called
components
, contain the generic parts of a problem's solution. Their interfaces implement the specific details.
Frame
works strongly support the idea of componentware and software extensibility at a coarser level of granularity than object classes do. This is because they provide a means to define design and interoperation rules for components. Says Oberon Microsystems' Pfister: "Frameworks bridge the gap between integration and isolation of components. They provide the resources to specify and control their mutual interaction." Oberon Microsystems developed Oberon/F, a platform-independent component framework that supports both of its competing component-integration standards, Microsoft's OLE and IBM/Apple's OpenDoc.
Typically, frameworks export abstract classes that are not fully functional but define a design blueprint for future implementations. However, inheritance presents some dangers to this abstract approach. As the experts say, inheritance breaks encapsulation.
In most OOP systems, derived types inherit all the procedures and methods of their base type but can override them and define new implementation
s. (An object's
type
is its externally visible interface.) This powerful feature allows the object's type to replace or modify inherited behavior. But overriding can lead to a situation where the behavior of a base type (i.e., the type of the base's class) cannot be modified without breaking some of its extension types (i.e., the types of its subclasses). (See "Extensible Software Systems," May 1994 BYTE.)
Documentation
This
semantic fragile base-class problem
can become especially critical in frameworks where users can extend the implementation hierarchy and derive new subclasses. Because of the internal interactions that are implemented as default behavior, the effect of overriding a method can become difficult to predict. Only an in-depth understanding of the implementation hierarchy of a framework can avoid this problem. As a consequence, only the source code of the framework can serve as sufficient documentation. Frameworks that heavily rely on inheritance, and
therefore are published in source form, are called
whitebox frameworks
.
Using source code as documentation means that implementation details that might change in a future release cannot be separated from a framework's basic architecture. Thus, the extension of a base class in a framework update can cause incompatibilities with existing, user-derived subclasses (referred to as the
syntactic fragile base-class problem
).
"Another way to look at inheritance is as the abstraction scheme it implements," says Nicolai Josuttis of Bredex (Braunschweig, Germany), a software consultancy and training company. Inheritance can express the relation of a real-world object and its parts (e.g., a vehicle has wheels; this is referred to as a "has-a relation"), or it can represent a generic term and its concrete versions (e.g., a car is a kind of vehicle; this is referred to as a "is-a-kind-of relation").
In C++, for example, inheritance can be
public
, where all properties and methods
make sense for all subclasses, or
private
, where not all properties of the base class are accessible from the subclass. Public inheritance, or inheritance of interfaces, directly represents the is-a-kind-of relation, whereas private inheritance, or inheritance of implementation, typically represents a has-a relation.
However, "inheritance of implementation is often used covertly in a generic-term relation and thus breaks encapsulation," explains Josuttis. Consequently, in languages that deploy subtyping, such as C++, inheritance means whitebox reuse of properties: Without strict usage rules and a good understanding of source code, it's difficult to keep this process under control.
For frameworks, the way out of the fragile base-class problem is to renounce inheritance.
Blackbox frameworks
, which do not rely on inheritance, are better to maintain and easier to document. Typically, they define more object types with a looser and less explicit coupling of components than whitebox f
rameworks.
"Blackbox reuse, or reuse by instantiation, is easier to apply than whitebox reuse, since developers have to deal only with interfaces of classes and not with their internals," says Philip Ackermann of Perspectix (Zurich), which is a spin-off company of the Multimedia Laboratory at the University of Zurich. Perspectix developed the visual programming
environment PerEdit
for easy reuse of a multimedia application framework's classes. "Our experience showed that programming based on application frameworks can be hard to understand. This led us to the idea of representing reusable objects in a graphical way," Ackermann adds.
PerEdit and the company's other authoring tools sit on top of the MET++ framework, the public-domain multimedia extension of ET++. MET++ like ET++ implemented in C++, allows for the control of 3-D graphics and variable audio, video, and MIDI streams.
To make MET++ classes available in PerEdit, Perspectix developed a wrapping technology that
offers a simpler interface to MET++ classes and allows blackbox reuse. The new interfaces enable the MET++ classes to be combined visually in object-related and temporal layout systems. Both types of visual layout systems are independent from each other and, according to Ackermann, allow for the redundancy-free definition of animation.
Frameworks can be separated into several (but not clear-cut) categories. Application frameworks, component frameworks, vertical and horizontal frameworks, and blackbox and whitebox frameworks are typical classification schemes. Systems that support applications development in certain areas, such as MET++, are known as "vertical," while "horizontal" systems have no limits in the application fields they support. An example of a horizontal framework is Oberon/F. Most horizontal frameworks aim at exporting binary software components (i.e., component frameworks), while vertical systems aim at composing complete applications (i.e., application frameworks).
Reusable
Business Logic
"The power of an application framework is its ability to encapsulate a standard business logic into a set of reusable objects," says Jens Schroeder, information technology director of MPro Consult (Wiesbaden, Germany). Genesis, the company's application framework, specializes in the simulation, optimization, and visualization of industrial processes. It contains a visual programming environment that's based on a multiplatform run-time engine that integrates OLE objects, Open Database Connectivity (ODBC) databases, and TCP/IP update services.
Genesis' object model allows for the composition of nested objects that can contain themselves and includes an implementation of inheritance as a has-a relation. Notes Schroeder: "This kind of horizontal inheritance is useful because it facilitates real-world modeling."
Faba's (Linz, Austria) ComponentWare is a whitebox component framework for business-process optimization. It's based on a dynamic object model that supports bidirect
ional interfaces to Microsoft's COM architecture and OLE Automation scripting language. The package includes modules for work flow, document management, and ISO 9000 quality-management systems running on an enterprise-wide network.
Easy maintenance and system extension at run time are also strengths of Siemens Nixdorf's OT Framework. This system provides a dedicated tailoring tool that lets you link new components on the fly or change the user-interface language of the whole system. It closely integrates with Visual Basic 4.0 and aims at building large-scale, three-tier, client/server applications. For each of its three layers -- user interface, business management, and business data -- it provides reusable Visual Basic classes, including an appropriate default behavior.
More Work to Do
So far, object-oriented programming hasn't created a viable software-component industry. For components to work together better, there have to be standards governing the integration of components
and how components from different sources work together and share resources. OLE 2.0 and OpenDoc both support cooperative resource sharing, although they have been used mostly for the Interapplication Communication (IAC) of monolithic applications.
Frameworks will not eliminate monolithic applications in a day. But they ensure that more granular applications, which are easier to build and maintain, will appear soon.
Where to Find
Faba
Linz, Austria
Phone: +43 732 222561
Fax: +43 732 2225619
E-Mail:
coo@faba.faba.ca.at
Internet:
http://www.faba.co.at/faba/