Frameworks evolve

If you ask three people what frameworks are, chances are you'll get three different answers. While we've been promoting the use of frameworks and the notion of reuse for some time now, we've been spinning in very different directions.

The reality is that we are not much closer to creating reusable application objects, frameworks, or components than we were seven years ago. Much of this is due to our inability to pick and leverage object and component standards, and our willingness to spend more time with "code-and-go" RAD application development and less time on rigorous and reusable design processes.

Frameworks, however, are not lost. As we refine application development technology and standards, we slowly move toward creating reusable frameworks for the enterprise. Success stories are few and far between, but progress is progress.

Let's take a look at where we are today with frameworks, including types of frameworks, and the problems they solve. It is also helpful to look at framework products, and how the Web could be the mechanism that places frameworks back on the radarscope.

What is a framework?

One of the fundamental problems with frameworks is that there are so many definitions. However, there are a few definitions that stand out.

"The Computer Glossary, Sixth Edition" (Alan Freedman, American Management Assn., 1993) defines frameworks as: "in object-oriented programming, a generalized subsystem design for building applications. It consists of abstract classes and their object collaboration as well as concrete classes. While object-oriented programming supports software reuse, frameworks support design reuse."

If you check with "A System of Patterns" (Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, and Michael Stal, Wiley, 1997) you know frameworks as: "a semi-finished software (sub-) system intended to be instantiated. A framework defines the architecture for a family of (sub-) systems and provides the basic building blocks to create them. It also defines the parts of itself that must be adapted to achieve a specific functionality."

While the first definition correctly links frameworks to their object-oriented origins, leveraging such concepts as abstraction and inheritance, today we extend the definition of frameworks to include non-object-oriented approaches to software development. Thus the second definition is more applicable. However, a more generic definition of frameworks would be better. For the purposes of this article let's consider frameworks as: a fully debugged and tested software subsystem that developers may extend or customize to create an application. Short, but simple.

The process of de-coupling frameworks from the object-oriented development model is in reaction to the success many are having using component-enabled and procedural frameworks. While the object-oriented, component-based and procedural approaches take very different views of frameworks, the goal of reuse is systemic throughout, and thus the value is still there. Object frameworks are the focus here because they dominate the number of frameworks in use today.

Why bother?

While the concept of object frameworks is well-known, many development organizations are still confused by the value that frameworks offer. There are many benefits, but there are almost as many notes of caution as well.

The most noticeable benefit is the ability to reuse existing code. The frameworks contain pre-built objects, and these are objects you don't have to write yourself.

Frameworks also provide a standard set of pre-designed, pre-tested, application architectures. Frameworks hide all of the dirty little details from the developer, allowing the developer to remain architecture-independent, concentrating more on the functionality of the application.

Frameworks reduce the amount of time developers spend maintaining a system.

Of course, there are downsides.

First of all, you cannot "RAD" your way to success when using frameworks. Design is an essential part of application development and it allows the application architect to derive the most benefit from the use of a framework. In other words, you have to know how the application and framework fit together.

Second, since we cannot seem to agree on a common language or binary object standard, frameworks are typically bound to a technology. For example, do nt try to use your C++ framework with your PowerBuilder application, or your Delphi framework with Smalltalk. You have to commit to a common set of enabling technologies, and in many organizations that is next to impossible.

Finally, the frameworks themselves must go through a very expensive design, architecture, development, and testing process. Poorly designed frameworks lead to bad applications, no matter how well the application was designed and developed. The cost of quality in building sound frameworks is too high for many organizations.

Framework functionality

Frameworks work by allowing developers and designers to take advantage of pre-built sub-systems, application architecture, and code. Since frameworks largely define the architecture for an application, developers and application architects need to build and leverage only those frameworks that are extensible and flexible.

When using object frameworks, for instance, developers have the option of changing as much of the existing functionality as required to meet the needs of the application. Developers simply inherit what they need from the frameworks, overriding methods that need changing. Interface frameworks provide the best example of this. Developers may want to leverage the custom buttons in a data window while overriding the default fonts in favor of new ones. They may also customize the frameworks by adding their own set of classes -- and frameworks themselves may change, as new revisions are released to take advantage of hardware and software changes.

Object frameworks

Available in a number of varieties, frameworks hide the dirty details from the developer. They provide a standard set of pre-designed, pre-tested, application architectures. With object frameworks, developers can mix and match features from each framework type.

Fig. 1

Source: Ernst & Young LLP's Center for Technology Enablement

