Escolar Documentos
Profissional Documentos
Cultura Documentos
vorgelegt von
Angefertigt am
Institut für Informatik
der Universität Zürich
Table of Contents
Chapter 1 Introduction and motivation .................................................................7
1.1 Software crisis ......................................................................................7
Introduction and motivation Chapter 1
Table of Figures
Preface
This work is delivered as a Degree Thesis for the Department of Computer Science University
of Zurich, Switzerland.
Additionally, the concepts like Corba Business Object, COM and Java Bean/Enterprise Java
Bean will be illustrated with the help of simple examples. Besides working with literature, the
state-of-the-art of component-based software engineering/developing will be researched on a
basis of Internet-Recherché.
Chapter 1. In this chapter, the motivations of using software are discussed and the
phenomenon of software crisis is illustrated. Then responses to software crisis, software
component and software reuse are introduced.
Chapter 2. Software reuse is regarded as one of the best ways to reduce the cost of software
production and to improve software quality. Using componentware is actually a kind of
software reuse. The basic forms of software reuse and the different granularities of reuse are
introduced in this chapter.
Chapter 3. The basic concepts, definitions, and standards concerning componentware are
discussed in this chapter. Since componentware means different things for different people,
only the minimal properties are described, which a software component should have. We*
focus on the component model of CORBA Component model, Microsoft’s COM model, and
JavaBean/Enterprise JavaBean model of Sun Microsystems. The differences between a
software component and an object in the sense of object-oriented programming are also
explained.
Chapter 4. In this chapter we discuss the advantages and issues of using software component.
We will do it in different perspectives. On the one hand, we will illustrate how the software
producers benefit by adopting component-based technology; on the other hand, we will
demonstrate how software buyers profit from using componentware. Adopting of a new
technology is not an easy task. We illustrate the possible difficulties and risks of using
componentware in this chapter, too.
Chapter 5. We distinguish in this work two closely related concepts: software component and
component-based software engineering (CBSE). The software components play a similar role
to bricks in building a house: they are raw materials. Conversely, CBSE is actually equivalent
to the process of building a house using pre-existing building materials. We introduce the
CBSE concept and compare it with the traditional software engineering principles and see
how CBSE affects enterprise organizations and our occupations as software producers.
Chapter 7. The work is summarized and we look ahead to the future development of
component-based software technology.
Introduction and motivation Chapter 1
Because programming is such a young discipline, there is a parallel between the stage it has
reached today and the historical development of other crafts. Just like shoe manufacturing
before the industrial revolution, software is produced in a very individual manner. A
shoemaker in medieval times made each pair of shoes unique for each customer, from raw
materials to finished product. One can find many similarities within software development
today. Software is always produced from scratch. And when it is delivered it is often poorly
documented, and much of the knowledge surrounding it is still sitting in the programmers
head – a situation very much like that of the shoemaker craftsman. As results, two major
problems of software development with today’s knowledge are:
d
2% useeredas
l i v
de after
d
use n
23% ificatio
d ut
mo ed b
e r
deli
v ed
% d d e l iver
5 0 se r
er ueve
nr ebvut n
fo
paid
25%
The traditional way of driving program development led to many problems. Those who order
software often find it difficult to explain to programmers what they want. As lead times
become shorter and shorter, documentation and testing suffer. When at last the product is
delivered, sometimes very late, it is often of poor quality. Ultimately, the lack of
documentation means that it is difficult to support old software and that it is virtually
impossible to reuse it in a new project because one is no longer sure of its function.
t
p men
De velo
nce
ena
Maint
tware
Sof
e
Tim
Introduction and motivation Chapter 1
Reuse of software components is becoming more and more important in a variety of aspects
of software engineering. Recognition of the fact that many software systems contain many
similar or even identical components that are developed from scratch over and over again has
led to efforts to reuse existing components. Structuring a system into largely independent
components has several advantages. It is easy to distribute the components among various
engineers to allow parallel development. Maintenance is easier when clean interfaces have
been designed for the components, because changes can be made locally without having
unknown effects on the whole system. And, if components’ interrelations are clearly
documented and kept to a minimum, it becomes easier to exchange components and
incorporate new ones into a system.
Software reuse and software components have a major influence on the structure of software
systems as well as the way we build them. Yet, many questions are still unanswered. What are
software components? What are their properties that support reuse and adaptability? What are
the implications for the software lifecycle? What are the legal, economic and organizational
consequences? In this work we will try to answer these important questions.
Components are artifacts that we clearly identify in our software systems. They have an
interface, encapsulate internal details and are documented separately. Recently, component-
base software development (CBSD) has become a buzzword. In this context it is required that
components be easily combined with each other, especially without knowing from each
other’s existence.
The primary intention in reusing components is that we can take a component and integrate it
into a software system. For example, we can take a procedure and use it for some
computations. We can also reuse an algorithm that is described in a book on algorithms. But
we cannot simply take the algorithm and integrate it into a software system. We have to
implement it first. Thus we reuse the idea that is described in some pseudo-code and tells us
how we can solve the problem. But we have to solve the problem ourselves using a specific
programming language and dealing with the special characteristics of this language. If the
algorithm were given already in a language that we can use in a system, then we would have a
component to reuse. In this context it does not really matter whether we have the component
given in the book only and we have to type it in, or if it is available in digital form already.
Reusing an algorithm suffers from another drawback. The algorithm’s documentation is given
in the book and not available in electronic form. This prohibits its incorporation into the
documentation of the whole system (unless someone undergoes the tedious effort of typing
the information from the book, which might be even prohibited by copyright rules).
A software design is not a software component. We can reuse a design by reusing a set of
components, for example, an application framework. The framework is not one component as
a whole, but consists of many components that can be modified and extended individually.
But the whole group reflects a certain design, which we reuse by integrating all these
components into a system. Design patterns have recently become popular. Are they reusable
components? They certainly can be reused, but they are not software components. We cannot
Introduction and motivation Chapter 1
component and arrange them as described by a design pattern. Or we might reuse a set of
components that realize a certain pattern. Design pattern describe how we can solve certain
problems by arranging components (usually classes) in a certain way. In this sense they are
like algorithms. They describe ideas, i.e., solutions to certain design problems that can be
implemented in a specific way.
This work focuses on component reuse because components are a field that promise a rich
harvest in productivity through reuse. Some people might argue that the reuse of software
design is more effective. Whether this is true depends on what a component is. Reusing
software designs might be more effective if we restrict ourselves to the reuse of source code
components. However, in order to increase productivity, we have to see software components
in a broader perspective. By using a component we may well reuse design. Many things can
be encapsulated in components. All the algorithms described in various books on that topic
can be realized as components. Object-oriented technology provides the possibility to build
generic components that are, for example, capable of sorting whatever we want. There is no
need to implement an algorithm every time we need to sort, and there is also no need to
customize these algorithms to whatever data structures we need to sort. Components have yet
another advantages: they can be documented and maintained. By using a component in
various projects, we benefit from the fact that it has to be maintained only once. Bugs need
not be fixed redundantly; documentation has to be written only once; and we avoid any
inconsistency problems that arise when we have similar code spread over many locations. If
we implement the same algorithm for various software systems, maybe for slightly different
data structures, we also have to invest redundant effort to maintain their code, even though we
successfully reused the algorithm.
Another important aspect of software components is that they must have an interface. Simply
copying some source code lines and pasting them into the system to be built does not satisfy
our conception of software components. There must be some kind of abstraction, and reuse
should be possible without knowing the internals of the component. This is called black-box
reuse. In order to increase software productivity and to ease software maintenance, black-box
reuse should be the goal. Sometimes performance considerations may require to know and
modify the internals of components, but this should be the exception rather than the rule.
Documentation is a necessity for reuse. Today reuse is sometimes still done by grabbing some
pieces of code, studying and trying to understand them and then modifying and integrating
them. The term code scavenging applies to this scenario. The abstraction level of reusable
components has to rise in order to considerably improve productivity. The reuse of plain
source code should be the exception. The more complex the components get, the more
difficult or impossible it becomes to reuse them. We want components that have the proper
information for retrieval and all the descriptions that are necessary for adaptation and
integration. This requires documentation, and we have to develop techniques and tools to
support these efforts.
Reusing software has a much broader influence on software engineering than one might
initially think. Not only does it influence the construction process, it fundamentally affects
organizational structures and project structures, and it influences legal and economic issues of
software engineering. For software reuse to become a matter of fact, software life cycles have
to be adapted accordingly, important new activities like domain analysis come into the scene.
The reuse of legacy code poses new challenges. Maintaining it is hard enough, reusing it and
Introduction and motivation Chapter 1
We have to build evolving systems that are geared for change. This is the only chance to keep
pace with ever changing and increasing requirements on software systems. We have been
struggling with the software crisis for decades. We should get ready to do a better job.
Software systems must be composed of components that can be reused and replaced. Instead
of replacing a whole system every twenty years, we have to continually add, remove and
replace components to adapt a system to changing requirements. After twenty years
everything in the system may be different, but this will have happened gradually with small
changes that are manageable.
Software reuse and software components will not solve all problems we encounter in software
engineering, but they will contribute to an important step towards more flexible software
systems that are constantly evolving and adapting. Reusable, adaptable software components
rather than large, monolithic applications are the key assets of successful software companies.
In rest of this work, we will discuss at first the software reuse in next chapter, then the
software component and its properties. The current popular standards and component models
will be presented. We show then the benefits and issues of using componentware in chapter 4.
Furthermore, we discuss the component-based software development (CBSE) and the way it
changes the traditional software lifecycle in chapter 5. At last, the state of the art of software
component will also be illustrated.
Software reuse Chapter 2
Generally, there are two ways to reduce the software development cost. On the one hand, this
can be achieved per rising the number of sold units, the more the vendors sell their software,
the less is the price of single exemplar; on the other hand, reduction of software development
cost can also be achieved per software reuse [Gli_96]. Many different viewpoints exist of
what software reuse is. In this work, we adopt the Kruger’s general view of software reuse
[Kru_92]:
“Software reuse is the process of creating software systems from existing software rather
than building them from scratch.”
It needs to point out that it is not always possible to simply reuse components. Development
of new components and/or systems is still necessary. We will discuss the software reuse in the
next sectors.
• Black-Box Reuse
Reusing a component as a black box means using it without seeing, knowing or modifying
any of its internals. The component provides an interface that contains all the information
necessary for its utilization. The implementation is hidden and cannot be modified by the
user. Thus reusers get the information about what a component is doing, but they do not have
to worry about how this is achieved. The implementation can be changed without any effects
on users.
Usually a black box is reused as-is. Object-oriented techniques allow modifications of black
boxes by making modifications and extensions to a component without knowing its internals.
This is one of the major contributions of object-oriented programming to software reuse.
However, components have to be designed so that such modifications become viable.
• White-Box Reuse
White-box reuse means reuse of components of which internals are changed for purpose of
reuse. White box are typically not reused as is, but by adaptation. They create more
opportunities for reusers due to the ease of making arbitrary changes. On the negative side of
white box reuse, it requires additional testing and costlier maintenance. Unlike black boxes, a
Software reuse Chapter 2
component and thoroughly tested. Additionally, the new component requires separate
maintenance. If many copies of a component exist with slight modifications, it becomes
burdensome to fix errors that affect all of them. If the changes made to a component are only
minor, e.g., a few variable renaming or changes in procedure calls, the term Grey-box reuse is
also used.
• Glass-Box reuse
The term glass-box reuse is used when components are used as-is like black boxes, but their
internals can be seen from outside. This gives the reuser information about how the
component works without the ability to change it. But this information may be crucial for
understanding how certain tasks are carried out. It may also give the reusers some confidence
from being able to see inside the component and capture how it works. Additionally, getting
internal information provides some kind of knowledge transfer and, for example, can help in
building new components.
Glass box reuse has its negative sides. It may lead to dependencies on certain implementation
details that become fatal when the internals of the component are changed. Unfortunately,
giving reusers detailed information about a component’s internals often serves as
compensation of nonexistent or insufficient documentation.
• Generative Reuse
Generative reuse is itself a reuse technique, but it can be seen as kind of black-box reuse.
Instead of picking of several existing black boxes, a component’s specification is created and
its implementation automatically generated by a program generator. The program generator is
a black box; its internals are of no interest to the reuser. Also, the generated implementation
will not be modified. If changes are necessary, they will be made in the specification and the
implementation is recreated. (In practice, however, modifications to the generated
implementation are sometimes made due to shortcomings in the generator.)
Black box reuse is more difficult to achieve than white box reuse but promises higher quality
and reliability of the reusing software system. The potential of customizing black-box
components can increase their reuse potential but has to be carefully considered and designed.
Black-box components have the advantage of possible verification and certification. Even
though we are far from having a market of verified and certified components, such attributes
will become essential in the future.
The second question relating to reuse is, what can be reused? To answer this question, we
firstly introduce the concept of reuse granularity. Granularity is used to express the different
abstraction degrees of reuse. There are many work products that can be reused, e.g., source
code, documentation, designs, specifications, objects and architectures. Source code is the
most common reuse product, for example. However, higher increases in productivity will
result from reusing higher level of abstractions. This can mean that source code is generated
automatically from higher levels of abstractions. For example, object-oriented programming
techniques allow the construction of application frameworks that facilitate not only source
code reuse but also design reuse. Design patterns have recently emerged and help to reuse the
knowledge of experienced designers.
Without systematic planning, reuse seldom goes beyond the implementation stage and the
source code level. Types of reusable artifacts can comprise data reuse (e.g., standardization of
data formats), architecture reuse (e.g., standardization of design and programming
conventions), design reuse (e.g., for common application like GUI), and programming reuse
(e.g., executable code) [Jon_84]. The most prominent examples of today’s reuse include
algorithms, function libraries, class libraries, application frameworks and design patterns.
Software reuse Chapter 2
Algorithms have a long tradition of successful reuse. Numerous books are published which
contain algorithms and data structures. They allow the reuse of these algorithms with only
minor modifications.
• Function Libraries
Functions are the most common form of reusable components. For many programming
languages, standard libraries have been defined, for example, for input/output or mathematical
functions. There are many examples of function libraries, from collections of standard
routines (e.g. the C standard libraries) to domain-specific libraries (e.g., for statistics or
numerical purposes).
• Class Libraries
Class libraries are the object-oriented version of function libraries. Classes provide better
abstraction mechanisms, better modifiability and adaptability than functions do. Reusability
has greatly benefited from concepts like inheritance, polymorphism and dynamic binding. In
many class libraries there are classes devoted to generic data structures like lists, trees and
queues. The major problem with class libraries is that they consist of families of related
components. Thus members of different families have incompatible interfaces. Often several
families implement the same basic abstraction but have different interfaces. This means
libraries hard to use and make interchanging components difficult. Also, most class libraries
are not scalable.
A software architecture is the global structure of a software system with its major subsystems,
including the specifications of these subsystems and their interrelationships. It includes the
collection of components and interactions. A description of a software system’s architecture
usually contains the collection of its components at the highest level of abstraction. For
example, it the system consists of independent processes, then the description of the
architecture contains these processes with a description of their functionality and the
interactions among them. If a software system runs as a single process, then its subsystems are
considered as being the architecture. These can be modules and classes or subsystems
containing several such modules and/or classes. The next lower level is generally considered
as being part of the software design. The reuse of software architectures is possible through
generic architectures for certain application domains. A high-level generic design for a family
of applications can be defined to meet requirements within the domain.
Software design incorporates the activities of creating the software architecture of a system
plus decomposing software components. This is repeated until the level of detail allows the
coding of the specified components. The steps involved include the design of the architecture
of the whole system or subsystems, component interfaces, component implementations, data
structure and algorithms. Reuse of software design is mainly reuse of knowledge. However,
with application frameworks it is possible to reuse not only source code but also the design.
• Application Frameworks
For large-scale reuse, isolated classes are small-scale primitives that are too fine-grained. To
boost productivity, systems have to be built out of large-scale composites. Thus we have to
focus on sets of classes that collaborate to carry out a common set of responsibilities, rather
than on individual classes. Frameworks are flexible collections of abstract and concrete
classes designed to be extended and refined for reuse. Components of class libraries can serve
as discrete, stand-alone, context-independent parts of a solution to a large range of different
applications, e.g., collection classes. Components of frameworks are not intended to work
alone; their correct operation requires the presence of and collaboration with other members
of the framework components [Tai_93]. Reusers of framework classes “inherit” the overall
Software reuse Chapter 2
application’s functionality. They do not have to worry about user interfaces, window systems,
event handling, etc.
The major advantage of framework classes over library classes is that frameworks are
concerned with conventions of communication between the components. Today the
combination of components from different class libraries is the exception rather than the rule.
This is because there is some implicit understanding of how components work together. High
cohesion and low coupling increase the reusability of components. But unless the component
does have extensive functionality, it is required to cooperate and communicate with many
others. In a framework this interaction is built in and eases interaction of its components.
• Design Patterns
Software design patterns capture the intent behind the design of a software system. They
standardize piecework to larger units. For example, many times there exists a special
arrangement of classes and objects in order to avoid reuse errors.
A subsystem is a set of classes with high cohesion among themselves and low coupling to
classes outside the subsystem. Design patterns can correspond to subsystems, but often they
have a finer level of granularity. Gamma et al. have presented an extensive collection of
design patterns [Gam_95]. These patterns promise to be one further step in increasing the
abstraction level in software development. They can help both in improving the development
process and in recapturing design decision behind of the structure of certain parts in a system.
Design patterns are seen as a means of transferring design knowledge. Thus design patterns
provide an efficient means of reusing the designs of experienced software engineers. Patterns
can help to improve productivity by shortening the learning curve for novice and intermediate
programmers. In contrast to methodologies that tell us how to do something, design patterns
show us how to do it. They are standard techniques for software development similar to
algorithms, which operate on a lower level.
• Applications
Entire applications can be thought of as components that provide well-defined services. They
can reference or embed other applications and invoke services by sending messages. Besides
production gains, reusing applications offers the flexibility to customize environment and let
users stick to their preferred tools, e.g., the Emacs text editor. Applications are reused as black
boxes. They have to provide an interface to allow other applications to interact with them,
e.g., to send commands.
• Documentation
Documentation is hard to reuse in a systematic way. The usual case is copying a document
and editing it. The reuse of components should involve the reuse of their documentation as
well. If components are integrated into a software system, so should be their documentation.
Reuse scopes: The amount of possible software reuse depends on the degree of commonalty
among applications that share software. A domain is an area of activity or knowledge
Software reuse Chapter 2
If the majority of applications are in a specific domain, a higher degree of reuse is probable
than among applications across a broad range of different applications. Domain-specific reuse
and general-purpose reuse are often called vertical and horizontal reuse, respectively.
• Abstraction
Abstraction is essential in any software reuse techniques. Abstraction and reusability are two
sides of the same coin. Krueger states: “without abstraction developers would be forced to sift
through a collection of reusable artifacts trying to figure out what each artifact did, when it
could be reused, and how to reuse it.” [Kru_92]
Raising abstraction level is a major challenge in software engineering. The relation between
abstraction and reuse gives a first hint about the difficulties we face in software reuse. Every
software abstraction has two levels: specification (what is done by the abstraction) and
realization (how is it done). The realization of one level of abstraction is the specification of
the next lower level of abstraction. Finding concise abstraction for components is a difficult
task. The best-known successes are in application domains with application-specific, one-
word abstraction, e.g., stack, list (in abstract data types).
• Compositional reuse
Compositional reuse is based on the idea of reusable components that (ideally) remain
unmodified in their reuse. Higher-level or more complex components are built by combining
lower-level or simpler components. Only if needed components that are not available or
cannot be created by modification of existing components are built from scratch or
constructed from lower-level components. The components suitable for reuse are collected in
repository.
Compositional reuse is based on component repositories (e.g., function libraries) or on
principles of organization and composition, like object-oriented construction of software
systems.
Challenges in the context of repositories are techniques to locate components efficiently, e.g.,
classification schemes, retrieval techniques, and to integrate them in software systems. This
lead to the next aspect of compositional reuse, component composition.
Component composition. Software components exist in many different forms. They cannot
be arbitrarily assembled and expected to communicate and cooperate. In order to enable the
combination of components they must rely on the same kind of composition technique.
Module interconnection languages and the Unix “pipe” mechanism are example of possible
Software reuse Chapter 2
examples of a simple, yet powerful composition and integration technique where complex
programs can be built out of simpler ones. The alliance of components is accomplished by
connecting the output of one component to the input of another. Incompatibilities of
components are among the main hindrances of successful component reuse.
Generation-based systems have the advantage that the reused patterns can be designed and
implemented carefully by experienced programmers. But they are applicable only to a certain
domain and are typically restricted to the reuse of source code. Also, they cannot be applied
easily in all situations. Often they are too general or too specific for applications under
considerations.
Components are applicable to a wider variety of applications. Additionally, they are more
modular and self-contained and thus easily maintainable. Compositional reuse provides the
more general approach. The generative approach is useful in specific domains can be built on
top of components.
Software reuse Chapter 2
Basic concepts, definitions, and standards Chapter 3
“Since the beginning of the cycle industry, local blacksmiths and mechanics have participated
in constructing small numbers of bicycles to order. Standardization had two opposite effects
on industry: it further enhanced mass production, and it strengthened the position of those
small workshops. A considerable number of local bicycle makers could offer a ‘home-made’
product to the residents of their small village at a price somewhat lower than that of factory-
produced bicycles because of their lower overhead costs. Some large companies had
specialized in the manufacture of standardized components, delivering them to both bicycle
factories and local workshops. Thus three classes of machine could be distinguished. First,
there were the mass-produced bicycles made by bicycle factories. Only the largest of these
factories manufactured all components themselves; most of them had contracted out the
manufacture of saddles, tires, and the like. Second, there were bicycles made by local
workshops, constructed from proprietary components made by specialized forms. And the
third class of bicycles, made by special department of factories as well as by small
workshops, was known as ‘de luxe’ machines, produced without much regard for costs.”
[Bij_95]
Thus this approach of building bicycles offers the end-users a choice of products (standard,
modified, hand-built) with different cost-quality equations. Such experience was later taken
over by many modern industries, such as automobile industry. Today, a car factory can
produced thousands of cars with very modern technique such as computer aided
manufacturing (CAM), robot, etc., but the idea is always the old one which bicycles were
produced in the 1870s in England, namely, building whole with the pre-existing components.
Those experiences are also observed and learned by software developers. Although there is a
still a long way ahead of us to build software systems as the way we build cars, we want to
summarize the major characteristics of a mature industry like motor industry:
configuration of a PC, and the exact trimming of your car, but within a set of predefined
choices.
• Third-party parts market. In a mature industry, often a thriving third-party parts market
exists, where all the parts are built to well-defined specifications and architectures. There
are companies that focus on building high-quality or low-cost parts, rather than products.
For example, any large car manufacturing company products only a fraction of the parts of
its engines and of its cars.
• Maintenance by part substitution. When a part breaks, it is cheaper and easier to
substitute the whole part rather than fix the issue. Even if as consumers we hate it, it is
cheaper to substitute a whole PC-motherboard than trying to fix a specific integrated
circuit on the existing motherboard. Very few people today know how to replace a
component in a motherboard. It is much easier and more cost-effective to throw the whole
part away and replace it with a new one.
• Supply chain. The costs of manufacturing are only a small part compared to the overall
costs of the supply chain. Successful businesses are able to reduce the costs of the whole
supply chain, including manufacturing but also covering aspects such as distribution.
Third-party parts markets would require that industry standard and well-known protocols for
interactions between components, as well as standard component specifications, exist and are
publicly available. But it would also require a segmentation of the market into solution
providers and component providers, and the availability of component-based solutions for
which the component providers can deliver individual parts.
Maintenance by part substitution would require that it is easy to identify the source of an
issue and easy to replace the affected component with a new version, possible from a different
provider. Among other things, this requires that it is possible to prove that two components
provide equivalent interfaces and functionality as far as the affected solution is concerned.
Finally, addressing the whole supply chain requires that the cost of software manufacturing is
understood to be only a part of the whole software supply chain. In a mature software
industry, developing software should be a small part of the overall cost, which includes
marketing, selling, delivering, and supporting software. Any approach that successfully
supports the industrialization of software manufacturing will need to address in a consistent
way not only software development but also the deployment, distribution, marketing, and
selling of the software.
Because component means different things to different people, we will define the functions a
minimal component must provide. According to [Orf_98], a minimalist software component
should have following properties:
Some Component-model, like that from Object Management Group (OMG), supports not
only the minimal characters of a componentware, they offer but also some additional “smart”
properties, which make the life of software programmers easier. For example, the OMG
CORBA support following facilities, including:
• The Security Service provides a complete framework for distributed object security. It
supports authentication, access control lists, confidentiality, and non-repudiation. It also
manages the delegation of credentials between objects.
• The Licensing Service provides operations for metering the use of components to ensure
fair compensation for their use. The service supports any model of usage control at any
point in a component’s life cycle. It supports charging per session, per node, per instance
creation, and per site.
• The Transaction Service provides two-phase commit coordination among recoverable
components using either flat or nested transactions.
• The Persistence Service provides a single interface for storing components persistently on
variety of storage servers, including Object Databases, Relational Databases, and simple
Basic concepts, definitions, and standards Chapter 3
• Life Cycle Service defines operations for creating, copying, moving, and deleting
components on the ORB.
• The Query Service provides query operations for objects. It’s a superset of SQL. It is
based on the upcoming SQL3 specification and the Object Database Management Group’s
(ODMG) Object Query Language(OQL).
There are a number of definitions on software components. Since we are interested in the
character “plug & play” of componentware so that software can be composed with
components like hardware, we adopt the definition of Szyperski [Szy_98]:
This definition has a technical part and a market-oriented part. The technical part is with
aspects such as independence, contractual interfaces, and composition. The market-oriented
part is described with aspects such as third parties and deployment. It is a property unique to
components, not only in the software world, to combine technical and market aspects. Since
not only technology plays an important role, the market, where components are bought and
sold, takes also significant function.
All three of the above are considered to be different kinds of software components, and each
defines a quite different granularity level (as shown in Figure 3.1).
Basic concepts, definitions, and standards Chapter 3
onent
Co mp
el
e m -lev
t t
Sys ponen
Co m
nt
p one
Com
iness
Bus
ted
s t r ibu nt
Di pone
Com
A software component has an export interface. This interface may contain as little as one
procedure through which a handle to a class factory can be obtained. The class factory in turn
can be used to allocate new objects of the classes that the component implements.
But an export interface may also define interfaces for other components. Such an interface
constitutes a standard to which these other components conform. Components that conform to
one or several common standards may be interoperable, components that conform to no
common standard are not interoperable.
For example, Microsoft’s OLE defines a number of COM interfaces. COM components that
implement objects with these interfaces can be used in compound documents. In imitation of
application framework, the following definition is given [Szy_98]:
“ A component framework is a collection of rules and interfaces (contracts) that govern the
interaction of components plugged into the framework that embodies an abstract design for
solutions to a family of related problems.”
A component framework is a collection of contracts, i.e., rules that specify how objects can
Basic concepts, definitions, and standards Chapter 3
follow because the framework provides suitable code along with the interfaces. For example,
GUI frameworks provide default behavior for applications, windows, menus, and so on. If the
default behavior is not replaced, it can be expected to follow the rules, e.g., to implement the
correct user interface guidelines of the underlying platform. Still other rules may actually be
enforced by the framework, e.g., drawing routines may prevent an application from drawing
outside of its windows. Enforcement means that the framework provides some services only
through safe code that guarantees the necessary invariants (e.g., the invariant "drawing always
occurs inside of the application's windows"). The key to the enforcement of such invariants,
which typically span several objects, is the information hiding across several classes.
In contrast to the older application frameworks, a component framework defines rules for
independently developed and dynamically loadable components, rather than for classes that
are linked together into a monolithic application. A component framework may provide
interfaces, possibly along with some procedures. In contrast to most application frameworks,
component frameworks are black-box frameworks, i.e., frameworks that can be used without
access to their source code. Like a perfect contract, a pure black-box interface is an ideal that
can only be approximated in practice.
Years ago, Microsoft tried a "Windows everywhere" strategy, i.e., one operating system for
every possible use. Today, Microsoft is pushing an "Active Platform" strategy. One
interpretation of this shift is that they realized that the actual code (i.e., Windows) is not
important; that only the collection of interfaces (i.e., the COM interfaces constituting the
ActiveX Platform) matter, as long as there is some implementation of the these interfaces.
Hardware designers have understood the importance of architecture versus implementation
since the IBM 360 in the sixties; software designers are only now catching up to this insight.
A framework embodies architecture, i.e., the design of extension components and their
interactions. Implementing an extension component according to the standard defined by a
framework's interfaces is a form of reuse: design reuse. Since developing a new design is so
much more difficult than implementing an existing design, design reuse is more important
than mere code reuse. Creating a new design requires knowledge of an application domain,
experience with other designs, the capability to distinguish essential issues from unimportant
ones, and a flair for recognizing and inventing patterns. Since bad designs can become very
expensive, only the most experienced developers should create frameworks. Other
programmers should focus on good implementations of existing designs, i.e., develop
components that implement given interfaces. Even more programmers will concentrate on
component assembly.
Framework design is an iterative process. In each iteration, a new solution based on the
framework is developed. Usually, this experience leads to some modification of the
framework and the other already existing extension components. It is hoped that after several
iterations, the framework becomes stable enough that new extension components can be
Basic concepts, definitions, and standards Chapter 3
can easily take several years. The current hectic production of new CORBA, ActiveX/COM
and Java frameworks is dangerous because their definition often seems to develop faster than
the necessary experience. Moreover, standardization and certification issues even further
complicate the already difficult development process.
The time needed to obtain good framework designs has far-reaching financial implications. In
particular, in-house developers in large enterprises need to be aware that developing reusable
software components is almost like developing products for the global market: it requires a
potentially large up-front investment, professional documentation, a market calibration phase,
(internal) marketing and sales, and post-sales support. This approach is too expensive if the
return-on-investment is calculated on a per-project basis; instead of considering the longer-
term savings, time-to-market reduction, lower risk of failure, and better evolvability of
component software systems.
3.5 Major players in the field: OMG, Microsoft, and Sun Microsystems
Componentware is expected a big future and a tremendous market. So this field is full of
competition. The major players are OMG with its CORBA-Specification and Microsoft with
its ActiveX/COM technology. With the increasing deployment of Java technology, Sun
Microsystems plays in this competition also a very important role. As a member of OMG,
Sun Microsystems works tightly with CORBA technology and this combination will have
really a big future.
The "vision" behind CORBA is that distributed systems are conceived and implemented as
distributed objects. The interfaces to these objects are described in a high-level, architecture-
neutral specification language that also supports object-oriented design abstraction. When
combined with the Object Management Architecture, CORBA can result in distributed
systems that can be rapidly developed, and can reap the benefits that result from using high-
level building blocks provided by CORBA, such as maintainability and adaptability.
Technical Detail
Basic concepts, definitions, and standards Chapter 3
CORBA ORBs are middleware mechanisms, as are all ORBs. CORBA can be thought of as a
generalization of remote procedure call (RPC) that includes a number of refinements of RPC,
including:
B
OR
s es
ervice aciliti
AS AF
RB RB
CO CO
OMA services are partitioned into three categories: CORBAServices, CORBAFacilities, and
ApplicationObjects. The ORB (whose details are specified by CORBA) is a communication
infrastructure through which applications access these services, and through which objects
interact with each other. CORBAServices, CORBAFacilities, and ApplicationObjects define
different categories of objects in the OMA; these objects (more accurately object types) define
a range of functionality needed to support the development of distributed software systems.
Naming service Provides the ability to bind a name to an object. Similar to other forms of
directory service.
Event Service Supports asynchronous message-based communication among objects.
Supports chaining of event channels, and a variety of producer/consumer
roles.
Lifecycle Defines conventions for creating, deleting, copying and moving objects.
Service
Persistence Provides a means for retaining and managing the persistent state of objects.
Service
Transaction Supports multiple transaction models, including mandatory “flat” and
Service optional “nested” transactions.
Concurrency Supports concurrent, coordinated access to objects from multiple clients.
Service
Relationship Supports the specification, creation and maintenance of relationships among
Service objects.
Externalization Defines protocols and conventions for externalizing and internalizing
Service objects across processes and across ORBs.
Table 3.1 Overview of CORBAServices
CORBA in detail
Figure 3.3 depicts most of the basic components and interfaces defined by CORBA. This
figure is an expansion of the ORB component of the OMA depicted in Figure 3.2.
ion
e ntat
Implem
nt ect
Clie Obj
**
** *** *** ^^^
^
*** *** ** *** ^^^ ^^^
* *** **** * * * * s * * * * ^ ^ ^ ^
*
** *** * ” *** ***** ton *** *****eleton ^^^ ^^^^^
* * kele * ^
*** namic *
** B IDL
S *** micSk ^^^
Dy OR a
IDL dyn ^r^
tion rfac
e pto
Inv
oca bs Inte Ada
Stu ect
pe Obj
j e c tntsy
b o
heronetati
aecmo
o r pelC
f
onsRim B
s k ellleOt ROB face
s a nfdor a t I nter
ub a l e n
e st ntic end
” * e r eacaer ide n - dep
*** Th rf tio
* *** *** Inte enta ject
** *
*** *****
* *
p l e m
e r a l ob
m
***
* I BI e se
v
OR ayb
re m
re a
^^^
^ The
^^^ ^^^ rs
^ ^
^^^ ^^^ pto
^^^ ^^^^^ ^^^^^ ada
^ ^
^ ^^^^^^^^^^
^ ^
^ ^
^^^ ^^^^^ ^^^^
^ ^
^^^ ^^^^^
^^
^^^ ^
One element (not depicted in Figure 3.2) that is crucial to the understanding of CORBA is the
interface definition language (IDL) processor. All objects are defined in CORBA (actually, in
the OMA) using IDL. IDL is an object-oriented interface definition formalism that has some
syntactic similarities with C++. Unlike C++, IDL can only define interfaces; it is not possible
Basic concepts, definitions, and standards Chapter 3
to specify behavior in IDL. Language mappings are defined from IDL to Java, C, C++,
Ada95, and Smalltalk80.
An important point to note is that CORBA specifies that clients and object implementations
can be written in different programming languages and execute on different computer
hardware architectures and different operating systems, and that clients and object
implementations can not detect any of these details about each other. Put another way, the
IDL interface completely defines the interface between clients and objects; all other details
about objects (such as their implementation language and location) can be made "transparent."
CORBA Core The CORBA runtime infrastructure. The interface to the ORB Core is not
defined by CORBA, and will be vendor proprietary.
ORB Interface A standard interface (defined in IDL) to functions provided by all CORBA-
compliant ORBs.
IDL Stubs Generated by the IDL processor for each interface defined in IDL. Stubs
hide the low-level networking details of object communication from the
client, while presenting a high-level, object type-specific application
programming interface (API).
Dynamic An alternative to stubs for clients to access objects. While stubs provide an
Invocation object type-specific API, DII provides a generic mechanism for constructing
Interface (DII) requests at run time (hence “dynamic invocation”). An interface repository
allows some measure of type checking to ensure that a target object can
support the request made by the client.
Object Adaptor Provides extensibility of CORBA- compliant ORBs to integrate alternative
object technologies into the OMA. For example, adaptors may be developed
to allow remote access to objects that are stored in an object-oriented
database. Each CORBA-compliant ORB must support a specific object
adaptor called the Basic Object Adaptor (BOA). The BOA defines a
standard API implemented by all ORBs.
IDL Skeletons The server-side (or object implementation-side) analogue of IDL stubs. IDL
skeletons receive requests for services from the object adaptor, and call the
appropriate operations in the object implementation.
Dynamic The server-side (or object implementation-side) analogue of the DII. While
Skeleton IDL skeletons invoke specific operations in the object implementation, DSI
Interface defers this processing to the object implementation. This is useful for
(DSI) developing
Table 3.2 Components of the CORBA specification
CORBA 1.1 was only concerned with creating interoperable object applications; the
implementation of the ORB core was left as an “exercise for the vendors.” The result was
some level of component portability, but not interoperability. CORBA 2.0 added
interoperability by specifying a mandatory Internet Inter-ORB Protocol (IIOP). The IIOP is
basically TCP/IP with some CORBA-defined message exchanges that serve as a common
backbone protocol. Every ORB that calls itself CORBA-compliant must either implement
IIOP natively or provide a bridge to it.
We can use inter-ORB bridges and IIOP to create very flexible topologies via federations of
Basic concepts, definitions, and standards Chapter 3
bridges. IIOP promotes diversity and gives us total mix-and-match flexibility, as long as we
use IIOP for our global backbone.
)
SIOP
E/E
B (DC
e OR
k bon
Bac
BA BB
OR ridge OR
B
P)
IIO
RB(
on eO
Ba ckb
BC BD
OR OR
In January 1996, the OMG issued a Request for Proposal (RFP) for “Common Business
cts
Objects” and for a “Business Object Facility”. ThisOis bjeone of the first OMG RFPs to address
explicitly the application developer and end user. ss
u s ine The Business Object Facility (BOF) takes a
“top-down” view, looking at the needs iof Bthe user and application developer, rather than the
previously normal “bottom-up” approach, e c if c aimed at the infrastructure builders’ needs.
Sp
p r ise
er
Ent
es s
ctu r usin
a n cial nufa er B
n
Fi ness Ma - Oth
i ects
Bus cts inngess Obj
j e s i
Ob u
B cts
j e
Ob
je cts
Ob
in ess
n Bus
mo
Com
ct Fa ties
bje ili
Fac
ss O rba
ine ty Co
Bus cviilci es,
r
rb aSe
ba , Co
Cor
Basic concepts, definitions, and standards Chapter 3
Business objects provide a natural way for describing application-independent concepts such
as customer, order, competitor, money, payment, car, and patient. They encourage a view of
software that transcends tools, applications, databases, and other system concepts. The
ultimate promise of object technology and components is to provide these medium-grained
components that behave more like “the real world does.” Of course, somebody must first
define the rules of engagement for these components to play, which is where the OMG comes
into the picture.
Business object are ideal for creating scalable 3-tier client/server solutions because they are
inherently decomposable. A business object is not a monolithic piece of code. Instead, it is
more like a Lego of cooperating parts that we break apart and then reassemble along 3-tier
client/server lines (see figure 3.6). The first tier represents the visual aspects of the business
object – one or more visual objects may each provide a different view. These visual objects
typically live on the client. In the middle tier are server objects that represent the persistent
data and the business logic functions. Typically, these objects work in ensembles. In the third
tier are existing database, legacy server applications, and ERP systems. The partitioning of
business objects is very dynamic. We can decide where to host the different parts at run time.
Basic concepts, definitions, and standards Chapter 3
b ject
ss O
ine
Bus
B
OR
M
OT
MS
DB
B B
OR BA OR
R O
CO M
IIO
P R OT
B
ys tem
PS
B ER
OR
M
OT
a
2 Leg r3
1 T ier Tie
T ier ects s
ects bj ica tion
Obj v er O ppl
Vie
w Ser cy A
Figure 3.6: Three-Tier Client/Server model with Business Object
Middle-tier server objects interact with their clients and implement the logic of business
object. They can extract their persistent state from multiple data sources – for example, SQL
databases, HTML files, and Lotus Notes etc. The server object provides an integrated model
of the disparate data sources and back-end applications. Clients interact with business objects
that naturally correspond to domain entities. They do not have to concern themselves with the
hodgepodge of functions, stored procedures, and databases that live in the third tier. The
business object hides all this nastiness.
Business objects will be used to design systems that mimic the business processes they
support. In the real world, business events are seldom isolated to a single business object.
Instead, they typically involve clusters of objects. To mimic their real-world counterparts,
business objects must be able to communicate with each other at a semantic level. Business
objects must have late binding and well-defined interfaces, so that thy can be implemented
independently. A business object must be capable of recognizing events in its environment,
changing its attributes, and interacting with other business objects. Like any CORBA object, a
business object exposes its interfaces to its client via IDL and communicates with other
objects with the ORB.
Figure 3.7 shows a suite of four business objects that are part of a car reservation system:
customer, invoice, car, and car lot. Note that car lot is a business object that contains other
business objects: cars. Clearly, these four business objects have some agreed-upon semantics
for communicating with each other to perform business transactions. Under the cover, they
could use the CORBA object transaction service to synchronize their actions. They also know
how to share a single window to display their views seamlessly.
ines
Bus
bject
ine ss O
Basic concepts, definitions, and standards Chapter 3
Bus em
t
b j ect n Sys
ess
O tio
s i n s e rva
Bu e
C ar R
ect A
bj
ine ss O
Bus
r
Broke
u est
Req
ect
ba Obj
Cor
So how is this different from a traditional application? With very little work, we can reuse
some of these business objects in another application context. For example, a car sales
program could reuse most of those objects, especially if they were designed to work with
more than one semantic suite. For example, the car, customer, and invoice objects could
support multiple views to handle different business situations.
COM stands for Component Object Model. It refers to both a specification and
implementation developed by Microsoft Corporation which provides a framework for
integrating components. This framework supports interoperability and reusability of
distributed objects by allowing developers to build systems by assembling reusable
components from different vendors which communicate via COM. By applying COM to build
systems of preexisting components, developers hope to reap benefits of maintainability and
adaptability.
It is best to consider COM and DCOM as a single technology that provides a range of
services for component interaction, from services promoting component integration on a
single platform, to component interaction across heterogeneous networks. In fact, COM and
its DCOM extensions are merged into a single runtime. This single runtime provides both
local and remote access.
Basic concepts, definitions, and standards Chapter 3
While COM and DCOM represent "low-level" technology that allows components to interact,
OLE and ActiveX represent higher-level application services that are built on top of COM
and DCOM. OLE builds on COM to provide services such as object "linking" and
"embedding" that are used in the creation of compound documents (documents generated
from multiple tool sources). ActiveX extends the basic capabilities to allow components to be
embedded in Web sites.
The distinctions between various Microsoft technologies and products are sometimes blurred.
Thus, one might read about "OLE technologies" which encompass COM, or "Active
Platform" as a full web solution. In this part, we focus on the underlying technology
represented by COM and DCOM.
Technical Detail
COM is a binary compatibility specification and associated implementation that allows clients
to invoke services provided by COM-compliant components (COM objects). As shown in
Figure 3.8, services implemented by COM objects are exposed through a set of interfaces that
represent the only point of contact between clients and the object.
nter
Poi
nt n
Clie licatio ect
p rf ace Obj
Ap Inte
Figure 3.8: Client using COM object through an interface pointer [COM]
COM defines a binary structure for the interface between the client and the object. This binary
structure provides the basis for interoperability between software components written in
arbitrary languages. As long as a compiler can reduce language structures down to this binary
representation, the implementation language for clients and COM objects does not matter -
the point of contact is the run-time binary representation. Thus, COM objects and clients can
be coded in any language that supports Microsoft's COM binary structure.
A COM object can support any number of interfaces. An interface provides a grouped
collection of related methods. For example, Figure 3.9 depicts a COM object that emulates a
clock. IClock, IAlarm and Itimer are the interfaces of the clock object. The IClock interface
can provide the appropriate methods (not shown) to allow setting and reading the current
time. The IAlarm and ITimer interfaces can supply alarm and stopwatch methods.
ock
ICl
er ck
ITim Clo ct
e
arm Obj
IAl
COM objects and interfaces are specified using Microsoft Interface Definition Language
(IDL), an extension of the Distributed Computing Environment (DCE) Interface Definition
Language standard. To avoid name collisions, each object and interface must have a unique
identifier.
Basic concepts, definitions, and standards Chapter 3
Interfaces are considered logically immutable. Once an interface is defined, it should not be
changed-new methods should not be added and existing methods should not be modified. This
restriction on the interfaces is not enforced, but it is a rule that component developers should
follow. Adhering to this restriction removes the potential for version incompatibility, if an
interface never changes, then clients depending on the interface can rely on a consistent set of
services. If new functionality has to be added to a component, it can be exposed through a
different interface. For our clock example, we can design an enhanced clock COM object
supporting the IClock2 interface that inherits from IClock. IClock2 may expose new
functionality.
Every COM object runs inside of a server. A single server can support multiple COM objects.
As shown in Figure 3.10, there are three ways in which a client can access COM objects
provided by a server:
• In-process server: The client can link directly to a library containing the server. The client
and server execute in the same process. Communication is accomplished through function
calls.
• Local Object Proxy: The client can access a server running in a different process but on
the same machine through an inter-process communication mechanism. This mechanism
is actually a lightweight Remote Procedure Call (RPC).
• Remote Object Proxy: The client can access a remote server running on another machine.
The network communication between client and server is accomplished through DCE
RPC. The mechanism supporting access to remote esservers s is called DCOM.
s rProc
es rve
roc e
nt P al S
Clie ess
Loc
roc
In-P ct b al
e
Obj cess Stu Loc ct
nt n j e
Clie licatio ro
In-P er RPC
Ob
ver
p p v CO
M Ser
A Ser Local
e
a chin
RPC M s
al e m ote Proces
Loc ct R ve r
Ob y j e
t e Ser
x o
Pro
M Rem
CO
ote ote
Rem ct Stu
b Rem ct
e
Obj y
e Obj ver
P r o x
CO
M
t e Ser
o
Rem
If the client and server are in the same process, the sharing of data between the two is simple.
However, when the server process is separate from the client process, as in a local server or
remote server, COM must format and bundle the data in order to share it. This process of
preparing the data is called marshalling. Marshalling is accomplished through a "proxy"
object and a "stub" object that handle the cross-process communication details for any
particular interface (depicted in Figure 3.11). COM creates the "stub" in the object's server
process and has the stub manage the real interface pointer. COM then creates the "proxy" in
the client's process, and connects it to the stub. The proxy then supplies the interface pointer
to the client.
The client calls the interfaces of the server through the proxy, which marshals the parameters
and passes them to the server stub. The stub unmarshals the parameters and makes the actual
Basic concepts, definitions, and standards Chapter 3
passes them to the proxy, which in turn returns them to the client. The same proxy/stub
ry
nda
mechanism is used when the client andouserver are on different machines. However, the
B
internal implementation of marshalling and unmarshalling differs depending on whether the
client and server operate on the same machine (COM) or on different machines (DCOM).
Given an IDL file, the Microsoft IDL compiler can create default proxy and stub code that
performs all necessary marshalling and unmarshalling.
s
ces
Pro
nt
Clie ect
Obj
b
xy Stu
Pro
l l
nne nne
Cha Cha
ib rary rary
ML ML
ib
CO CO
e
tim ime
un unt
CR R
RP RPC
spo
rt ort
n nsp
Tra Tra
All COM objects are registered with a component database. As shown in Figure 3.12, when a
client wishes to create and use a COM object:
ate
1) Cre ct oca
te
e
Obj OM 2) L
C
COM includes interfaces and API functions that expose operating system services, as well as
other mechanisms necessary for a distributed environment (naming, events, etc.). These are
sometimes referred to as COM technologies (or services), and are shown in Table 3.3.
Service Explanation
Type Some clients need runtime access to type information about COM objects.
Information This type information is generated by the Microsoft IDL compiler and is
stored in a type library. COM provides interfaces to navigate the type
library.
Structured COM objects need a way to store their data when they are not running. The
Storage and process of saving data for an object is called making an object persistent.
Persistence COM supports object persistence through "Structured Storage", which
creates an analog of a file system within a file. Individual COM objects can
store data within the file, thus providing persistence.
Monikers Clients often require a way to allow them to connect to the exact same
object instance with the exact same state at a later point in time. This
support is provided via "monikers". A moniker is a COM object that knows
how to create and initialize the content of a single COM object instance. A
moniker can be asked to bind to the COM object it represents, such as a
COM object residing on specific machine on the network, or a group of cells
inside a spreadsheet.
Uniform Data COM objects often need to pass data amongst themselves. Uniform Data
Transfer Transfer provides for data transfers and notifications of data changes
between a source called the data object, and something that uses the data,
called the consumer object.
Connectable Some objects require a way to notify clients that an event that has occurred.
Objects COM allows such objects to define outgoing interfaces to clients as well as
incoming interfaces. The object defines an interface it would like to use
(e.g., a notification interface) and the client implements the interface. This
enables two-way communication between the client and the component.
Table 3.3 COM Services
Maturity
COM has its roots in OLE version 1, which was created in 1991 and was a proprietary
document integration and management framework for the Microsoft Office suite. Microsoft
later realized that document integration is just a special case of component integration. OLE
version 2, released in 1995 was a major enhancement over its predecessor. The foundation of
OLE version 2, now called COM, provided a general-purpose mechanism for component
integration on Windows platforms [Brk_95]. While this early version of COM included some
notions of distributed components, more complete support for distribution became available
with the DCOM specifications and implementations for Windows95 and Windows NT
released in 1996.
COM and DCOM are most mature on Windows platforms. A component marketplace with a
wide selection of COM-compliant objects has developed for Windows. However, the step
from Windows platform-specific COM to distribute, heterogeneous support is quite
significant. DCOM support must mature and component marketplaces must develop if
DCOM is to thrive on other platforms. While the Windows component base provides a
starting point, migrating existing Windows components to alternate platforms will require
significant effort, since these components must be architect and compiled specifically for the
host platform.
There are many PC-based applications that take advantage of COM technology. The basic
Basic concepts, definitions, and standards Chapter 3
The computing paradigm for distributed applications is in flux, due to the relative immaturity
of the technology and recent advances in web-based computing. The Web-centered
computing industry has begun to align itself into two technology camps – with one camp
centered on Microsoft's COM/DCOM, Internet Explorer, and ActiveX capabilities, and the
other camp championing Netscape, CORBA, and Java solutions. Both sides argue
vociferously about the relative merits of their approach, but at this time there is no clear
technology winner. Fortunately, both camps are working on mechanisms to support interplay
between the technology bases. Thus, a COM/DCOM to CORBA mapping is being supported
by CORBA vendors [Foo_96], and Microsoft has incorporated Java into an Internet strategy.
However, work on interconnection between the competing approaches is not complete, and
each camp would shed few tears if the other side folded.
J2EE is a standard set of Java APIs that define a multi-tier architecture suitable for the
development, deployment, and management of enterprise applications written in the Java
programming language. J2EE is functionally complete in the sense that it is possible to
develop a large class of enterprise applications using only the J2EE APIs. Figure 3.13
illustrates the architecture of a J2EE application.
n
rmatio
e
-Sid Info
Basic concepts, definitions, and standardserver pris
e Chapter 3
on S i c er
tati s Log Ent
sen ines
Pre Bus
ide de
nt- S n ve r-Si
Clie t atio Ser
sen
Pre
tem
er Sys
ows b
Br We r EJB iner
v e ta
e
PurML Ser Con
HT
JSP EJB
a
Jav let
Ap p JSP EJB
p
kto
Des
A
a
Jav ation JAVlet EJB
ic r v
p l Se
Ap
e
D evic
O ther
E
J2E t J2E rm
E
J2E rm
E
l i e n f o f o
C a t a t
Pl Pl
Figure 3.14 shows a programmer’s view of a JavaBean. As we can see, a bean exposes to the
world its methods, properties, and the events it emits. Another bean or tool can dynamically
discover this information. The bean saves its state in a (.ser) file that we can package inside a
JAR. A bean is introspective; it can tell us quite a bit about itself via the BeanInfo class. A
bean may prove a Customizer class to help us customize its behavior at design time – this is a
custom wizard that we invoke from within a tool. In most cases, we will be able to customize
a bean by setting its properties via property editor.
Basic concepts, definitions, and standards Chapter 3
nfo izer
nI tom
Bea Cus
ds
tho
Me an
a v aBe ent
J pon
Com
rtie
s nts
pe Eve
Por
JAR
r)
(.ja
There is no IDL – or component definition language – that describes a bean. The JavaBean
specification defines a set of naming conventions (JavaBean calls them “design patterns”)
that we use to identify the methods, events, and properties of our bean.
A visual assembly tool can pass our bean to an Introspector class to generate the BeanInfo
metadata. The Introspector is part of the JavaBeans runtime; it knows exactly how to
interpret the naming conventions. So it is important that we follow the naming rules.
Alternatively, we can explicitly specify a bean’s metadata by providing our own BeanInfo
class; it lets us define – via descriptor – all the introspection information for our bean.
So where is the component infrastructure for running these beans? In a sense, the Java
Developer Kit (JDK) provides a giant framework for running JavaBeans. The JDK provides
the following infrastructure-type services to JavaBeans:
• Visual layout and presentation. A component infrastructure must support the visual
layout of components in containers – for example, a form or an HTML page. It must also
provide services that let components visually interact with each other and with their
containers. In the case of JavaBeans, these services are provided by the Java Foundation
Class (JFC), which include AWT, the 2-D graphics, and the new Swing components.
• Events. The JavaBean event model – also known as the event-delegation model – is the
same one JDK 1.1 introduced for AWT. It requires that interested beans explicitly register
for events in which they have an interest.
• Properties. JavaBeans abide by object encapsulation principles. Consequently, a bean
does not let outsiders directly manipulate its properties. Instead, we must invoke get/set
accessor methods for each variable. JavaBeans support single-value and indexed
properties. In addition, properties can be bound and constrained. There’s nothing sinister
going on here. A bound property will notify interested parties – via events – when its
Basic concepts, definitions, and standards Chapter 3
modification. Of course, the bean is responsible for specifying the behavior of its
properties and for posting the events they generate.
• Introspection. JavaBeans provide a high-level introspector facility that makes it easy for
a visual tool to discover a bean’s incoming and outgoing interfaces. This facility is built
on top of the JDK’s lower-level reflection classes. Developers can define the behavior of
their beans by either using the JavaBeans naming conventions or by providing an explicit
BeanInfo class.
• Persistence. We should be able to store away a component instance and then recreate it at
a later time. In addition, visual tools require components that support some form of
persistence. For example, a tool lets us customize a component by changing its properties;
it must then be able to tell the component to save its newly modified state. Beans take
advantage of the JDK serialization service to automatically save and restore their states.
Our beans can be made to be implicitly persistent – we don’t have to do any extra work
unless we want to customize how a bean is stored. The serialization service also supports a
simple form of versioning, which is an important requirement in component environments.
It enforces simple rules that let newer beans load state written by their older versions; it
also lets newer beans store state in a format that’s consistent with older versions. Finally,
beans can be packaged and distributed using JAR files, another built-in facility of the
JDK.
• Customization. Toolability is an important part of the JavaBeans component model. This
is the area where we will find most of new JavaBeans classes. They encourage us to
provide as many hooks as possible to allow our beans to be used by non-programmers.
Property Editor classes provide the first level of support for tools. They let us visually edit
a particular type of property – for example, a font, color, or integer. Property sheets are
visual interfaces that group all the property editors we need not edit a bean. Finally, bean
customizers provide wizard-like dialogs that let us edit a bean as a whole. In this case,
JavaBeans only specifies a Cusomizer interface and leaves the implementation of the
wizard as an exercise for the programmer. In most situations, property sheets provide all
the customization end users will ever need.
• ORB services. We should be able to invoke a JavaBean across languages, operating
systems, and networks. Java 2 now includes a built-in CORBA-ORB that lets us invoke
methods on beans across all these boundaries. The JavaBeans component model simply
builds on the JDK’s distributed object facilities. The Enterprise JavaBean (EJB) further
extends this model to support distributed transactions.
Each Java Bean component has to be capable of running in a range of different environments.
There is really a continuum of different possibilities, but two points are particularly worth
noting.
First a bean must be capable of running inside a builder tool. This is often referred to as the
design environment. Within this design environment it is very important that the bean should
provide design information to the application builder and allow the end-user to customize the
appearance and behavior of the bean.
Second, each bean must be usable at run-time within the generated application. In this
environment there is much less need for design information or customization. The design time
information and the design time customization code for a component may potentially be quite
large. For example, if a component writer provides a “wizard” style customizer that guides a
user through a series of choices, then the customization code may easily dwarf the run-time
code for the bean. We have therefore a clear split between the design-time aspects of a bean
and the run-time aspects, so that it should be possible to deploy a bean at run-time without
needing to download all its design time code.
Since its introduction over two years ago, Enterprise JavaBeans technology has maintained
unprecedented momentum among platform providers and enterprise development teams alike.
That's because the EJB server-side component model simplifies development of middleware
components that are transactional, scalable, and portable. Enterprise JavaBeans servers reduce
the complexity of developing middleware by providing automatic support for middleware
services such as transactions, security, database connectivity, and more.
As an example, consider transaction management. In the past, developers have had to either
write and maintain transaction management code, or rely on third-party transaction
management systems, generally provided through proprietary, vendor specific APIs. In
contrast, Enterprise JavaBeans technology enables components to participate in transactions –
including distributed transactions – simply by specifying which objects and methods are
transactional. The EJB server itself handles the underlying transaction management details, so
developers can focus specifically on the business purpose of the objects and methods. And
because EJB technology is based on the Java programming language, components can be
deployed on any platform and operating system that supports the Enterprise JavaBeans
standard, and any operating system.
The Enterprise JavaBeans technology model delivers benefits that address the most pressing
concerns of enterprise development teams. These include reduced time to market for mission-
critical applications, effortless scalability and portability, reduced reliance on hard to find
developer skill sets, and an overall increase in developer productivity. EJB technology
reduces the cost of developing enterprise scale applications, while protecting an organization's
existing investment in IT resources.
During the early 90s, traditional enterprise information system providers began responding to
customer needs by shifting from the two-tier, client-server application model to more flexible
three-tier and multi-tier application models. The new models separated business logic from
system services and the user interface, placing it in a middle tier between the two. The
evolution of new middleware services – transaction monitors, message-oriented middleware,
object request brokers, and others – gave additional impetus to this new architecture. And the
growing use of the Internet and intranets for enterprise applications contributed to a greater
emphasis on lightweight, easy to deploy clients.
Within Sun's Java Software division, several development efforts pointed toward what would
become the EJB technology. First, Java servlet technology showed that developers were eager
to create CGI like behaviors that could run on any web server that supported the Java
platform. Second, the JDBC technology gave us a model for marrying the "Write Once, Run
Anywhere" features of the Java programming language to existing database management
systems. Finally, the JavaBeans component architecture demonstrated the usefulness of
encapsulating complete sets of behavior into easily configurable, readily reusable components
Basic concepts, definitions, and standards Chapter 3
the Java programming language, connectors to enable access to existing enterprise systems,
and modular, easy to deploy components – led to the EJB standard and its ability to
effectively leverage and consolidate industry-wide knowledge of middleware.
Component based, multi-tier applications are the future of enterprise computing. And
developers who use the Enterprise JavaBeans technology lead the way in realizing the
benefits of these components: portability and scalability to a wide range of enterprise servers,
along with simplified, rapid application development, deployment, and maintenance. EJB
technology helps protect existing IT investments and promotes freedom of choice for future
investments. Thanks to Enterprise JavaBeans technology, the era of server-side components
dedicated to the "Write Once, Run Anywhere" vision is here.
Object Transaction Monitors (OTMs) are top-of-the-line application servers for distributed
objects. OTMs are a morph between a TP Monitor and an ORB. An OTM manages a set of
containers that in turn run the server-side components. We declaratively define and administer
the properties of our server-side components by setting their attributes – typically, using a
visual tool. The container then provides the callback objects that implement the required
functionality. Programmers simply write their business logic. At run time, the OTM intercepts
all incoming calls, invokes the appropriate callback objects within a container, and then
passes the request to our object.
An ORB is simply an object bus. With an object bus, anything goes. This means our objects
must determine when and how to call the ORB’s services – for example, naming, security,
transactions, and lifecycle. Our objects must explicitly provide all the calls to these services.
Consequently, our objects will end up with a ton of system-specific code. This makes them
hard to port across containers. In addition, each object must orchestrate the calls to the
different services, which is also a difficult and error-prone process. It requires highly-skilled
programmers who understand the workings of an ORB and its related middleware services. In
contrast, an OTM provides a framework – or organized environment – for running server-side
components. With an OTM, we get organized anarchy: everything goes, as long as we play by
the framework’s rules.
OTMs follow the “Hollywood Principle”: “Don’t call us; we call you”. The OTM framework
is the primary orchestrator of our server-side components. It calls our components at the right
time, and in the right sequence.
Enterprise JavaBean provides the first formalized component-to-OTM contract for the
CORBA/Java world; EJB defines the callback interfaces a server-side bean must expose to its
OTM, and vice versa. In addition, EJB specifies a packaging mechanism for server-side
components. So we should be able to set the quality-of-service attributes of an EJB via a
visual tool, package the EJB inside a JAR, and then run it within any EJB-compliant
container: Figure 3.15 shows the major functions a server-side container provides to the EJBs
that run within it.
M)
Basic concepts, definitions, and standards OT Chapter 3
t or (
M oni
ct ion
nsa
ct Tra
O bje
e /
JAR r ativ a tion n
l a n i v te nt
Dec sactio Act tivatio Sagtaeme
n c an
Tra Dea M
rk
ata m ewo ainer)
M etad a
Fr Con t
B
(EJ
y
est urit
Ma
nif le
cycent Sec
f e
Li agem
n
Ma
B
t OR
o p men
e l o r
Dev script e
D e e r -sid ts
v
EJB EJB EJB Ser ponen
g Co m
kagin
Pac
• Distributed object infrastructure: EJB does not concern itself with the distributed object
infrastructure; it assumes an underlying ORB that understands the CORBA RMI/IDL
semantics.
• Component packaging and deployment: EJB defines a packaging mechanism for
server-side components based on JARs, manifests, and deployment descriptors. The
container un-JAR the EJB and then runs it based on the instructions it gets from the
manifest and the deployment descriptors.
• Declarative transaction management: EJB supports implicit transactions built on the
CORBA OTS service. The EJB container automatically manages the start, commit, and
rollback of a transaction. We define the transactional attributes of a bean at design time (or
during deployment) using declarative statements in the deployment descriptor. Optionally,
a bean can explicitly control the boundaries of a transaction using explicit CORBA OTS
semantics.
• Life cycle management: EJB containers manage the entire life cycle of an enterprise
bean. As a bean provider, we are responsible for defining one or more create methods in
the HOME interface, one for each way we create an EJB object. Our bean must implement
an ejbCreate method for each create method we defined in the Home interface. The Home
interface also defines find methods to help clients locate existing entity beans. As a last
step, we must register our Home interface with a Naming Service so that clients can create
new beans.
• Bean activation and passivation: as part of managing the life cycle of an enterprise
bean, the container calls our bean when it is loaded into memory (or activated); it also
calls it when it is deactivated from memory (or passivated).
• Bean state management: EJB containers can manage both transient and persistent beans.
Persistent (or entity) beans encapsulate in their object reference a unique ID that points to
their state. An entity bean manages its own persistence by implementing the persistence
operations directly. The container simply hands it a unique key and tells it to load its state.
In a future release of EJB, the entity bean will be able to delegate the management of its
persistence to its container.
Basic concepts, definitions, and standards Chapter 3
• Container metadata: EJB containers can provide metadata about the beans they contain.
For example, the container can return the class name of the enterprise bean that is
associated with this Home interface.
• Security: EJB containers automate the management of some of the security aspects of our
beans. We get to declaratively define the security rules for our enterprise bean in an
AccessControlEntry object; we must then serialize this object and put it in our bean’s JAR.
The EJB container uses this object to perform all security checks on behalf of our bean.
This list shows what an EJB container does for its beans. The beauty of the EJB framework is
that it lets us declaratively define most of our server-side run-time attributes. So we can use
visual tools to administer and set the properties of our server-side components – including
their transactional, security, and state management policies.
It is currently unclear if any one-component model will become dominant in the industry. It
seems that the most likely outcome is that all components models will achieve, at least, a
minimum critical mass market share, necessary for survival. Not surprising, the majority of
vendors, apart from Microsoft, IBM and Sun, are following a strategy of supporting all three
component models, specifically because of the uncertainty.
The challenge for most vendors of component technologies is that they currently remain
technical complex to use. New developments of the component models promise to make them
easier to use. The evolution of use of COM into COM+, and similarly EJBs, will remove the
need to program the use of complex infrastructure services into the logic of the component
itself. This will not only make the developers’ job easier, leaving them more portable.
onent
Comp
at ion
plic
Ap et * er
get c a ng r l ect ustom acy DB
d to I e S e g
e e
I n omer s tom m C a le
t
u
c ls Fro from
cus ls i
i deta And m
det a te
sys
n
ntatio acy
ace me Leg em
erf le t
Int Imp Sys
Moving the code that deals with the physical implementation of “get Customer Details” from
the application into a component, removes the need to maintain the application as these
changes occur. Of curse, the component would still have to be changed twice, but if the
component was used in five applications, we have saved eight maintenance tasks.
The above scenario is shown in Figure 3.16. It works because the physical implementation of
a component is hidden behind an interface that provides a logical view of what the component
does without realizing how it does it. Of course, the interface has a physical implementation
too, but this should give no clue as to the internals of the physical implementation of the
component. The applications that consume the component do so only via the interface, not by
figuring out how to jump straight to some address in the code, or the name of the database, so
it can be read directly. Neither should the interface have parameters that pass information or
instructions that are implementation dependent.
We can look at the interface of a component at the binary level, the domain-specific
application level, and sometimes at the user interface level. But before looking at existing
standards for these various interface levels, we should take a closer look at what an interface
Basic concepts, definitions, and standards Chapter 3
An interface defines what a component vendor must provide, and what a customer can expect
to get. For example, a mathematics component may implement an interface that defines
procedures for calculating the sine and cosine functions:
DEFINITION Math;
PROCEDURE Sin (x: REAL): REAL; (* return the sine of x *)
PROCEDURE Cos (x: REAL): REAL; (* return the cosine of x *)
END Math.
Contracts involve at least two parties, e.g., a vendor who promises to provide some goods,
and a customer who promises to consume the goods in a particular way. For example, an
author writes a book, and a book publisher publishes this book. Both author and publisher are
bound by a contract. Sometimes a contract comes from a third party. For example, many
professional organizations offer standardized contracts for their profession.
There are good contracts and bad contracts. A good contract should be clear, complete, and
concise. A bad contract is ambiguous, misses important points, or lays down irrelevant
details. All these deficiencies lead to one party making false assumptions about the behavior
of the other. If a point in a contract is ambiguous, each party must supply its own
interpretation of what its and the other one's duties are. This easily leads to incompatible
assumptions, and then to conflict.
If something important is missing, tacit assumptions may pop up. If such an assumption
remains valid for some time, it may turn into an unwritten law, i.e., into an implicit
refinement of the contract. But this refinement is fragile, since the assumptions may suddenly
not hold anymore, when the other party sees reasons to do things in a different way in the
future. This leads to a power struggle or cancellation of the contract.
If irrelevant details are fixed in a contract, an unnecessary constraint is put on one or both
parties. There comes the time when one party wants to change the contract in order to be more
flexible. This can lead to expensive and possibly futile attempts at renegotiation. Or instead of
negotiating, a contractor may simply violate the contract. If this leads to no complaints, the
violation also may turn into a kind of established right. But power struggles, cancellation of
the contract, or litigation are likely.
In summary, contracts that are ambiguous or underspecified are fragile, while overspecified
contracts are too constraining. Both are likely to lead to conflicts. Interestingly, the conflicts
often break out when the contract needs to be amended for some reason. This is a very
important effect, as we will see later. The art lies in defining contracts which are neither
under- nor overspecified.
Contracts have other interesting properties. For example, if someone has to provide a certain
amount of valuable goods, the receiver usually won't complain if he receives a larger amount.
Vice versa, if the receiver for some time requires a smaller amount than agreed upon, the
provider usually won't mind either. This means that in some cases, contract violations are
harmless. Another interesting point is that contracts often have an expiration date, i.e., they
are only valid for some predetermined period of time.
What does this all have to do with interfaces between components? The parties bound by a
contract correspond to components interacting through some interface. Bad contracts are
Basic concepts, definitions, and standards Chapter 3
For example, the following formal specification indicates in the precondition that the input
parameters x and y must not be negative. In the postcondition, it is specified that the result
parameter z is the sum of x and y.
This is an interface (contract) between the developer of the procedure and the caller of the
procedure. The developer is free to accept weaker preconditions, e.g., it may also accept
negative values for x and y. While this can never be wrong, no one may rely on the
assumption that negative values for x or y are handled in a particular way. Similarly, a
developer may support stronger postconditions, i.e., it may deliver more than what is required.
An interface that defines too many inessential details will cause programmers to use them and
to rely on their availability. This makes it impossible to change these details later, even
though it may become strongly desirable to do so. Giving too many details is especially
enticing if there already exists some complex but undocumented code, which is to be turned
into a component. Then the easy thing to do is to publish the source code and not bother with
the definition of a less constrained interface. As a result, the entire implementation becomes
the interface and may never again be modified, since this may break the client code, i.e., the
other party.
behaves. Such a complex "specification" is similar to a contract that contains a book full of
small print.
Even if a software component has a minimal and well-defined interface and is not available in
source code, an inventive programmer will find out by trial and error how the component
behaves under circumstances that are not mentioned in the interface. Basically, such a
programmer derives his own ad-hoc interface specification that is more specific than the
published interface, i.e., the contract. If he takes advantage of this more useful but fragile
extended interface, then his code may break when the component is replaced by a new version
whose internal workings have changed. We all know this effect from applications that
suddenly don't work correctly anymore after a new operating system release is installed.
These applications relied on assumptions that were not written in the contract and thus not
guaranteed. Of course, if a sufficient number of important applications rely on such
undocumented features, the operating system vendor may be forced not to change them in the
future anyway. Thereby the vendor would, grudgingly, accept the established rights of the
marketplace.
Can interface contracts be enforced? To some degree, such enforcement is possible. Some
contract violations can be detected at compile time by the compiler, other violations can be
detected later at run-time, by using suitable hardware and software protection mechanisms.
At the most basic level, every component is required to interact with other components
through their interfaces exclusively; this is a kind of universal contract, i.e., a law. For
example, directly overwriting another component's memory would be a gross violation of the
law. In a closed world, e.g., in an isolated monolithic application, this problem can be solved
easily. But in an open component software world, interference between components is a
fundamentally more critical issue. If the hardware or software infrastructure of a computer
can completely prevent the violation of interface contracts and laws, the reliability of the
whole system will improve, by limiting the damage that a component can possibly create
("bug containment"). There exist hardware protection facilities and in particular modern
programming language designs that provide this kind of safety.
When a component is sold worldwide, the vendor typically doesn't know all its customers
anymore. This means that it has a contract with unknown parties. Since contracts can be
changed only if all parties agree, it follows that an interface of such a component may never
again be modified. Except in the harmless ways described earlier, i.e., by providing more, or
by requiring less than what was specified in the original interface.
Finally, if a vendor and a customer agree on using a standard contract from a professional
organization in their field, this is similar to a component constructor and a component
assembler who agree on the same standardized component interface that was defined by some
third-party framework designer.
We have seen that contracts give a deep insight into the nature of component interfaces. By
now, we should have become sensitive to the problem of good interface specifications.
Unclear interfaces lead to incompatibilities, underspecified interfaces lead to the invention of
ad-hoc interfaces by trial and error, and overspecified interfaces provoke overly constrained
or outright incorrect implementations. Under-specification and over-specification are both
latent sources of conflict: when a component is replaced by a new version, dependent
components may suddenly break.
There is confusion in popular writings about the similarity and differences between an object
and a component. Some of this stems from the fact that component technology is often best
implemented using an object-oriented language; more fundamentally, it stems from loose
usage of the terms object, class, and component; and the subtle distinctions between concepts
and instantiations of those concepts.
Components are on the upswing; objects have been around for some time. It is
understandable, but not helpful, to see object-oriented programming sold in new clothes by
simply calling objects “components”. In this section, we will try to make a difference between
those two concepts. So, what exactly is Object Orientation? Booch defines the Object-
Oriented Programming (OOP) in [Boo_94] as follows:
Individual objects don't stand alone. They belong to a collection of other similar objects that
all are members of the same group, or class. Classes and objects are closely related, but are
not the same thing. A class is a description or definition of the characteristics of objects that
belong to that class. An object is a single instance or member of a class. There can be many
instances of objects of a given class, but all members of a class have similar behavior.
For example, there might be a class called sensor used to model sensors. The class would
define the characteristics of all sensors. Each individual physical sensor in the system would
be represented be as object belonging to the class, and have specific values for the attributes
described by the class definition.
The class description includes the means of accessing and changing the state of individual
object members of that class. One common representation of color is called RGB, where the
color is specified by the values of its red, green, and blue components. A color class
description would provide the means of both retrieving and setting the RGB values of a color
object.
It is also typical to describe one class based on a different class - either by extending the
description of a higher-level class, or by including the description of another class within the
current class. For example, we might create a class that describes the general characteristics of
all sensors, and then more specialized classes that describe specific sensors such as
temperature or pressure.
We will refine the definitions of an object and a class later, but objects and classes are really
the heart of Object Orientation. OO software systems consist of objects of different classes
that interact with each other using well-defined methods or services specified by the class
definitions. This represents a totally different software paradigm. To produce successful OO
designs and programs, it is important to switch our thinking so that everything becomes a
well-defined, self-contained object that interacts with other objects in well-defined ways.
Basic concepts, definitions, and standards Chapter 3
Objects and classes are related, but are not the same thing. Each individual object is a single
instance of a class, something that exists. It is said to be a member of a given class. A class is
the description of the attributes and behaviors of all members of that class.
Objects
Classes
A class called Animal would be a base class because there never would be an instance of a
general object called an Animal. Instead, there would be more specialized subclasses of
Animal such as Horse or Snake, which would have instances.
A component may contain multiple classes, but a class is necessarily confined to a single
component; partial deployment of a class wouldn’t normally make sense. Just as classes can
depend on other classes (inheritance), components can depend on other components (import).
The superclasses of a class do not necessarily need to reside in the same component as the
class. Where a class has a superclass in another component, the inheritance relation crosses
component boundaries.
Is an object a component?
Components are software artifacts, and represent the work of software developers and their
tools; objects are identifiable individual instances created in running systems by executing
code that is a part of some component. So, in that strict sense, an object is not a component.
Parts of the code in a component may define the templates for objects, e.g. using OOP classes.
It is the component code that is reused.
Basic concepts, definitions, and standards Chapter 3
That said, a component, when deployed and running, will often be manifested as a collection
of objects; and can sometimes be usefully treated as though it was one large-grained object.
So we can sometimes use the term “component” a bit more loosely to refer to the object, or
set of objects, that manifest a particular usage of a component in an application. Even if a
component is not implemented with object technology, a single large-grained unit, when
running, can usually be modeled as an object; if it has no local state then there would be not
much use to refer to its identity.
Is a class a component?
class C1
implements I1, I2 // interfaces this class implements
{
public T0 foo (T1 x);
private T2 y;
}
If class C1 inherited part of its implementation from another class, then the interfaces
provided and required would include the inherited ones; and there would be a direct
implementation dependency between the classes. Many believe that implementation
inheritance, while often very useful, should not cross component boundaries; when the
boundary must be crossed, it may be better to adopt a composition or delegation style
approach.
In general, a component could implement its interfaces (a) by directly exposing them to
clients, or (b) by implementing classes that provided those interfaces; clients would need to
obtain a handle to an instance of such a class to use that interface.
Component Objects
Components carry instances that act at run time as prescribed by their generating component.
In the simplest case, a component is a class and the carried instances are objects of that class.
However, most components (whether COM or JavaBeans) will consist of many classes. A
Java Bean is externally represented by a single class and thus is a single kind of object
representing all possible instantiations or uses of that component. A COM component is more
flexible. It can present itself to clients as an arbitrary collection of objects whose clients only
see sets of unrelated interfaces. In JavaBeans or CORBA, multiple interfaces are ultimately
merged into one implementing class. This prevents proper handling of important cases such as
components that support multiple versions of an interface, where the exact implementation of
a particular method shared by all these versions needs to depend on the version of the
interface the client is using.
Basic concepts, definitions, and standards Chapter 3
While components capture the static nature of a software fragment, objects capture its
dynamic nature. Simply treating everything as dynamic can eliminate this distinction.
However, it is a time-proven principle of software engineering to try and strengthen the static
description of systems as much as possible. We can always superimpose dynamics where
needed. Modern facilities such as meta-programming and just-in-time compilation simplify
this soft treatment of the boundary between static and dynamic. Nevertheless, it’s advisable to
explicitly capture as many static properties of a design or architecture as possible. This is the
role of components and architectures that assign components their place. The role of objects is
to capture the dynamic nature of the arising systems built out of components. Component
objects are objects carried by identified components. Thus, both components and objects
together will enable the construction of next-generation software.
3.7.4 Conclusion
Component-based technology has a strong object-oriented character. JavaBeans and
Enterprise JavaBeans exemplify component-based technology. The OMG’s Unified Modeling
Language (UML) – itself an outgrowth of object-oriented analysis and object-oriented design
– actively addresses component concepts. But a software component is much more
“intelligent” than a normal OOP object. For example, CORBA components are different from
normal OOP objects in following aspects:
To state the conclusion, we are agreed that object technology is a useful and convenient
starting points for component technology, but
• By itself, object technology did not express the full range of abstractions needed by
component-based software development; and
• It is possible to realize component-based software development without employing object
technology.
Benefits and risks of using componentware Chapter 4
The advent of component software is one of the most important new developments in the
software industry since the introduction of high-level programming languages. Component
software combines the advantages of custom software and standard software. It enables
solutions that are better evolvable, are more readily maintainable, can be extended over time,
and can be modernized incrementally.
However, custom software also has severe disadvantages. It is typically much more expensive
than standard "shrink-wrapped" software and its development can take a long time. Long
time-to-market is especially critical, since by the time the software is ready, it may already be
obsolete, because the business needs have changed again already.
In the last decade, the complexity of software environments has increased tremendously.
Highly interactive PCs with extensive multimedia capabilities, networks ranging from local
area networks to the Internet, and demanding graphical user interfaces lead to an explosive
growth in both operating system complexity and application complexity. To remain
competitive, every new release of an application has to support at least some of the new
capabilities of the operating system and hardware. This trend leads to ever more features,
larger software ("fatware"), longer development cycles, and last but not least, more defects in
the produced software.
To keep up with these increasing challenges becomes harder and harder. Thus it is not
surprising that the risks of custom development are avoided whenever possible. Instead,
people shop for standard software.
Of course, buying standard software is only possible if at least one vendor has already
developed software for this market niche. The more specialized our requirements are, the
smaller is our market niche, and the less likely it is that we find an off-the-shelf solution. If
there exists no standard solution for our problem, this also affects our competitors. In such a
situation, with no standard software to level the playing field, custom software can give us a
critical advantage over our competitors.
The financial services market is a good example of where custom software often still makes
sense. For example, a bank may develop its own balance sheet rating application, hoping to
better judge the risks involved in business loans, and thereby reduce the losses caused by
Benefits and risks of using componentware Chapter 4
Figure 4.1 shows the software features that may apply to a given type of market, e.g., for the
financial services market, and the percentage of customers in this market who can use these
features. To the left side, the most commonly used features are located. To the right side, the
features desired only by one customer are located. Custom software works best for products
targeting the right side of the spectrum, since there the market is too small for standard
software.
ers
c u stom
l
f al ent d by
5 0 % o t segmquire
ut ke s re
Percent of Customers
100%
abo is mar#14 i
t h r e
in eatu
F
e.g.
50%
#14
res
0%
u
feat
Once we have bought the software, we need to install it. This can be quite a challenge, since
many applications have extensive configuration facilities, allowing to fine-tune them to
specific needs, up to a certain degree. Some high-end commercial packages go to extremes in
this respect. They provide thousands of parameters that have to be set up appropriately. This
can be so complex that it is unpractical without the help of expensive systems integrators.
Even though standard software may provide extensive configuration features, it still forces us
to adapt our business to the needs of the software, rather than the other way around.
Word processors are a prime example for standard software. Every new generation of word
processors adds new features, if only to keep up with the competition. Often, these features
are of little use to most buyers, but still everyone must pay for them. Since standard software
is sold in large volumes, the costs of the software alone may even be very low. But there are
hidden costs, e.g., the cost involved in training, or in upgrading to more powerful hardware.
The latter is often necessary because a new software release is typically much larger and
slower than its predecessor. Operating systems are further examples of this “fatware” trend:
when our company switched from Windows 3.11 to Windows 95, how much money did it
spend for hardware upgrades or replacements? Standard software works best for products that
address the left side of the spectrum of required features, i.e., where the features required by a
large percentage of customers are located. “Fatware” is standard software that tries to
implement too many features that are too far to the right side of its market's spectrum of
required features.
Ideally, we would like to combine the advantages of full custom software and standard
software: tailored software at the price of off-the-shelf software. Unfortunately, this is asked
for too much. Fortunately, there is a practical way of getting at least closer to this ideal. The
idea is simply to combine custom and standard software. Why shouldn't it be possible to buy
70% of an application in a store, and to develop the remaining 30% in-house? For example, a
balance sheet rating application may consist of word processing and rating functionality. Why
not buy a word processor, develop the rating algorithm, and then assemble the two pieces into
a complete balance sheet rating solution?
Obviously this is only possible if software pieces from different origins can be composed such
that they work together in a meaningful way. Such software building blocks are called
software components, in contrast to monolithic software.
Most "new" business applications can be implemented as modifications to, or new groupings
of, existing components.
It may happen in a software project that someone remembers that some part of the current
problem had already been solved for an earlier project. If this partial solution has the form of
a separate component, it can be reused in the new project, thus saving time and cost.
A component implementation can be replaced by a new version if its interface remains the
same. This makes it possible, e.g., to send an incremental update to a customer, rather than a
new release of the entire application (or operating system). Hence, only a corrected or
otherwise improved component needs to be sent to the customer.
So far, the outlined advantages of component software have been mostly traditional software
engineering advantages. They are desirable in any type of large-scale software development
project. But component software is much more than good software engineering. The main
advantage of component software is the creation of markets. Component markets mean that a
developer can buy the more generic features of a desired application, and concentrate on the
more specific features that make the application truly valuable to the customer. Thus
component software lets small developers focus on their core competence and achieve shorter
time-to-market. It breaks the trend towards software that is so large and complex that only a
few vendors can keep up, while small developers are driven out of business.
If a component is of sufficiently general interest, it can be sold on the market. While this
possibly results in a loss of a competitive advantage for the component vendor, it may
Benefits and risks of using componentware Chapter 4
Looking back at all the advantages we've discussed, we can see that the majority of
developers, i.e., small and medium companies, have no business interest in monolithic
software. They can only profit from a move towards component software. But interestingly
enough, the large companies, which could have more vested interests in sticking to monolithic
software, are also shifting towards component software. Probably this is because the
maintenance and further development of their monolithic “fatware” has already turned into a
software engineering nightmare so precarious that even unlimited resources won't help
anymore.
Component software allows adding new functionality over time, by adding new components
to an already existing solution. In this way, a solution can be extended to handle new needs
over time.
In order to use a component, a programmer must have access to its interface description. If the
interface is clear and complete, any competent programmer could develop an alternative to an
existing implementation. For example, assume that we have a word processor “Write” and a
spelling checker “Spell”. The spelling checker allows us to spell-check Write texts, i.e., it uses
the Write programming interface. Now, if the better word processor “WritePro” comes on the
market, we want to substitute “WritePro” for “Write”, without buying a new spelling checker.
This is possible if “WritePro” implements the same interface as “Write” does (or a strict
superset of it), and if “Spell” only accesses a text via this interface. In this example, we have
replaced one component by another one that implements the same interface.
This is one of the most important characteristics of component software: it replaces "either/or"
decisions by more gradual, and thus less critical, decisions. The question is not whether or not
to replace existing software anymore; the question rather becomes which components to
replace. The question is not "make" or "buy" anymore; the question rather becomes which
components to buy and which components to develop. Component software introduces
gradual choice where previously there were only hard absolute decisions. Figure 4.2
illustrates the gap in the spectrum between "make" and "buy"; this gap is closed by
component software:
Benefits and risks of using componentware are Chapter 4
ftw
r d so
nda
Sta
tom war
e
Cus oft
asre gap ss
t so
ftw a k e
b u sine
d a p M apt
+ a ess ++ - ad twarel
b usnintrol + ++ of tro
o
t ll co +
+ ++ tolse con ive et
e ket + ++ t s ark
+ fu ensiv o-mar ++++ +
t
- li expen -to-m
p t
- ex time- ++
+ +
+ ++ + + in rt time
n g uce u +y++ + + + o
+ sh risk adapt
- lo h risk prod + +B
+ +
++ + + + ++ + +
w
o + ++ + + + + + o
g
- hi ficult
t
+ ++ + + + ++++ + + l icult t costs
o
f f f t e d
- di + ++ +
+ ++ + ++ + +
i
- d expec
+
+ ++ + +
+
-u n
+ ++
No company will ever be able to develop the best-of-breed products in every possible
software category and to integrate them all into one package. Component software allows the
buyer to pick and choose the best products among all vendors in the world, and integrate them
in a plug-and-play manner. The larger and more diverse component markets become, the
more leverage a buyer has in building a uniquely powerful and customized software
environment.
For complex problems, buyers may still rely on systems integrators to do the integration of
components, but the dependence on single vendors or integrators is much less than it was with
either custom or standard software.
Because of this new freedom of choice, the software industry in the long run will likely
become much more customer-driven than it is today. Why? Because customers and customer-
driven organizations can propose new component interfaces. Such component interfaces,
standards in fact, create markets by forcing vendors to compete with each other in creating
better implementations of these interfaces.
Components can create a worldwide mass market with fierce competition. The idea of
component software is to tap the entire potential of a global software economy, rather than
relying on the limited capabilities of only one vendor. Component software simplifies the
cross-over of good ideas. After all, even a market leader can steal and reimplement only a few
good ideas per new release of a software package; there's just no way he can compete with all
the developers on the planet, once they start to build interoperable components. Crossover
makes new good ideas gain market share in an explosive way. Monolithic software with its
linear growth of good ideas cannot compete with this advantage of component software.
We have seen that component software is in the interest of small and large vendors, software
integrators, and buyers. Everyone wins. But are there domains where component software
simply doesn't work?
If we look at the spectrum of required features (see Figure 4.1), it becomes clear that the most
obvious candidates for component software are the products in the middle of the spectrum,
i.e., features that are desired by many, but not by all, customers. There it makes most sense to
create a component market. If everyone had completely unique requirements, there would be
no market for reusable components. On the other hand, if everyone had exactly identical
requirements, there wouldn't be room for more than a few vendors.
However, even these left and right extremes of the spectrum benefit from component
software, due to its inherent software engineering advantages, in particular its better
evolvability. But it is more expensive to dethrone established market leaders in these areas.
Benefits and risks of using componentware Chapter 4
Today many people still believe that their particular field cannot benefit from component
software. It is argued that a domain is too complex, or that there is no market in this domain,
and so on. Often, these beliefs come from a lack of experience in the design of modular
software. Very complex pieces of software have successfully been turned into components,
e.g., whole operating systems. The complexity of a problem does not prevent component
software. On the contrary; without a divide-and-conquer strategy such as component software,
truly complex problems cannot be handled anymore. Even specialized domains such as
embedded systems look like promising opportunities for component software, since there the
spectrum of required features looks very good, with many features in the middle of the
spectrum. The market in this domain is still underdeveloped, but that doesn't mean that it
cannot grow into a strong one.
The benefits of using componentware can also be observed and summarized in other
perspectives: business benefits and technical benefits.
One of the compelling arguments for componentware is that it allows legacy and packaged
applications to be reused. So the componentization task, unlike previous technology led
trends, does not require the total replacement of all previous investment in software
applications. Further, building applications using components from different sources, or of
different styles, can promote an effect of diversification and, therefore, can reduce the
enterprise’s dependence on only one service supplier.
be reused already tested and certified. Software reuse of components, while still inhibited by
culture and organizational issues, is both easier and more productive than code reuse.
Secondly, the component approach breaks down large applications into more manageable
chunks that can each be micro-managed in terms of their life cycle, and staff can be assigned
based on skills appropriate to individual components as opposed to the whole application.
Thirdly, the use of stable, published interfaces enables the assembly or integration of
applications from disparate sources of components, including wrapped legacy and packaged
applications.
Finally, outsourcing and package acquisition can take place at the component level, enabling
organizations to retain control at the application level and more easily integrate them
alongside legacy applications and in-house new build. Taken together, the componentware
can reduce costs and improve the manageability of application delivery.
• Power users will find it second nature to assemble their own personalized applications
using off-the-shelf components. They will use scripts to tie the parts together and
customize their behavior.
• Small developers will find that components reduce expenses and lower the barriers to
entry in the software market. They can create individual components with the knowledge
that they will integrated smoothly with existing software created by larger development
shops - they do not have to reinvent all the functions around them. They can get fine-
grained integration instead of today’s ‘band-aid’ integration. In addition, they get faster
time to market because the bulk of an application is already there.
• Large Developers, IS shops and System integrators will use component suites to create (or
assemble) enterprise-wide client/server applications in record time. Typically, about 80%
of the function they need will be available as off-the-shelf components. The remaining
20% is the value-added they provide. The client/server systems may be less complex to
test because of the high reliability of the pre-tested components. The fact that many
components are black-boxes reduces the overall complexity of the development process.
• Desktop vendors will use components to assemble applications that target specific markets
(for example, ‘WritePro for Financial Firms’). Instead of selling monster suites at high
prices, they will be able to provide their consumers with what they really need. Even the
Pay-per-Use can be achieved, when customers use the Corba compatible products, which
provide this Corba Service. Increased customization and more malleable products will
create new market segments. Consumers will not be at the mercy of long product release
cycles to get new functions. They can buy add-on functions, in the form of components,
when they need it.
Reusable components can be very large and contain up to a hundred KLOC or more.
Consequently, these components represent considerable investments, multiple man-years in
certain cases. Therefore, some companies maintain multiple versions (implementations) of
components in parallel. One can identify at least four situations where multiple versions are
introduced.
• Conflicting quality requirements: The reusable components that are part of the product
line are generally optimized for particular quality attributes, e.g., performance or code
size. Different products, even though they require the same functionality, may have
conflicting quality requirements. These requirements may have so high priority that no
single component can fulfill both. The reusability of the affected component is then
restricted to only one or a few of the products while other products require another
implementation of the same functionality.
• Variability implemented through versions: Certain types of variability are difficult to
implement through configuration or compiler switches since the effect of a variation
spreads out throughout the reusable component. An example is different contexts, e.g.,
operating system, for an component. Although it might be possible to implement all
variability through, e.g., #ifdef statements, often it is decided to maintain two different
versions.
• High-end versus low-end products: Low-end products, generally requiring a restricted
subset of the functionality, pay for the unused functionality in terms of code size and
complex interfaces. Especially for embedded systems where the hardware cost play an
important role in the product price, the software engineers may be forced to create a low-
end, scaled-down version of the component to minimize the overhead for low-end
products.
• Business unit needs: In the organizational models, where the business units are
responsible for component evolution, components are sometimes extended with very
product-specific code or code only tested for one product. The problems caused by this
create a tendency within the affected business units to create their own copy of the
component and maintain it for their own product only. This minimizes the dependency in
one business unit and solves the problems in the short term, but in the long term it
generally does not pay off: Business units had to rework considerable parts of their code to
incorporate a new version of the evolved shared component that contained functionality
that needed to be incorporated in their product also.
Since the components are all part of a component architecture, they tend to have dependencies
between them. Although dependencies between components are necessary, often
dependencies exist that could have been avoided by another modularization of the system or a
more careful design. The initial design of the architecture generally defines a small set of
required and explicitly defined dependencies. It is often during evolution of components that
unwanted dependencies are created. Three situations are identified where new, often implicit
dependencies are introduced:
Legal issues
Many legal issues in the context of software reuse are still diffuse. For example, what exactly
are the rights and responsibilities of providers and consumers of reusable components? What
happens if a reused component fails in a critical application? Such issues are not so important
for reuse within companies or organizations, but may be a hindrance for reuse across such
boundaries [Fis_94].
Software is legally protected as intellectual property. Laws for this protection may differ
among various countries. The following types of protection are usually provided for software:
trade secret protection, copyright protection and patent protection [Yoc_89]. They are all
legal concepts and apply to different aspects of software.
Trade secret protection is for the “know-how” that is embodied in software. Know-how in this
context is substantial and secret information that is proprietary and leads to a commercial
advantage. This becomes a problem when software is transferred to others, as is the case with
inter-corporation reuse. In this case the reuser is obliged to sign a nondisclosure agreement
before the components are delivered. If, despite signing a nondisclosure agreement, the reuser
does not keep the information confidential, damages may be claimed. However, others cannot
Benefits and risks of using componentware Chapter 4
• Patent Protection
Patents are granted for technical inventions that are new and involve inventive steps. The
decision whether something is patentable is often difficult and requires legal advice. For
example, patents are granted for processes or methods that describe how products work. A
computer is a product and an algorithm is such a process [Kar_95].
• Copyright Protection
Copyright protection is the most common form of protection for software. It covers the
software itself but not any underlying ideas and principles, which may be protected by
patents. Copyright owners hold the right to reproduce their software, to reuse, maintain and
adapt it, to make backup copies, and to authorize third parties to perform such activities.
Buyers of copyright protected software are allowed to make backup copies and to study the
software, especially to get information about interoperability, unless this is provided by other
means [Kar_95].
In the context of software reuse, questions about responsibilities and liabilities have to be
addressed. Especially for reuse across company boundaries, questions about a guarantee that
the software works become important. Who will fix it in case it does not work? Who is liable
in case the reused component malfunctions? So far, software is usually reused at one’s own
risk. This is especially true if the reused software is in the public domain. It is the
responsibility of the reuser to check whether reused components fulfill quality standards and
meet specifications. Careful testing of software before it is reused may also be important in
this context. If software to be reused is purchased, such issues should be addressed in the
purchase agreement [Mar_94].
A main distinction has to be made whether reused software has been modified in a new
system. In case of modification by the reuser, the reuser bears the primary liability. This is
similar to the situation when vendor-supplied hardware components are integrated into one’s
system.
Economic issues
Costs associated with software reuse must be justified by the expected benefits; i.e., there
must be sufficient return on investment. The following questions have to be answered
[Coo_94]:
The reuse process is an economic model of supply and demand. The model includes
producers, consumers and distribution mechanism. How much procedures are able to transfer
depends on how well their products match what the consumers’ need. The following factors
affect this [Cco_94]:
Costs incurred by a project creating reusable components must be recovered from the reusers
of those components [Fis_94].
Benefits and risks of using componentware Chapter 4
Initial Investments
Initial investments are needed in order to install a reuse program. These investments include
costs that do not directly support the completion of a company’s primary development goals.
Instead, money is invested to make components of this development effort more reusable. The
completion of maintenance investments is the starting point of reuse investments.
Separating these costs may be difficult. Making software maintainable is often an integral part
of the development process, whereas making its components reusable is not. However,
maintenance will also benefit from money being spent for software reuse. The reuse benefit
can be calculated by comparing costs for activities done with reuse and those done without
reuse, e.g., comparing the costs developing a software system from scratch to the costs of
developing this software system utilizing reusable components from repository. Reuse
investments are cost effective when they are smaller than the sum of all reuse benefits
[Bbr_91]. The benefits can only be estimated at the time the investments have to be made. If
early estimations indicate that benefits will be small, then only limited investments should be
made.
Reuse Effectiveness
Making reuse cost-effective can be accomplished by increasing the level of reuse, by reducing
the average cost of reuse, and by reducing investments to achieve reuse benefits [Bbr_91].
Early in the development phase the merit of investing in certain components must be
identified and their reuse potential must be determined. Buying components from the
commercial software market may be taken into consideration. Even if the initial cost is higher,
it might turn out that in the long run a commercial product might prove more effective if it is
well documented, generalized and of high quality.
Reuse effectiveness can be improved by reducing reuse costs and reuse investments. Reuse
cost can be reduced by making components easy to find, adapt and integrate into new
systems. Investments can be reduced by accurately predicting future needs.
Résumé. As software companies increase their commitment to reuse, they will pass from ad-
hoc reuse with application groups only through domain-based reuse with domain groups and
application groups. Adopting domain-based reuse requires sufficient company size to
maintain specialized groups. Component groups are responsible for developing reusable
components. Domain groups are also responsible for the development of reusable
components; in addition, they have to gain knowledge about their specific domain.
Application groups are obligated to develop applications by using components created by
these specialized groups. These sub-areas, component engineering (design for component),
application engineering (design with component) and domain engineering (design for
components in a certain domain) are described in next chapter.
Benefits and risks of using componentware Chapter 4
Component-based software engineering and its influences Chapter 5
“Software Engineering: The practical application of scientific knowledge in the design and
construction of computer programs and the associated documentation required to develop,
operate, and maintain them.” [Boe_79]
“Software Engineering is concerned with building software systems which are larger than
would normally be tackled by single individual, uses engineering principles in the
development of these systems and is made up of both technical and non-technical aspects.”
There are major difference between the production of larger software systems and the
production of small software systems. Producing larger systems bears similarities to the
production of other technical products. The major problems are:
• Definition of requirements
• Mastering complexity
• Decomposition of a system into subsystems
• Specification of interfaces between subsystems
• Reusability of components
• Modifiability and extensibility
• Portability and adaptability to other hardware platforms
• Project organization, especially for divided-labor system development
Commonsense alone cannot solve all these problems. Instead, it is necessary to scientifically
study the whole complex in order to determine the prerequisites for methods and tools to
support software production. The field of software engineering thus needs to provides
methods, tools, standards and aids that enable us to manage the technical and organizational
problems that arise in the production of software. The goals of software engineering can be
described as follows [Gli_96]:
We naturally apply this basic idea of systems engineering to our approach to the development
of software. As with projects, we divide software projects into individual phase. These phases
collectively and their chronological sequence are termed the software life cycle. A Software
Life-Cycle is the period of time beginning with a concept for a software product and ending
whenever the software in no longer available for use. A Software Life-Cycle Model
represents the activities, their inputs and outputs (documents, tables, measurements) and their
interactions during the life-cycle.
The waterfall model was first put forward by Royce [Roy_70]. A version of the model
appears as figure 5.1. In its original form, the waterfall model describe a sequence of activities
in a software life-cycle that begin with concept exploration and concluded with maintenance
and eventual replacement. Concept exploration and requirements focus on what we know
about the basic features of the solution to a problem. This means identifying and describing
the basic activities and attributes of a system. The results of each waterfall activity provide
feedback to earlier phases. Once the solution to a problem has been worked out, software
developers shift their attention to determining how the system is put together so that it
functions correctly and has required qualities. In the final stages of the waterfall, the focus is
on the operation of the system. Each of the activities in the waterfall provides feedback to
developers responsible for earlier activities. Ideally, this feedback provides impetus for the
improvement and evolution of the software. Notice that the waterfall model caters to what is
known as forward engineering of software products. This means starting with a high-level
conceptual model for a system. After a description of the conceptual construct for a system
has been worked out, the software process continues with the design, implementation, and
testing of a physical model of the system.
Component-based software engineering and its influences Chapter 5
ents
rem
requi
n
icatio
specif
ign
des
ntation
l eme
imp
n
gratio
inte
n,
e r ationce
op tena
n
mai
A principal advantage of the waterfall model is that it provides for baseline management,
which identifies a fixed set of documents produced as a result of each phase in the life-cycle.
Except for feedback, the waterfall model does not make it clear how one might go about
discovering the intentions of designers of a legacy systems. A legacy system is a collection of
hardware and software that has accumulated over the years. The process of identifying and
analyzing the components and relationships between components of a legacy system is called
reverse engineering. The waterfall model is lacking in prescribing how one reverse engineers
an existing system. Another drawback in the waterfall model is that a client must wait until
the installation and checkout phase to see how a system works. The first time that the client
sees a working product is only after the entire produce has been coded. Small wonder that
software developers live in fear of the sentence “I know this is what I asked for, but it isn’t
really what I wanted.”
The development of a large, complex system requires considerable time and effort. Absent
from the waterfall model are the notions of prototyping and incremental development. A
prototype is an executable model that accurately reflects a subset of the properties of a system
being developed. Prototypes make it possible for clients and developers to see how a software
increment works in the early stages of a software process. It is also the case that prototypes
aid the understanding of a system. Making changes to prototypes of software increments is
easier than trying to change a complete system.
To remedy the weaknesses of the waterfall model, the evolutionary and prototyping life-cycle
models were introduced. Software is built, not written. That is to say, software is constructed
step by step, in the same way that a building is constructed. While a software product is in the
process of being developed, each step adds to what has gong before. One day the design is
extend; the next day another module is coded. The construction of the complete product
proceeds incrementally and iteratively in this way until completion.
The realization that software is engineered incrementally has led to the development of a
model that exploits this aspect of software development, the so-called incremental model
shown in Figure 5.2. The product is designed, implemented, integrated, and tested as a series
me
lop
D eve
of incremental builds, where a build consists of code pieces from various modules interacting
to provide a specific functional capability.
ce
t s n t e nan
e n i
u irem Ma
re q
on
i f i cati
c
spe
g
nin
plan
e
i t e ctur
arch gn
i
des
:
b uild
h
eac
Forom d
irlatetino-n
f
Pergn, idnetetagem e nt.
i
desn, andim pl clie
o
o e t
r
tati Deliv
.
test
mode
ons
rati
ope
For example, if the product is to control a nuclear submarine, then the navigation system
could constitute a build, as could the weapons control system. In an operating system,
scheduler could be a build, and so could the file management system. At each stage of the
incremental model a new build is coded and then integrated into the structure that is tested as
a whole. The process stops when the product achieves target functionality, that is, when the
product satisfies its specifications. The developer is free to break up the target product into
builds as he or she sees fit, subject only to the constraint that as each build is integrated into
the existing software, the resulting product must be testable. If the product is broken into too
many builds, then at each stage considerable time is spent in the integration testing of only a
small amount of additional functionality.
In contrast to waterfall model, the incremental model does deliver an operational quality
product at each stage, but one that satisfies only a subset of the client’s requirements. With the
incremental model, portions of the total product might be available within weeks, whereas the
client generally waits months or years to receive a product built using the waterfall model.
The gradual introduction of the product via the incremental model provides time for the client
to adjust to the new product. A change is an integral part of every growing organization; and
because a software product is a model of reality, the need for change is also an integral part of
delivered software. Change and adaptation are natural to the incremental model.
A difficulty with the incremental model is that each additional build somehow has to be
incorporated into the exiting structure without destroying what has been built to date. The
incremental model can too easily degenerate into the build-and-fix approach. Control of the
process as a whole can be lost, and the resulting product, instead of being open-ended,
becomes a maintainer’s nightmare.
Component-based software engineering and its influences Chapter 5
The first generation of methods includes examples such as the Object Modeling Technique
(OMT) developed by a team led by James Rumbaugh, the method developed by Grady
Booch, OOA/OOD/OOP developed by Peter Coad and Edward Yourdon, the method
developed by Sally Shlaer and Steven Mellor and the Object-Oriented Software Engineering
(OOSE) method created by Ivar Jacobson and his team. These all have their own distinct
notations supported by a set of process descriptions, although many of the underlying ideas
are common.
In addition to the methods named above, there are also fifteen to twenty other methods that
have been proposed, usually accompanied by one or more books, some with fully fledged
system development environments – usually called CASE (Computer Aided Software
Engineering) environments. One result of this proliferation of methods has been a desire to
provide a standardized modeling language for object-oriented systems, two of which have
been proposed:
• The Unified Modeling Language (UML) has been developed by Booch, Rumbaugh and
Jacobson (the 'three amigos'!) and is now being standardized by an Object Management
Group (OMG) task force.
• The OPEN Modeling Language (OML) developed by Don Firesmith, Brian Henderson-
Sellers and Ian Graham has been released as a de facto standard.
Both UML and OML are notations for modeling object-oriented systems, the process
descriptions are separate.
The description of any of these methods is outside the scope of this work. As an
representative example, Booch Method will be introduced here. It is important to remember
that there are established object-oriented analysis and design methods beyond the lower level
programming concepts.
In his earlier text Software Engineering with Ada [Boo_87], Booch suggests the following
steps for analyzing a system in preparation for designing a solution in an object-oriented
manner:
These steps are based on the earlier work of Abbott [Abb_83]. The problem is defined in a
concise, informal textual description, then information on the objects and operations
represented in the system can be obtained from this description. Objects are represented by
nouns, and operations by verbs. Pressman [Pre_87] notes that the first two steps are actually
performed during the software requirements analysis stage of development, rather than the
design. Booch [Boo_86], however, had already noted that object- oriented development, as he
described it, is not a complete lifecycle method, but rather, it concentrates on the design and
implementation stages.
In his later work [Boo_91], Booch suggests the following order of events for the
formalization of the strategy:
Booch builds upon these principles in expounding his recommended method. He stresses that
this is not just a simple sequence of steps to be followed, but rather an iterative and
incremental development through refinement of complementary (logical and physical) views
of a system. He states that "the process of object-oriented design starts with the discovery of
the classes and objects that form the vocabulary of our problem domain; it stops whenever we
find that there are no new primitive abstractions and mechanisms or when the classes and
objects we have already discovered may be implemented by composing them from existing
reusable software components."
Identifying the classes and objects involves finding key abstractions in the problem space and
important mechanisms that offer the dynamic behavior over several such objects. These key
abstractions are found by studying the terminology of the problem domain.
Identifying the semantics involves establishing the meanings of the classes and objects
identified in the previous stage. The developer should view the objects from the outside,
define the object protocol and investigate how each object may be used by other objects.
Identifying relationships extends the previous work to include the relationships between
classes and objects and to identify how these interact with each other. Associations such as
inheritance, instantiation and uses between the classes are defined, as are the static and
dynamic semantics of the mechanisms between the objects. The visibility between classes and
objects is also decided upon.
Implementing classes and objects involves delving into the classes and objects and
determining how to implement them in the chosen programming language. This is also the
step where components are used, and the classes and objects are structured into modules.
In the design method, Booch emphasizes the distinction between a 'logical view' of a system,
in terms of classes and objects, and a 'physical view' of a system in terms of modules and
processes. He also makes a distinction between static and dynamic models of the system. The
method he proposes is, however, geared more towards static system descriptions, with less
support for dynamic descriptions.
One of the major strength's of Booch's method is the rich notation available. There are
diagrammatic notations for producing:
The notations for class and object modeling use annotations or variant symbols (e.g. different
kinds of arrow) to convey detailed information. Booch suggests that a subset of the notations
can be used in the earlier stages of design, with the detail being filled in later. There is also a
textual form for each notation, consisting of templates for documenting each major construct.
The notations are defined in terms of a large repertoire of symbols, but there seems to be no
real definition of syntax or static semantics, only informally in the text accompanying the
symbol overview.
Walker [Wal_92] has this to say about Booch's object-oriented approach: "One possible
problem is undoubtedly the lack of significant partitioning and layering of diagrams in the
Booch method. Booch employs a variety of diagrams for different purposes (e.g. class
diagrams, state transition diagrams, object relationship/visibility and message synchronization
diagrams etc.), but within some diagrams, he appears to attempt to cover too much of the
system (at least, this appears to be the case in the examples and cases he uses)." He then goes
on to say: "Perhaps the criticism of Booch's strategy can be encapsulated in the phrase breadth
rather than depth. Booch's diagram notation has sacrificed detail or depth for breadth; this can
be useful at the early stages of the design process, but needs to be capable of being reworked
to increase the level of detail. In part, this is performed by the textual templates, but they are
not structured so as to relate detail in a helpful way to the diagrams; indeed, in some respects,
they also lack essential information for the resolution of fine structure within the application."
In terms of designing with reuse, Booch is a little more vague. He states that "Actively looking
for reusable software components that are relevant to a new system is a very important
activity in any development." He goes on to say that "If we can find a component that is
relevant to our to our problem, that component becomes a primitive abstraction with which
we can compose the system; thus we are left with a smaller problem to solve." However, the
details are hidden in the examples given, and no overall recommendations are given. Booch
also advocates the use of application generators where applicable.
Programming (OOP) has not brought many benefits since they have not provided
interoperability of components at the binary/runtime level. OOP has some weaknesses in that
it does not always produce reusable software and is not suitable for a large project and does
not support the complete encapsulation of classes due to the inheritance of subclasses. As a
evolutionary method of OOP, Component-Based Software Engineering (CBSE) or
Component-Based Development (CBD) has recently been hot issues for the Object-Oriented
community and reuse community, and the component market is also growing rapidly.
As we earlier discussed, software reuse is generally considered as one of the most effective
ways of increasing productivity and improving quality of software. To make software reuse
happen, however, there should be a change in the way we develop software: software must be
developed for reuse and with reuse, and there must be a paradigm shift from the notion of
specific application "development" to that of "integration/composition." Component-based
software engineering (CBSE) is an emerging software engineering paradigm in which
applications are developed by integrating (wiring) existing components. Here, components
refer to any units of reuse or integration, including computational (i.e., functional)
components, interface components, communication components, and architectures.
As we can learn from car industry, we build component-based software systems as following
as cars are built. In principle, we build a car using pre-existing car components like motor,
wheels, seats etc. There are two very different processes: the process which single car
components are built according to some industry production standards; and the process which
cars are assembled using those components. Similarly, we differentiate two different
processes regarding component-based technology (Figure 5.3).
ign
Des ent m
on yste
mp nS
-For -Co atio
plic
Ap
on ent
Comp
on ent
Design m
-Fro -Comp
Sc ript
Glue ( uage)
-lang
As at begin of this chapter pointed out, we divide the software development process into
several phases, in order to control the complexity and to improve the manageability of
software projects. The development of a componentware is actually a process of developing
software, and therefore, can also be divided into such sub-phases, namely, component
specification, component design, component implementation, component testing, and
component maintenance.
Component Specification
• Functional requirements
Services that are expected by end-users.
• Nonfunctional requirements
Constraints under which software has to operate
Component Design
After component requirements have been analyzed and specified, a design has to be made.
Component design is an iterative process and involves describing a component at different
levels of abstraction. Design includes various activities:
Component-based software engineering and its influences Chapter 5
Top-Down design is typical for components being built from scratch. Tasks are decomposed
into subtasks until these can easily be formulated as algorithms. Bottom-Up design proceeds
in the opposite direction. Fundamental components are defined first and used to realize the
next level of abstraction. Each level comprises what is called an abstract machine. Bottom-Up
design is essential for the reuse of existing components.
Good design is crucial for the quality of a software component. There is no exact definition of
what a good design is, but good designs are considered to have the following characteristics
[Som_96]:
Various categories of design methods exist, for example, function-oriented (like stepwise
refinement), data-oriented (like Jackson Method) and object-oriented methods as proposed by
Booch and Rumbaugh.
Component Implementation
Implementation is the process of transforming a design into an executable form. For software
systems this typically means coding in a certain programming language. According to our
definition, software components can have a variety of forms. They can be implemented in a
programming language or be composed of components of any kind.
We refrain from dealing with implementation in greater detail. This typically comprises
subjects like choice of programming language, choice of names, programming style,
comments, portability considerations, etc. These issues lose importance for systems being
composed of components. They have to be considered, however, in order to implement a
component in a certain programming language.
Component Testing
• Specification test. Specification tests check for the completeness, clarity, consistency and
feasibility of a component specification. This could be done together with potential
component users.
Component-based software engineering and its influences Chapter 5
• Integration test. Composing tested components can reveal new kinds of errors that stem
from the interaction of components. Integration tests are applied to sub-systems or
components being composed of lower-level components.
• Acceptance test. The development of software products ends with an acceptance test
where real operating conditions are used. This may not be possible for software
components where potential reuse candidates might not even be known at the time.
• Static/dynamic testing. Static testing involves activities to find errors via static and
semantic analyses. For dynamic tests components have to be executed or simulated.
• Black-Box/White-Box testing. Black-Box tests involve input/output relationships of
components. White-Box tests consider the inner structures of components as well.
• Top-down/Bottom-Up testing. In top-down testing the main components are tested first by
using stubs for components that are not yet available. In bottom-up testing basic
components are tested first, followed by higher-level components that rely on lower-level
components.
With software component, software quality can be increased and testing efforts can be
decreased. A component developer will do any kinds of tests that seem appropriate to
guarantee a component’s quality. The component user should be able to trust a component’s
quality. Dynamic black-box tests are sufficient on the component user’s side. For composition
of application systems from components, bottom-up tests are suitable in most situations.
Component Maintenance
Component maintenance is the modification of a software component after its first delivery.
Such modifications include error corrections, performance or other improvements,
functionality extensions, or adaptations to changed environments.
Component maintenance is by far more than just fixing bugs. Maintenance activities fall into
the following categories:
The cost of maintenance has been steadily increasing over the past decades. Most companies
spend by far more than 50 percent of their software life-cycle budget on maintenance. This
causes a dramatic decrease in software productivity. Maintenance costs are related to both
technical and non-technical factors. Technical factors include component dependencies,
programming languages, quality of documentation, etc. Dependencies on the external
environment (e.g., taxation changes), system lifetime, and staff stability are examples of non-
technical factors influencing maintenance costs.
In the traditional reuse approach, developers are encouraged to look for needed components
after most of the design work has been done. Rather than waiting until the design is done,
software products need to be designed around available software components. We
differentiate therefore development with components and Component-driven development.
ign e
Dietsectur
arch
cify ts
Sppeonen
com
rch ts
Sepaonen
com
pt ts
Apdoanen
com
te
n t e graents
I pon
com
• Component-driven Development:
In Component-driven development the system specification and the architectural design
are already influenced by available software components. The design is based on available
components and, compared to development with components, results in a higher degree of
reuse (Figure 5.5).
Component-based software engineering and its influences Chapter 5
tem
t e sys n
a
Cre ificatio
c
spe
rch ts
Sepaonen
com
tem
f y sys
di n
Mo ificatio
c
spe
ign e
Dietsectur
arch
rch ts
Sepaonen
com
cify ts
Sppeonen
com
pt ts
Apdoanen
com
te
gra ts
Intpeonen
com
For effective use of components, it must be easier to find components than to develop
them from scratch. Finding suitable components does not mean finding exactly what is
needed. Locating similar components can be sufficient.
After components have been found, they must be understood in order to reuse them.
Finding and understanding are related to selecting a component for reuse requires
knowing what the component does. Understanding becomes even more important when
die component has to be modified. Adequate documentation is significant for this step.
Building a software system out of a set of unmodified components is the ideal scenario.
Typically, at least some of the components have to be adapted to specific needs of the
particular software system to be built. Components can be modified in various ways, e.g.,
by changing internals or by adding new features.
Once a component provides the required functionality, it has to be incorporated into the
software system. The goal is to maximize reuse and to minimize basic development
efforts. However, typically, existing components will not suffice to build new systems. At
least a few components will have to be built from scratch.
In many cases a component does not perfectly fit the required needs, and modifications
are required. A good understanding of a component is essential to perform this task. The
means of possible modification plays a role in the evaluation process and influences the
selection of a component from possible candidates. At this point the development of a
new component may turn out to be better than modification of an existing one.
Component-based software engineering and its influences Chapter 5
• Domain Orientation: Software reuse may be the most effective ways of increasing
productivity and reducing maintenance as well as development cost of software. To
achieve successful software reuse, commonalities of related systems must be discovered
and represented in a form that can be exploited in developing similar systems. Domain
orientation is one such approach. It attempts to discover commonalities of systems in an
application or a technical area (i.e., a domain) and then develop models or components
that can be used in developing systems in the domain. This approach will help evolving an
application as well as developing a family of applications. Although domain orientation is
believed to be the key element in achieving successful CBSE, most domain-oriented
engineering technologies are still in their infant stage. There are many technical issues that
must be resolved before we can mature these technologies.
- on ent
n tceadtion mp nt
i e
OArppl i Co
Tas
k p one t
l C om p o nen
na om
ain
-
u n ctio ogy C
o m d F nol
D nte
e T ech
Ori ain
Dom t cat
ion
nm t
en
m uni
i r o n om a
Env poneace, i n g/C Dat ueue,
eric m r
Cor Inte er)
f
Sha
r eq
sag ization
)
Gen e v iessm
ent ( s ice dri
U aMn )n
ech(,yRnPchCro
on Dev M
mp ion BAS
Co e g rat , COR
Intx Pipe
i
(Un
Figure 5.7 illustrates a flexible, component-oriented process model from Bergner et al.
[Ber_99]. It shows the different tasks of a componentware development process. Each of
these tasks produces results. Thus, a process model for componentware contains a hierarchical
task structure resp. result structure. Note that the presented concepts apply to Component
Users, i.e. the developers of component-oriented systems, as well as for Component Vendors
shipping components to Component Users.