Component Programming A Conceptual Overview

Introduction

Consider for a moment why the design and development of computer hardware has made such dramatic improvement over the years, while the practice of programming software has made comparatively little progress. The primary reason stems from the fact that a large portion of hardware design, based on the reuse of previously developed components, leverages pre-existent work many times over. Electronic engineers typically construct a new piece of hardware by selecting pre-built components, based on their functional specifications, and assembling them according to their published interfaces.

This same idea, namely, the reuse of previously developed components, has not influenced the software design process to nearly the same extent. To be sure, various models have been proposed and tried, but until recently software reuse was a practice more promised than delivered.

Structured programming and object-oriented programming are widely recognized as two of the most influential paradigms in the brief history of software development Whether we like it or not, in most situations object-oriented programming has not succeeded in fostering code reuse, except in the most limited way. The trend toward reusable software components tries to address that problem, by defining functional between objects that make sure that a component will reused than would, say, an object class.

A third paradigm is now breaking through into wide-spread use. Known as component programming, this model extends the benefits of object orientation to virtually any language while addressing those deficiencies inherent to a language-based, object-oriented approach.

Component programming builds on object-oriented programming in two important ways.

·  First, the object-oriented ideas of encapsulation, polymorphism and inheritance are refined through a language neutral implementation. Thus, the technical foundation of object orientation is automatically made available to legacy languages in an easily adaptable manner.

·  Second, the engineering benefits of binary interoperability and multiple version coexistence are added. This solves those problems that arise when integrating multiple components from different vendors and allowing those components to be individually upgraded with new implementations as they become available.

component programming is not distributed programming. Distributed programming is greatly facilitated by the component programming solutions to deployment, parameter marshaling and inter-process invocation. These solutions, however, remain useful even when employed on a single machine.

Finally, component software is not about enabling users to build their own applications. Users no more want to build their own applications than they want to build their own cars. They are, however, interested in specifying various qualities and requirements for their applications and determining a component's suitability to task. Description Software components are often described as analogous to machine or electronic components. However, all analogies break down at some point. For instance, the analogy of software parts to machine or electronic parts falls apart when considering the inherent plasticity or reconfigurability of software. Try to imagine a battery that is able to fit itself into any sized socket and automatically deliver the required voltage to a device. Not likely. However, a software component tailoring itself to a particular user's preferences and patterns of work is commonplace.

There are two distinct types of component programming.

The first has to do with constructing applications from pre-existing software parts and the second concerns itself with developing software parts in a manner that facilitates their subsequent reuse in many applications. The former is sometimes referred to as component-based programming, while the latter may be more properly termed component development. One is a consumer, the other a producer, but both centers on the idea of a component.

Component-based development is building software from pre-existing software parts. These software parts provide their services through well-defined interfaces. There are no claims of artificial intelligence, of programs building themselves. This is down-to-earth, real-world current practice. Programmers must still understand what they want to do--what services the available software components provide and how to make them interact. Nevertheless, this is a huge leap forward compared to also understanding, specifying and building each individual piece for each new application.

The development of components is much more involved than simply writing subroutines to be packaged into software libraries. Components expose their services through uniquely named interfaces. Typically, an interface groups together a related set of functions, but there are no hard and fast rules strictly enforced. The interface author retains complete freedom as to the makeup of a given interface. However, once published, the interface specification is immutable -- it is written in stone. Back to Basics Building software from off-the-shelf components has been a highly prized objective for many years. What prevented this goal from being reached until relatively recently? The primary reason was the absence of a widespread agreement as to the actual structure of a software component. Minus a common definition, every developer or development organization faced the task of first devising their own comprehensive component architecture and then persuading potential component suppliers to build software according to these unique specifications. Obviously, this was no more than a slightly disguised form of custom contract programming.

What, then, are the primary characteristics of a component architecture necessary for its widespread adoption? Many approaches have been tried, but generally found incomplete in some aspect or another. However, each approach has had to address the fundamental problem of component programming.

How does one piece of software invoke or access the services of another piece of software? Historically, there have been several different methods employed depending on the inter-relationship of the two pieces of software.

· Call/Parm or Linked Libraries are used when both pieces of software execute within the same application process. · System Calls are used to reach across the boundary between an application process and the operating system. · IPC (Inter-Process Communication) messages are used when the two pieces of software reside within separate application processes on the same system. · RPC (Remote-Process Communication) messages are used when the two pieces of software reside within separate application processes on different systems.

Each method is different, imposing its own set of constraints on its usage and requiring pre-existing knowledge of the software relationships in order to choose appropriately.

