Chapter 1: Overview | |
The development of a software system is usually just a part of finding a solution to a larger problem. The larger problem may entail the development of an overall system involving software, hardware, procedures, and organizations.
In this book, we concentrate on the software side. We do not address associated issues such as constructing the proper hardware platform and reorganizing institutional procedures that use the software to improve overall operations. We further limit ourselves to the ``middle'' phases of OO system development. We discuss the initial collection of system requirements and scheduling of efforts only to the extent to which they impact analysis. Similarly, we discuss situation-dependent implementation matters such as programming in particular languages, porting to different systems, and performing release management only with respect to general design issues. Also, while we devote considerable attention to the process of OO development, we do not often address the management of this or any software development process. We urge readers to consult Humphrey [8], among other sources, for such guidance.
We cannot however, ignore the context of a software system. The context of any system is simply that part of the ``world'' with which it directly interacts. In order to describe the behavior of a target system, we have to describe relevant parts of the immediate context forming the boundary of the system. Consequently, one may argue that the apparatus that we present in this book could be used for modeling nonsoftware aspects as well. We do not deny potential wider applicability, but we have no claims in that direction.
We assume that the American Bank (AB) has partly decentralized account management. Every branch office has equipment to maintain the accounts of its clients. All equipment is networked together. Each ATM is associated and connected with the equipment of a particular branch office. Clients can have checking, savings and line of credit accounts, all conveniently interconnected. Clients can obtain cash out of any of their accounts. A client with a personal identification number (PIN) can use an ATM to transfer funds among attached accounts. Daemons can be set up that monitor balance levels and trigger automatic fund transfers when specifiable conditions are met and/or that initiate transfers periodically. Automatic periodic transfers to third party accounts can be set up as well.
We will expand on these requirements as necessary. For presentation reasons, we often revise descriptions from chapter to chapter. Our examples represent only small fragments of any actual system.
Objects have complex historical roots. On the declarative side, they somewhat resemble frames, introduced in artificial intelligence (AI) by Marvin Minsky [10] around 1975. Frames were proposed in the context of knowledge representation to represent knowledge units that are larger than the constants, terms, and expressions offered by logic. A frame represents a concept in multiple ways. There is a descriptive as well as a behavioral component. A frame of a restaurant would have as a descriptive component its prototypical features -- being a business, having a location, employing waiters, and maintaining seating arrangements. The behavioral component would have scripts. For example, a customer script outlines stereotypical events that involve visiting a restaurant.
Objects and frames share the property that they bring descriptive and behavioral features closely together. This shared feature, phrased from the programming angle, means that the storage structures and the procedural components that operate on them are tightly coupled. The responsibilities of frames go beyond those of objects. Frames are supposed to support complex cognitive operations including reasoning, planning, natural language understanding and generation. In contrast, objects for software development are most often used for realizing better understood operations.
On the programming side, the Simula [3] programming language is another, even older, historical root of objects. Unsurprisingly, Simula was aimed at supporting simulation activities. Procedures could be attached to a type (a class in Simula's terminology) to represent the behavior of an instance. Simula supported parallelism , in the approximation of coroutines , allowing for many interacting entities in a simulation.
Simula objects share the close coupling of data and procedures. The concurrency in Simula was lost in Smalltalk , Eiffel , Objective-C , C++ , and other popular OO programming languages. However, parallelism has reentered the OO paradigm via OO analysis methods and distributed designs. Modeling reality with ``active'' objects requires giving them a large degree of autonomy.
The notion of whether objects have a parallel connotation or not is currently a major difference between OO analysis and OO programming. Since we expect OO programming languages to evolve to support the implementation of distributed, parallel systems, we expect this difference to decrease. The parallel OO paradigm is well positioned to meet these upcoming demands.
Like ``system'', ``software'', ``analysis'', and ``design'', the term ``object'' evades simplistic definition. A typical dictionary definition reads:
Samplings from the OO literature include:
Our own working definition will be refined throughout this book. We define an object as a conceptual entity that:
The structured analysis (SA) paradigm [15] is rooted in third generation programming languages including Algol , Fortran , and COBOL . The procedure and function constructs in these languages provide for a powerful abstraction mechanism. Complex behavior can be composed out of or decomposed into simpler units. The block structure of Algol-like languages provides syntactic support for arbitrary many layers. Applied to the development of systems, this abstraction mechanism gives prominence to behavioral characterization. Behavior is repeatedly decomposed into subcomponents until plausibly implementable behavioral units are obtained.
The abandonment of sequential control flow by SA was a major breakthrough. Procedure invocations have been generalized into descriptions of interacting processes. The ``glue'' between the processes are data flows, the generalization of data that is passed around in procedure invocations. Processes represent the inherent parallelism of reality. At the same time, the use of processes produces a mapping problem. One has to transform a high level, intrinsically parallel description into an implementation that is usually sequential. As we will see, the OO paradigm faces the same mapping problem.
The starting point for process modeling resides in the required behavior of the desired system. This makes SA a predominantly top-down method. High level process descriptions are consequently target system specific, and thus unlikely to be reusable for even similar systems. As a result, a description (and a subsequent design and implementation) is obtained that is by and large custom fit for the task at hand.
OO software development addresses the disadvantage of custom fitting a solution to a problem. At all levels of the development process, solution components can be formulated that generalize beyond the local needs and as such become candidates for reuse (provided we are able to manage these components).
Other aspects of OO development are available to control the complexity of a large system. An object maintains its own state. A history-dependent function or procedure can be realized much more cleanly and more independently of its run-time environment than in procedural languages. In addition, inheritance provides for an abstraction mechanism that permits factoring out redundancies.
Are the applicability ranges of the object-oriented paradigm and the structured paradigm different? If so, how are they related? Is one contained in the other? Can we describe their ranges?
As yet there is not enough evidence to claim that the applicability ranges are different, although OO may have an edge for distributed systems. Structured analysis thrives on process decomposition and data flows. Can we identify a task domain where process decomposition is not the right thing to do, but where objects can be easily recognized? Conversely, can we identify a task where we do not recognize objects, but where process decomposition is natural? Both cases seem unlikely.
Processes and objects go hand in hand when we see them as emphasizing the dynamic versus the static view of an underlying ``behaving'' substratum. The two paradigms differ in the sequence in which attention is given to the dynamic and static dimensions. Dynamics are emphasized in the structured paradigm and statics are emphasized in the OO paradigm. As a corollary, top-down decomposition is a strength for the SA approach, while the grouping of declarative commonalities via inheritance is a strength for the OO approach.
The software development community has a large investment in structured analysis and structured design (SD). The question has been raised repeatedly whether one can mix and match components from the structured development process with components of the OO development process. For instance, whether the combination of SA + SD + OOP or SA + OOD + OOP is a viable route.
Experts at two recent panels1 denied the viability of these combinations (but see Ward [13] for a dissenting opinion). A key problem resides in the data dictionaries produced by structured analysis. One cannot derive generic objects from them. Inheritance cannot be retrofitted. Also, the behavior of any given object is listed ``all over the place'' in data flow diagrams.
1Footnote :
panels at OOPSLA/ECOOP '90 and OOPSLA '91.
Consequently and unfortunately, we cannot blindly leverage SA and SD methods and tools. However, OO analysis methods exist that do (partially) rely on SA to describe object behavior; see [6] for a comparative study.
Within a given paradigm, one may follow a particular method2. A method consists of:
2Footnote :
We use the word method, not methodology. The primary meaning of methodology is ``the study of methods'' which is the business of philosophers. The secondary meaning of methodology is method. Since that is a shorter word we refrain from joining the methodology crowd. (Similarly, we prefer using technique over technology.)
This book does not introduce yet another new method for OO development. We instead attempt to integrate methods representative of the OO paradigm. Our OO analysis notation is just borrowed from multiple sources. Still we have given it a name, OAN (Our Analysis Notation), for easy referencing. In part II, we introduce ODL (Our Design Language), a language with similarly mixed origins. Summaries of each are presented in the Appendix 27. When necessary to distinguish our views from those of others, we will refer to these simply as ``our method'' ( OM).
No author in the area of software development has resisted denouncing the waterfall model . Everyone agrees that insights obtained downstream may change decisions made upstream and thus violate a simple sequential development algorithm. The notion of a development process in which one can backtrack at each point to any previous point has led to the fountain metaphor (with, we assume, the requirements at the bottom and the target system at the top).
Whether the development process has few feedback loops (the waterfall model) or many (the fountain model) depends on several factors. The clarity of the initial requirements is an obvious factor. The less we know initially about the desired target system, the more we have to learn along the way and the more we will change our minds, leading to backtracking.
Another factor might be the integration level of tools that support the development process. A highly integrated development environment encourages ``wild'' explorations, leading to more backtracking. On the other hand without tool support, we may be forced to think more deeply at each stage before moving on because backtracking may become too costly. The development style of team members may be a factor as well.
It has been said that the object-oriented paradigm is changing the classic distinctions between analysis, design and implementation. In particular, it is suggested that the differences between these phases is decreasing, that the phases blur into each other. People claim that the OO paradigm turns every programmer into a designer, and every designer into an analyst. We are willing to go only part way with this view. There is empirical evidence from projects in which objects identified in the requirements phase carried all the way through into the implementation (see [5]). We will see as well that notions and notations used in analysis and design are similar, lending more support for this thesis.
On the other hand, intrinsic differences among phases cannot be forgotten. Analysis aims at clarifying what the task is all about and does not go into any problem solving activity. In contrast, design and implementation take the task specification as a given and then work out the details of the solution. The analyst talks to the customer and subsequently (modulo fountain iterations) delivers the result to the designer. The designer ``talks'', via the implementor, with hardware that will ultimately execute the design. In a similar vein we do not want to blur the difference between design and implementation. Contemporary OO programming languages have limitations and idiosyncrasies that do not make them optimal thinking media for many design tasks.
It is, in our opinion, misleading to suggest that phase differences disappear in the OO paradigm. Objects in the analysis realm differ significantly from objects in the implementation phase. An analysis object is independent and autonomous. However, an object in an OO programming language usually shares a single thread of control with many or all other objects. Hence, the design phase plays a crucial role in bridging these different computational object models.
Prototyping3 and exploratory programming are common parts of OO analysis, design and implementation activities. Prototyping can play a role when aspects of a target system cannot be described due to lack of insight. Often enough, people can easily decide what they do not want, but they cannot describe beyond some vague indications what is to be produced.
3Footnote :
We avoid the trendy phrase rapid prototyping since no one has yet advocated slow prototyping.
Graphical user interfaces are an example. What makes a particular layout on a screen acceptable? Must a system keep control during human interaction by offering menu choices or should control be relinquished so that a user can provide unstructured input?
These kinds of question are sometimes hard or impossible to answer. Prototyping experimental layouts can help. The situation resembles that of an architect making a few sketches so that a customer can formulate preferences.
As long as the unknown part of the requirements is only a fragment of a system, OO analysis cooperates with prototyping. Exploratory programming is called for when most of the requirements are not well understood. Research projects fall into this category. Programming in artificial intelligence is an example. Problem solving by analogy is particularly murky behavior. Exploratory programming can be a vehicle for validating theories and/or for obtaining better conjectures.
We feel that purely exploratory programming applies to an essentially different set of tasks than the more tractable (although possibly very large) tasks to which the methods described in this book apply. Formulated negatively, the methods in this book may not apply when the development task is too simple or when the task is too hard.
Elucidating functionality is just one of the motivations for prototyping. We have so far used ``prototyping'' primarily in the sense of ``throwaway prototyping'' -- aimed at gathering insights -- in contrast to ``evolutionary prototyping'' -- aimed at implementing a system in stages. A prototyping activity may have both aims but they need not coincide (see [4]). In Part II, we describe a framework for design prototyping that is explicitly evolutionary in nature. Similarly, performance constraints may require empirical evaluation via implementation-level prototyping.
Acceptance of the fountain metaphor as the process model for software development has profound ramifications. Beyond toy tasks, tool support and integration of different tools is essential in enabling backtracking. Of course these tools also need to support versioning, allow for traceability , and cater to team development. These are quite stringent requirements, which are currently not yet satisfied. Various groups are working on the standards to achieve tool control and data integration [11]. Manipulating objects in all phases of the development process should make it easier to construct an integrated development environment. We consider these issues in more detail in Chapter 12 and 15.
Software systems are often components of general systems. This book discusses only object-oriented approaches to developing software systems. The roots of the OO paradigm include AI frames and programming languages including Simula.
The structured paradigm focuses on decomposing behaviors. The OO paradigm focuses on objects, classes, and inheritance. The two paradigms do not mix well. While the OO paradigm tightly integrates the development phases of analysis, design and implementation, intrinsic differences between these phases should not be blurred. OO methods are compatible with prototyping efforts, especially those constructed in order to elucidate otherwise unknown requirement fragments.
Standard non-OO texts include Ward and Mellor's Structured Development for Real-Time Systems [14] and Jackson's Systems Development [9]. OO texts that cover the full life cycle include Booch's Object Oriented Design with Applications [1] and Rumbaugh et al's Object Oriented Modeling and Design [12].
Yearly proceedings are available from the principal OO conferences, OOPSLA (held in the Western hemisphere) and ECOOP (Europe). Both originally focused on programming and programming languages but have more recently broadened their attention to the full life cycle.