Components do not provide the same degree of customization as object-oriented frameworks. For instance, most components do not come with the source code. However, they typically provide mechanisms (or interfaces if you will) to allow developers to change look, feel, and behavior by altering the properties of the component. ActiveX controls are the best example of this. (For more on ActiveX components, See "ActiveX Alternatives," p. 59, this issue.)

Object frameworks also work with other frameworks, allowing developers to mix and match features from each framework. (See Fig. 1.)

For instance, many C++ applications leverage GUI-level frameworks for interface development, database-access frameworks for communicating with databases, and system-level frameworks for interacting with the native operating system. Many of these "combined" frameworks are now bundled with object-oriented development tools.

Typically object frameworks provide access to their services through APIs that are simple abstractions of the framework services. The framework approach to APIs is a bit different than the traditional procedural world because most of the code runs inside of the frameworks. The frameworks call code when a particular state is reached; applications rarely invoke frameworks. However, developers may leverage APIs to access the services of other frameworks.

The critical success factors of building frameworks include the ability to provide a complete framework that supports the features required by the clients and the client applications. For instance, providing concrete derivation for the abstract classes and default member function implementations makes classes easier to understand. Frameworks should be flexible and extensible, allowing clients to add and modify the functionality of the framework. Finally, frameworks should be well-documented and understandable by those who will use them.

Types of frameworks

Object frameworks are a common part of most application development. Although less common, component, service and procedural frameworks are quickly gaining currency. It is helpful to distinguish between the different types of frameworks.

Object frameworks, as discussed above, provide application services through the inheritance mechanisms that most object-oriented languages and tools provide. This means that developers get a copy of the framework source code, and have an opportunity to customize the framework. In addition, developers have the ability (inherited from the set of objects that make up the framework) to make changes to meet the requirements of the application. They make these changes using features of the object-oriented programming language such as encapsulation, polymorphism, inheritance, abstraction, and the like. This results in object frameworks, or white box frameworks, which allow developers to look inside and modify where needed.

Object frameworks are language and tool dependent. While most object frameworks are created using C++, there are object frameworks for PowerBuilder, Delphi, and most Smalltalk tools. Most client/server and intranet-enabled development tools, for example, come bundled with some type of framework providing common interface development and database access services. Object frameworks are made up of both abstract and concrete classes.

Service Frameworks, in contrast to object frameworks, do not provide functionality to applications through inheritance. They provide services. Distributed object frameworks are the best example of service frameworks, since they allow applications to invoke methods encapsulated in a distributed object, and typically do not allow access to these methods through inheritance. Also, one may not get the source code for the distributed objects. Thus, depending on the tool or language, it is difficult, but not impossible, to modify or extend the behavior of distributed objects and service frameworks for an application.

Distributed objects, such as those created around the Object Management Group's Common Object Request Broker Architecture (Corba) and Microsoft's Distributed Component Object Model (DCOM), offer a common approach to creating and deploying distributed objects. While CORBA-compliant distributed objects are sold through a number of third party vendors, DCOM comes with the infrastructure of the Windows operating systems. The idea is to create a set of distributed objects using either technology, then access those objects either locally or remotely from the application that needs a service through a well defined interface. For example, distributed objects are built into service frameworks to provide access to accounting functions, financial trading functions, database access functions, etc. Distributed objects also provide the plumbing for easy access to objects residing on network connected computers.

Distributed objects are one of the best hopes for frameworks because they offer tool and language independent frameworks for applications. C++, PowerBuilder, Delphi, and Smalltalk applications can all access distributed object services. Object frameworks, as you may recall, are tool and language dependent.

Procedural frameworks are a black box way of looking at frameworks. They do not allow developers to extend or modify the base set of services. So, if you cannot find the functionality your application requires in a procedural language you are out of luck. You will have to modify the procedural framework itself to add the functionality, or code the functionality directly into your application without the use of a framework.

Enabling technology which supports procedural frameworks includes TP monitors such as Microsoft Transaction Server (MTS), BEA's Tuxedo, and IBM's CICS. TP monitors typically exist on a remote server, and transaction services are created within the TP monitor environment for use by any number of applications. They provide database access services as well, and thus the concept behind 3-tier client/server computing. Clients invoke the transaction service on the TP monitor which carries out the transaction for the client. (See Fig. 2. ) Access to data can be included in that transaction.

TP monitor

Enabling technology which supports procedural frameworks includes transaction processing (TP) monitors.

Fig. 2

Source: Ernst & Young LLP's Center for Technology Enablement