Obviously, what we need is a single method for invoking software services. One that is sufficiently general to satisfy both the current and new requirements for connecting separate pieces of software but still efficient enough to be practical in today's systems. The Structure of the Solution Any model that attempts to provide a comprehensive architecture for the development of a component programming methodology must satisfy three primary requirements. It must be language neutral. Almost all applications share a similar structure: they interface with the user, they perform some kind of operation, and they obtain and store data. Each structural area contains requirements that distinguish it into a unique problem domain. For instance, the problems associated with constructing a rich and compelling information exchange with a human user are inherently different from those encountered in building a data management system.

Experience indicates there will never be a single language ideally suited for all software development tasks. The attempts, in the past, to devise a universal programming language proved themselves less than a total success; PL/1, ADA and more recently, Java come to mind.

It can hardly be disputed that the expert use of specialized tools leads to higher quality solutions with greater productivity. Moreover, there is no reason to expect programming languages, the primary software development tool, not to conform to this same pattern of experience. Thus, the evolution of programming languages into increasingly specialized forms targeting dissimilar problem domains, seems inevitable. It must establish a binary standard for component interfaces. The creation of a widespread base of component suppliers requires the ability to ship software components without any disclosure of proprietary information. Therefore, no trace of source code must accompany component distribution. This requires that all services exposed through component interfaces be invoked according to a binary protocol. Experience shows there must be a single, consistent mechanism for invoking services from a piece of software. It should not matter whether the software service resides in the operating system, in another application on the same or different machine, or is part of the same application in which the calling software is executing; the invoking process must be the same. This, in itself, is a great simplification to the overall programming problem. Having all software components invoke services through a common interface mechanism greatly reduces the number of problems that must be addressed when building even moderate sized applications. More time and energy can thus be spent on the problems unique to the particular application -- an obviously good thing. It must allow multiple versions of components to coexist. In a world of components, applications must have the ability to uniquely identify all of the components available for its use. Versioning associates the capabilities of a component with its identity. The ability to innovate and improve software over time requires the installation of new versions without adversely impacting current applications.

Subsequent to the first installation, component software is built and shipped by different providers at different times. The installation of a new component or an improved implementation of an existing component must be made immediately available to all applications on a system without the fear of breaking old code. Further, installing a version upgrade of a component must not disrupt applications dependent on a prior version. All versions must peacefully coexist on the same system.

A Market for Components

Why has it taken so long for a market for software components to emerge? There is a little bit of a chicken and egg dilemma here. To do component-based programming first requires the ready availability of a pool of software components, satisfying the particular specifications for the application under construction. However, the existence of such a pool directly depends on a sufficiently large demand to justify the investment required to create the individual components.

One of the barriers to the emergence of a widespread market is the nature of software reusability. While reusability is a worthy goal for development productivity, it presents a counter-incentive to component development. Software doesn't get tired or worn out and costs next to nothing to reproduce. Thus, to ensure appropriate remuneration much effort is spent devising intricate and proprietary schemes to count component use within a system.

A large portion of application development effort is currently devoted to design and implementation issues. Intellectual resources are consumed by the processes involved in translating humanly understood problems into machine efficient solutions. Many of the most fundamental and challenging infrastructure problems are solved once and for all by a comprehensive component architecture. Thus, the adoption of a component software model enables application developers to focus more on solving domain specific problems and less on re-implementing computer science algorithms.

A viable component software industry enables software suppliers to become specialized in a particular industry allowing them to better understand the needs of that industry. This, in turn, provides the opportunity for a class of application developer to emerge that stresses the ability to assemble, tune and integrate various kinds of software parts into a working whole. Knowledge of component requirements and their interface descriptions becomes of paramount importance.

Increasing specialization is often felt to be a violation of the human spirit. But as a model for technical efficiency, it's hard to beat. The ability of software developers to work within a narrow field of specialization predictably creates better quality solutions at greatly reduced prices. This, in turn, accelerates the penetration of once unaffordable applications into a broader range of consumers.

A thriving component software industry establishes the conditions necessary for an "after-market" of software components to emerge. Applications built from assembled components can then be enhanced by replacing various parts with new and improved versions from the same or different vendor. The ability to incrementally upgrade applications over time naturally increases their useable life-span with a concomitant gain in "return on investment."

Conclusion

The first public suggestions of a component programming model can be traced to the late 1960's. Moreover, there is little doubt that private dreams and mutterings of an industry full of software parts goes back to the dawn of computer languages. The barriers that prevented the realization of a component-based software industry are finally falling before the inescapable advance of technology: the absolute commoditization of computer hardware and the widespread availability of sophisticated system software once affordable to only the wealthiest of corporations.

Component programming is fundamentally based on a well-known model of organization and specialization; a model proven over time to achieve the highest levels of efficiency. Indeed, it represents the best approach so far devised to advance the practice of software development to the next level of competence.