Initially, object-oriented software development
was language-driven.
The motivation to adopt an object-oriented approach
came first from the need to cope with increasingly
complex software systems.
Research in object-oriented programming was
primarily concerned with the development
of language mechanisms to support the new approach.
Only recently, has the attention shifted from language
support mechanisms and the pragmatics of program development
to issues of analysis and design.
Research concerning language mechanisms, however, is
still important, for example in the area
of concurrent/distributed programming and
the support of persistent objects. See part II.
Object-Oriented Development
- to manage the complexity of massive software intensive systems
OOD/P -- will be in the 90s what structured programming was in the 70s.
Criterion for decomposition: \fbox{object}
- each object must correspond to an object or concept of the problem domain
Abstractions of the problem space
- model of reality -- promotes an understanding of the system
slide: Object-oriented development
The common denominator in both analysis and design
in an object-oriented approach
may be characterized as a decomposition into objects.
See slide [3-development].
Objects, according to [Booch86], are crisp
entities, that suffer and require actions,
which (must) have a clear relation to concepts
or entities of the problem domain.
Ideally, we have a seamless transition between the phases of analysis, design
and implementation.
Seamless in the sense that the various phases
employ a common object model, that is gradually
refined as the project progresses.
In other words, such a transition presupposes a notion
of objects that may unify the activities in the respective phases.
The central imperative of the object-oriented movement,
namely to provide a model of reality, still betrays
the conception of object-oriented programming as simulation,
as originally expressed by [DaNy66].
The initial motivation underlying this approach is the idea that a natural representation
of the problem domain in a software system may reduce the complexity of
understanding the system implementing a solution.
The presupposition here is that modeling involves the use
of objects to represent the entities in the problem domain.
Assuming the presupposition to hold, our task then reduces to
identifying the right objects and showing that that particular
decomposition is valid with respect to the original problem.
The goal of design may then be stated as arriving at an architectural
structure that adequately reflects the relevant properties of
the problem domain.
The architecture of object-oriented systems
The process of software development has often
been compared to the process of constructing buildings,
usually in the context of defending a traditional software
development method.
The argument comes down to
the statement that it takes a solid plan
and sufficient time to lay the foundations
and erect the building.
The conclusion, generally, is a plea for
a science of software engineering/programming,
or an engineering discipline of software design. See for
example [Gries] or [Potter91] for a similar
argument in defense of formal specification methods.
The line of reasoning exemplified by the building
metaphor is defective in two respects.
Firstly, the presupposition of a rigid ordering in
time is clearly contradicted by the many attractive
old city centers, which have often evolved over time
without a plan.
Secondly, the presupposition of a fixed method
of development is clearly demonstrated to be false
by modern building techniques, employing prefabricated components.
Hence, neither temporal order nor procedures
of construction are as fixed as they at first seem.
The view expressed in the building metaphor
also fails for the software life-cycle.
Both throwaway and incremental prototyping
have come to be accepted as viable methods
for developing software.
Nevertheless, when we speak of design,
we think of some architectural blueprint of the system,
the layout of its structure.
What, we may ask, is the role of the design in
the software life-cycle?
And what is the function of its product,
the design document?
Software Development Process -- transition
- analysis --> design --> implementation
Aspects
- architecture -- {\em components\ifsli{,}{ and} relations}
- method -- guidelines
- process -- management
- design -- software support
Alternative styles
- rapid and evolutionary prototyping
slide: Software development process
In [Jacobs92], a detailed account is given of a method
of object-oriented software engineering
based on elementary architectural notions,
such as (object) components and (use) relations,
and strong convictions with respect to design guidelines
and process management issues.
See slide [3-process].
An explicit distinction is made between the {\em architectural
concepts}, which provide the means with which to construct
various models, the method, which is a bag of guidelines
telling us how to employ the architectural notions, the
process, which details what steps to take to complete
the software life-cycle,
and the tools, which provide the software support
either for the construction of models
or for managing the actual process of software development,
or both.
In [Jacobs92], both the method and issues of process
development are spelled out in great detail,
illustrated by a number of examples.
These issues are clearly important
in actual production environments (business or industrial),
but seem to be dependent
to a large extent on non-technological
factors.
From the perspective of software technology,
we are primarily interested in the architectural
notions underlying the various methods and, to
a lesser extent, in the tool support for
these methods.
Also, apart from the architectural structure per se,
we are interested in what properties a design model must have
in order that
we may verify that a model satisfies its initial requirements.
Perspectives of modeling
Understanding a problem domain may be quite demanding.
Understanding is even more difficult when the
description of the domain is cast in some
representation pertaining to the solution domain.
An object-oriented approach is said to require less
translation from the problem domain to the (software)
solution domain, thus making understanding easier.
Many proponents of an object-oriented approach, however,
seem to be overly optimistic in their conception of
the modeling task.
From an epistemological point of view,
modeling may be regarded as being essentially colored
by the mechanisms that are available to express the model.
Hence, rather than opposing the functional and object-oriented
approach by claiming that an object-oriented
approach aims at modeling reality,
I would prefer to characterize the distinction in
terms of (modeling from) a different
vernacular, a different perspective due to
different modeling mechanisms.
In other words, a model is meant to capture
some salient aspects of a system or problem domain.
Dependent on what features are considered as most
important, different means will be chosen to construct
a model.
Even within the confines of an object-oriented approach, there appear to be
radically different perspectives of the modeling required
in the various phases of the software life-cycle.
Modeling reality -- vernacular
- requirements -- use cases
- analysis -- domain concepts
- design -- system architecture
- implementation -- language support
>
Design model {\em -- system oriented}
- provides a justification of the architecture
slide: Perspectives of modeling
An important contribution of [Jacobs92]
is the notion of use cases
that describe the situations in which a user actually
interacts with the system.
Such a (use case) model is an important constituent of
the requirements document, since it precisely
describes what the system is intended for.
For the purpose of analysis,
it may be helpful
to develop a more encompassing (conceptual) model
of the problem domain.
The advantage of such an approach is that the actual system
may later easily be extended due to the generality
of the underlying analysis model.
In contrast to the model used in analysis,
both the design model and the implementation model are more
solution oriented than domain oriented.
The implementation model is clearly dependent on the available
language support.
Within a traditional life-cycle, the design model may be seen as
a transition from analysis to implementation.
The notion of objects may act as a unifying factor,
relating the concepts described in the analysis document
to the components around which the design model is built.
However, as we have noted, object-oriented development
does not necessarily follow the course
of a traditional software life-cycle.
Alternatively, we may characterize the function of the
design document as a justification of the choices
made in deciding on the final architecture of the system.
This remark holds in so far as an object-oriented approach
is adopted for both design and implementation.
However, see [Hend90] for a variety of combinations of
structured, functional and object-oriented techniques.
Dimensions of modeling
When restricting ourselves to design models,
we may again distinguish between different modeling
perspectives or, which is perhaps more adequate
in this context, dimensions of modeling.
In [Rum91], it is proposed to use three complementary
models for describing the architecture and functionality
of a system.
See slide [3-dimensions].
Dimensions of modeling {\em -- OMT}
- object model -- decomposition into objects
- dynamic model -- intra-object state changes
- functional model -- object interaction (data-flow)
Model of control
- procedure-driven, event-driven, concurrent
slide: The OMT method
The OMT method distinguishes between
an object model, for describing the (static)
structure of object classes and their relations,
a dynamic model, that describes for each object
class the state changes resulting from performing operations,
and a functional model, that describes the interaction
between objects in terms of a data-flow graph.
An important contribution of [Rum91]
is that it identifies a number of commonly used
control models, including procedure-driven
control, event-driven control and concurrent
control.
The choice for a particular control model
may deeply affect the design of the system.
See section [duality] for a further discussion.
The OMT approach may be called a hybrid method
since it employs non object-oriented techniques
for describing intra-object dynamics, namely state-charts,
and a functional approach involving data-flow diagrams,
for describing inter-object communication.
Coherent models
The OMT object model, however,
only captures the static structure of the system.
To model the dynamic and functional aspects, the
object model is augmented with a
dynamic model, which is given by state diagrams,
and a functional model, which is handled
by data flow diagrams.
From a formal point of view this solution is rather
unsatisfactory since, as argued in [Hayes91],
it is hard to establish the consistency of the
combined model, consisting of an object,
dynamic and functional model.
Model criteria -- formal approach
- unambiguous -- single meaning
- abstract -- no unnecessary detail
- consistent -- absence of conflict
slide: Coherent models -- criteria
Consistency checking, or at least the possibility
to do so, is important to increase our belief
in the reliability (and reusability) of a model.
To be able to determine whether
a model is consistent, the model should be
phrased in an unambiguous way, that is, in a notation
with a clear and precise meaning.
See slide [3-coherent].
Also, to make the task of consistency checking manageable,
a model should be as abstract as possible, by leaving
out all irrelevant details.
To establish the consistency of the combined
model, covering structural, functional and dynamic aspects,
the interaction between the various models must be clearly
defined.
Currently, to my knowledge, there is no
completely developed method encompassing the
structural, functional and dynamic aspects
of a system in a manner that is amenable to
a rigorous formal approach.
However, there is an emerging understanding of how to
deal with these various aspects.
Moreover, there are attempts towards a standardization of the notions
employed in the various methods.
See sections [OMG] and [methods].
Functional versus object-oriented development
The functional approach is a relatively well-established
method of software development.
In essence, a functional approach amounts
to decomposing a task into the steps that must
be taken to complete it.
For instance, when describing a compiler in a functional
manner, a first decomposition can be made as follows:
lexical scan parser code generation
Each of these steps can be regarded as transforming
its input to a representation suitable for
the next step, finally resulting in an executable
program.
See slide [3-functional].
Obviously, the method of functional decomposition
lends itself to a structured approach,
since each step (in the example above) may be decomposed
into a number of smaller steps.
Graphically, a functional decomposition
may be pictured as a tree with the elementary
steps as its leaves.
A functional decomposition may be augmented
by a data flow diagram that depicts the nature
of the data transformations effected by each step.
Basically, a data flow diagram is a graph with nodes
labeled by the (intermediate) data representations and edges
that are labeled by the functional components
identified in the function decomposition tree.
Functional development methods
- each module represents a major step in the process
Disadvantages
- no data abstraction / information hiding
- not responsive to changes
- inadequate for natural concurrency
slide: Functional development methods
In contrast, the components that result from an object-oriented approach
do not represent actual steps
toward a solution, but rather may be seen as
(abstract) entities that contribute to the solution
on the basis of their assigned responsibilities.
Correspondingly, the flow of control is far less
regular than in a functional decomposition.
The equivalent of the combined data flow and functional
decomposition diagram for an object-oriented system
is a message-passing diagram depicting the actual
interaction between objects.
This diagram is a graph with objects as nodes,
and edges labeled by requests to execute a method.
In general, this graph will be too complex to
be represented pictorially.
It is possible, however, to divide up an object
interaction graph into meaningful related pieces,
which is the approach taken for Fusion, for example.
See section [Fusion].
Moreover, the complexity of object-interaction
is compensated for by the opportunities for a more
tight definition of the semantics, that is the
responsibilities and obligations, of each (object)
component participating in the computation.
The major drawback of a functional approach,
as observed in [Booch86], is the absence of data abstraction
and information hiding.
Typically, the functional approach is not concerned
with issues of data representation,
although it does allow additional procedural abstractions
to access and modify the data.
However, the functional approach does not in itself
provide any support for a tight coupling between
the functional components and data representations
or the procedural abstractions that are used for the
purpose of information hiding.
Hence, changes in the data representation or
the structure of the algorithm may ripple
across the system in an unforeseen manner.
Object-oriented development -- design for change
Advantages
- improved maintainability
- improved understandability
Support for concurrency {\em -- active objects}
- no modifications needed for concurrency
slide: Support for change
In contrast, object-oriented development is neither
data nor procedure oriented,
but strives to encapsulate both data and procedures
acting on these data in objects.
Instead of a detailed description of the steps
that need to be taken to solve a problem or complete a task,
the required functionality is distributed among the objects
that may later be assembled (in a rather straightforward way)
to actually perform the task.
Perhaps the most important advantage of
encapsulating data and procedures, from the perspective
of design, is that (in many cases)
changes may be kept strictly local
to the classes defining the relevant objects.
See slide [3-OO].
Ideally, object-oriented design is design for change,
in other words the development of an architecture
that is adaptable to changing requirements or changes
in the underlying software and hardware support.
However, to achieve this adaptability generally
requires a non-trivial effort during design,
in order to find stable abstractions
with a well-defined semantics that determines their
role in the system.
Obvious potential spin-offs from the effort to design for change
are improved maintainability
of the system and a better understanding of
its architectural structure.
Another benefit of an object-oriented approach,
mentioned in [Booch86],
is the possibility of introducing concurrency
in a later stage.
Starting from a functional decomposition,
the introduction of concurrency would generally incur a total
restructuring of the algorithm.
With an object-oriented approach, however,
concurrency may be introduced by employing
active objects.
In principle, clients of an object need not be aware
of whether the object is passive, that is merely
responding to messages, or active, which
means that the object in addition to answering messages
has (autonomous) behavior of its own.
However, employing active objects imposes a number of
additional constraints, on an implementation
level but also on a design level.
We will explore these issues in chapter \ref{Distribution and concurrency}.