The worlds of TP monitors and distributed objects could, however, be merging. We now see DCOM and Corba-compliant distributed objects that provide TP monitor services. Tuxedo and MTS are examples of technology moving in that direction now. Procedural frameworks provide heterogeneous services using a Corba-defined interface. This approach will allow the gradual transition to objects from our existing set of legacy systems since "wrappering" the TP monitor services makes the service appear object-like.

Component frameworks are the fastest growing of all the types of frameworks. Driven by the Web and the rise of component-enabling technologies such as ActiveX and JavaBeans, we are just beginning to understand the value of sharing components among applications and we are moving beyond discrete functionality. Components today are able to provide both simple and complex application features, such as reporting subsystems and inventory control systems.

Component-based frameworks differ from traditional object frameworks. Developers reuse objects by embedding them inside an application with application development tools that know how to use a type of component (for example, ActiveX) through a well-defined interface. Developers can modify the look, feel, and behavior of the component by setting the properties of the component using the host tool, or through the process of aggregation.

The component framework and the enabling technology, limit the developer's ability to change the component to the exact needs of the application. The developer does not typically have access to the source code. Components deal with the interface on the client, where application services and procedural frameworks provide base application services on the back end. What is more, component frameworks do not provide the reuse granularity of true object-framework development. Instead, components provide reusable features that eliminate the need to know component implementation details.

Mixing and matching components means that developers can purchase expertise they may not yet possess. For instance, vertical market component vendors from petroleum, financial, and retail industries offer developers specialized functionality that requires little or no custom coding.

In contrast to object frameworks, component frameworks usually contain fewer features and functions than applications, but they provide more services than a simple program function or an object. In many respects, components are "retro," and adhere more to the modular program model of the past than they do to object-oriented development.

Framework categories

Putting the types of frameworks aside for now, there are several categories of frameworks based on the types of features they provide. Any of these frameworks could be object-, service-, procedure-, or component-enabled. They are application service, domain, and support frameworks.

Application service frameworks are frameworks that encapsulate common enterprise application functionality. These frameworks are created to provide horizontal functionality across many client domains.

Most frameworks that ship today are examples of application service frameworks, and most exist as object frameworks linked to a particular programming environment. The best examples of application service frameworks include the GUI interface frameworks that come with C++ development tools such as Borland's Object Windows Library (OWL) and Microsoft's Foundation Classes (MFC). Application frameworks such as Rogue Wave's dBTools.h++ may also provide database connectivity. Portable frameworks are also in this category. Portable frameworks allow developers to write an application using only framework services. By simply changing the layer the application can move from platform to platform. XVT from XVT Software is an example of a portable application services framework.

Domain frameworks encapsulate expertise for certain problem domains and provide vertical functionality for certain areas of the enterprise (for example, accounting, marketing, or logistics). The notion is to build common application architectures into a common framework shared across applications.

Support frameworks offer native system-level services such as network support, device access, or file access. These frameworks are typically platform dependent.

Webfluence and more

While frameworks are in a steady rate of growth, the Web is propelling them in new directions. The Java revolution, for instance, has put frameworks in the spotlight for intranet and Internet developers. Java's ability to leverage the object-oriented model has given tool and framework vendors an opportunity to add much needed power to the Java language. Jet Connect from XDB, for example, is a Java framework that adds database connectivity to Java applets and applications.

While Java is still evolving, it is becoming the one true success story of frameworks. Javasoft and its partner organizations are spending most of their R&D dollars developing new frameworks layers into the JDK (Java Development Kit). Current examples include the Java Database Connectivity (JDBC), Remote Method Invocation (RMI), and the security API. While the interest in Java frameworks is mostly at the application services level we are seeing a movement to domain level Java frameworks, and the use of distributed object-based frameworks with Java applets and applications.

Clearly frameworks provide a higher level of code and design reuse. However, development organizations need to understand that just employing frameworks does not assure success. Organizations only get the value out of frameworks with a considerable amount of planning and knowledge transfer. All development projects need to share a common set of design infrastructures, and there must be a portion of the organization responsible for maintaining the frameworks' intra- and inter-applications. The use of design patterns is helpful, as is the use of a consistent enterprise architecture. Frameworks are not cheap, but they can save millions in the long run.

Frameworks are evolving in different directions, and with the advent of new enabling technology such as components, distributed objects, TP monitors, and Web-bound languages such as Java, we are seeing something that was rather simple becoming very complex. C++ is losing its dominance, and we need to figure out how to finally create frameworks that are language and tool independent. Distributed object and component standards provide part of the solution, but we still have to figure out how to bring them into applications without a lot of pain.