Object Oriented Analysis
- analysis = extracting the needs
The problem domain -- complex reality
Communication -- with domain experts
Continual change -- user requirements
Reuse -- of analysis results
slide: Object-Oriented Analysis
Another claim made by proponents of OOP
is that an object-oriented approach enables
a more seamless transition between the respective phases
of the software life-cycle.
If this claim is really met, this would mean
that changing user requirements could be more easily
discussed in terms of the consequences of these changes
for the system,
and if accepted could in principle be more easily
propagated to the successive phases of development.
One of the basic ideas underlying object-oriented
analysis is that the abstractions arrived at
in developing a conceptual model of the problem domain
will remain stable over time.
Hence, rather than focusing on specific functional
requirements, attention should be given to
modeling the problem domain by means of high level abstractions.
Due to the stability of these abstractions, the results
of analysis are likely candidates for reuse.
The reality to be modeled in analysis is usually very complex.
[CY90] mention a number of
principles or mechanisms with which to manage complexity.
These show a great similarity to the abstraction
mechanisms mentioned earlier.
See slide [1-complexity].
Principles for managing complexity
Abstraction -- procedural / data
Encapsulation -- information hiding
Inheritance -- expression of commonality
Message passing -- consistent interface
Organization -- object / attributes
Scale -- components, frameworks
Behavior -- actors, servers, agents
slide: Managing complexity
Personally, I do not feel entirely comfortable
with the characterization of the analysis phase
given by [CY90],
since to my mind
user needs and system requirements
are perhaps more conveniently phrased
in terms of functionality and constraints
than in terms of a model that may
simultaneously act as an architectural sketch of
the system that is to be developed.
However, I do agree with [CY90], and others,
that the products of analysis,
that is the documents describing user needs
and system requirements,
should as far as possible provide a conceptual model
of the domain to which these needs and
requirements are related.
Actually, I do consider the blurring of the distinction
between analysis and design,
and as we will see later, between design and implementation,
as one of the attractive features of an object-oriented
approach.
Analysis methods
The phases of analysis and design
differ primarily in orientation:
during analysis the focus is on aspects of the problem
domain and the goal is to arrive at a description
of that domain to which the user and system requirements
can be related.
On the other hand, the design phase must result
in an architectural model of the system,
for which we can demonstrate that it fulfills the user
needs and the additional requirements expressed
as the result of analysis.
- Functional Decomposition = Functions + Interfaces
- Data Flow Approach = Data Flow + Bubbles
- Information Modeling = Entities + Attributes + Relationships
- Object-Oriented = Objects + Inheritance + Message passing
slide: Analysis methods
[CY90] discuss a number of methods
that are commonly used in analysis
(see slide [sli-1-methods]).
The choice of a particular method will often depend
upon circumstances of a more sociological nature.
For instance, the experience of a team
with a particular method is often a crucial
factor for success.
For this reason, perhaps, an eclectic method
combining the various approaches may
be preferable
(see, for instance, Rumbaugh {\it et al.}, 1991).
However, it is doubtful whether such an approach
will have the same benefits as a purely
object-oriented approach.
See also section [methods].
I will briefly characterize the various methods
mentioned by [CY90]. For a more extensive
description and evaluation the reader is referred
to, for example, [Jones90].
The method of Functional Decomposition
aims at characterizing the steps that must be taken to
reach a particular goal.
These steps may be represented by functions
that may take arguments in order to deal
with data that is shared between the
successive steps of the computation.
In general, one can say that this method
is not very good for data hiding.
Another problem is that non-expert users
may not be familiar with viewing their problem
in terms of computation steps.
Also, the method does not result in descriptions
that are easily amenable to change.
The method indicated as the Data Flow Approach
aims at depicting the information flow
in a particular domain by means of arrows that
represent data and bubbles that represent
processes acting on these data.
Information Modeling
is a method that has become popular primarily
for developing information systems and applications
involving databases.
As a method, it aims at modeling the application domain
in terms of entities, that may have attributes,
and relations between entities.
An object-oriented approach to analysis
is very similar in nature to the information modeling
approach, at least with respect to its aim
of developing a conceptual model of the application domain.
However, in terms of their means, both methods differ
significantly.
The most important distinction between objects,
in the sense of OOP,
and entities, as used in information modeling,
to my mind lies in the capacity of objects
to embody actual behavior, whereas entities
are of a more passive nature.
Discussion
At this stage it is very difficult to draw any
final conclusions with respect to object-oriented
analysis.
Currently methods are proposed that integrate
the various techniques,
such as for example the Object Modeling Technique
(Rumbaugh {\it et al.}, 1991), which integrates information modeling,
data flow analysis and a technique for modeling
the dynamic behavior of objects.
Returning to my initial remarks,
I think we may safely set as the goal
for every method of analysis
to aim at stable abstractions,
that is a conceptual model that is robust
with respect to evolving user requirements.
Also, we may state a preference for methods
which result in models that have a close
correspondence to the concepts and notions
used by the experts operating in the application
domain.
Design
In an object-oriented approach,
the distinction between analysis
and design
is primarily one of emphasis;
emphasis on modeling the reality of
the problem domain versus
emphasis on providing an architectural
model of a system that lends itself
to implementation.
One of the attractive features of such
an approach is the opportunity of a seamless
transition between the respective phases
of the software product in development.
The classical waterfall model can no
longer be considered as appropriate
for such an approach.
An alternative model, the
fountain model, is proposed by [Hend92].
This model allows for a more autonomous
development of software components,
within the constraints of a unifying framework.
The end goal of such a development process
may be viewed as a repository of reusable components.
A similar viewpoint has originally been
proposed by [Cox86] and [Meyer88].
In examining the primary goals of design,
[Meyer88] distinguishes between reusability,
quality and ease of maintenance.
Naturally, reusable software presupposes quality,
hence both quality and maintainability
are important design goals.
See slide [1-design].
Object-Oriented Design
- reuse, quality, maintenance
The software life-cycle
Traditional Object Oriented
Requirements 20 20
Design 30 50
Implementation 35 20
Testing 15 10
slide: Object-oriented design
In [Meyer88] a rough estimate is given of the shift in effort
between the phases of the software life-cycle,
brought about by an object-oriented approach.
Essentially, these figures show an increase
in the effort needed for design.
This is an immediate consequence
of the observation that the development
of reusable code is intrinsically more difficult.
To my mind, there is yet another reason for the extra
effort involved in design.
In practice it appears to be difficult and time
consuming to arrive at the appropriate
abstract data types for a given application.
The implementation of these structures,
on the other hand, is usually straightforward.
This is another indication that the unit of
reuse should perhaps not be small pieces of code, but
rather (the design of) components that fit into
a larger framework.
Software quality
From the perspective of software quality and maintenance,
these mechanisms of encapsulation
and inheritance may be characterized as powerful means
to control the complexity of the code needed to realize a system.
See slide [1-quality].
Software quality
- correctness, robustness, extendibility, reusability, compatibility
Maintenance -- 70\% of costs
Requirements change -- 41.8%
Data format change -- 17.4%
Emergency fixes -- 12.4%
Routine debugging -- 9%
Hardware changes -- 6.2%
Documentation -- 5.5%
Efficiency improvements -- 4%
slide: Software quality
In [Meyer88] it is estimated that maintenance accounts for
of the actual cost of software.
Moreover, adaptive maintenance,
which is the adaptation to changing requirements,
accounts for a disproportionately large part
of the cost.
Of primary importance for maintenance,
in the sense of the correction of errors,
is the principle of locality
supported by encapsulation, data abstraction and hiding.
In contrast, inheritance is a feature that may
interfere with maintenance, since it often breaks
down the protection offered by encapsulation.
However, to cope with changing requirements,
inheritance provides both a convenient and relatively
safe mechanism.
Implementation
In principle, the phase of implementation
follows on from the design phase.
In practice, however,
the products of design may often
only be regarded as
providing a post hoc justification
of the actual system.
As noted, for instance, in [HOB87],
an object-oriented approach may blur
the distinction between design and implementation,
even to the extent of reversing their actual order.
The most important distinction between design
and implementation is hence the level of abstraction
at which the structure of the system is described.
Design is meant to clarify the conceptual
structure of a system,
whereas the implementation must include all
the details needed for the system to run.
Whatever approach is followed, in the end
the design must serve both as a justification
and clarification of the actual implementation.
This role of design is of particular importance in projects
that require long-term maintenance.
Correcting errors or adapting the functionality of
the system on the basis of code alone
is not likely to succeed.
What may help, though, are tools that extract
explanatory information from the code.
See, for example, sections [eiffel-tax] and [pde].
Testing and maintenance
Errors may (and will) occur during the implementation
as well as later when the system is in operation.
Apart from the correction of errors,
other maintenance activities may be required,
as we have seen previously.
In [Knuth92], an amusing account is given of the errors
Knuth detected in the \TeX\ program over a period of time.
These errors range from trivial typos to
errors on an algorithmic level.
See slide [1-errors].
Errors, bugs
\zline{\fbox{ \TeX }}
- [A] -- algorithm awry
- [B] -- blunder
- [C] -- structure debacle
- [F] -- forgotten function
- [L] -- language liability
- [M] -- mismatch between modules
- [R] -- reinforcement of robustness
- [S] -- surprises
- [T] -- a trivial typo
slide: TeX errors and bugs
An interesting and important question is to what extent
an object-oriented approach, and more
specifically an object-oriented implementation
language, is of help
in avoiding and correcting such errors.
The reader is encouraged to make a first guess,
and to verify that guess later.
As an interesting aside, the \TeX\ system has
been implemented in a language system called Web.
The Web system allows one to merge code and explanatory text
in a single document, and to process that document
as either code or text.
In itself, this has nothing to do with object orientation,
but the technique of documentation supported
by the Web system is also suitable
for object-oriented programs.
We will mention a Web-like system for C++
in chapter 11.
Object-oriented language support
Operationally, encapsulation
and inheritance are considered to be the basic mechanisms
underlying the object-oriented approach.
These mechanisms have been realized in a number
of languages.
(See slide [1-languages].
See also chapter 5 for a more complete overview.)
Historically, Smalltalk is often considered to be the
most important object-oriented language.
It has served as an implementation vehicle
for a variety of applications (see, for instance, Pope, 1991).
No doubt, Smalltalk has contributed greatly to the
initial popularity
of the object-oriented approach,
yet its role is being taken over by C++, which
now has the largest community of users.
Smalltalk is a purely object-oriented language,
which means that every entity, including
integers, expressions and classes, is
regarded as an object.
The popularity of the Smalltalk language may be attributed
partly to the Smalltalk environment,
which allows the user to inspect the properties of all
the objects in the system
and which, moreover, contains a large
collection of reusable classes.
Together with the environment, Smalltalk
provides excellent support for fast prototyping.
The language Eiffel, described by [Meyer88],
may also be considered as a pure object-oriented language,
pure in the sense that it provides classes
and inheritance as the main device with which to
structure a program.
The major contribution of Eiffel is
its support for correctness constructs.
These include the possibility to specify
pre- and post-conditions for methods, as well
as to specify a class invariant, that may
be checked before and after each method invocation.
The Eiffel system comes with a number of libraries,
including libraries for graphics and window support,
and a collection of tools for browsing and the extraction
of documentation. See also chapter 11.
The C++ language (Stroustrup, 1991) has a somewhat different history.
It was originally developed as an extension of
C with classes.
A primary design goal of C++ has been to develop
a powerful but efficient language.
In contrast to Smalltalk and Eiffel,
C++ is not a pure object-oriented language;
it is a hybrid language in the sense that it allows us
to use functions in C-style as well as object-oriented
constructs involving classes and inheritance.
Much of the support that comes with Smalltalk
and Eiffel may be acquired for C++ in the form
of third party libraries or toolkits.
A number of these libraries and toolkits
are discussed in chapter 11 and 12.
Currently, a number of research groups
(including my own) are working on extending
C++ with concurrency.
An overview of these efforts and the conceptual
issues involved is given in chapter 6.
Smalltalk -- a radical change in programming
languages
Eiffel -- a language with assertions
C++ -- is much more than a better C
- the benefits of efficiency
DLP -- introduces logic \c{into object orientation}
- development of knowledge-based systems
slide: Object-oriented languages
As the final language in this brief overview,
I wish to mention the distributed logic programming
language DLP (see Eliëns, 1992).
The DLP language combines logic programming
with object-oriented features and parallelism.
I mention it, partly because the development
of this language was my first involvement with
OOP.
And further, because it demonstrates
that other paradigms of programming,
in particular logic programming,
may be fruitfully combined with OOP.
The language DLP provides a high level vehicle
for modeling knowledge-based systems
in an object-oriented way.
A more extensive introduction to the
Smalltalk, Eiffel, C++ and DLP languages is given in the appendix.