One of the most difficult obstacles for the beginner in object-oriented techniques is simply getting started: where do the initial objects come from? Given this set it is easier to go on, but how are these first objects identified? This is the first step of object-oriented analysis (OOA) and the most difficult.
Our approach to the question grows out of our experience with customer-centered design.
We believe the system design step is key to getting started on analysis and design of the implementation. Here we show why, and describe the approach we take to system design. We show in some detail how our approach generates an initial object model.
To analyze the underlying issues in the identification of objects in OOA, we will take one example from Rumbaugh: the Electrical Distribution Design System case study in Object-Oriented Modeling and Design (p433). This example is convenient because the book is popular and generally available. Rumbaugh’s approach is careful and ordered, and he makes a point of separating true requirements from design decisions disguised as requirements. We can expect this example to be cleaner than might be usual in real life.
Rumbaugh defines the front end of the software life cycle as follows:
Analysis: A precise, concise, understandable, and correct model of the real-world. Models the real-world system so that it can be understood. The successful analysis model states what must be done, without restricting how it is done, and avoids implementation decisions. (p148)
Design: The high-level strategy for solving the problem and building a solution. System design includes decisions about the organization of the system into subsystems, the allocation of subsystems to hardware and software components, and major conceptual and policy decisions that form the framework for detailed design. (p198)
One requirement for the proposed system is: “The system must permit portions of a design to be locked for periods of extended work. These extended duration locks permit work that may last for days or weeks, in contrast to the ordinary database transactions that complete in a matter of seconds.” So several people are expected to work at the same time, and to keep them from updating the same design and losing each other’s changes we introduce locks to keep others out. (Though we pick out this one requirement, almost any of the functional requirements would serve for illustration.)
What kind of a requirement is this? Is it a statement of user need, a statement of what must be done, or a design to implement the need? An alternative design might lock nothing, and provide for merging diagrams. Another might make all updates visible to every user immediately. So this requirement embodies a design choice. Why was this choice made, and no other?
Taking each alternative in turn, it seems clear this is not a statement of user need. The user need behind this requirement might be stated, “multiple people shall use the system simultaneously without getting in each other’s way.” But this is too vague to base a system on. What does it mean to stay out of each other’s way? Is it acceptable to lock a design indefinitely? Would simultaneous update be frustrating? Is merging diagrams possible, given the kind of updates people make?
Then is this a statement of what must be done? It could be considered a statement of what the system must do. But the lock is not part of the real world. We cannot walk around these people’s offices and see locks. Analysis is supposed to model the real world, so where did these locks come from? It seems that in saying what the system is to do, we must start from an implicit system design. This requirement describes one aspect of that design. But where did this design come from? What design activity supported its creation?
If it is a design, is this requirement really describing an aspect of the “design” phase of development, and is it out of place? It says nothing about how locking is implemented. “Design,” as defined above, makes decisions about the system implementation. It does not determine basic features the system will deliver.
The above definitions of analysis and design put us in a bind. We can state requirements so exactly that we make design decisions, without the support of any explicit design activity. Or, we avoid making design decisions and state requirements so vaguely we cannot know how to meet them.
Design choices come from design activities. If this requirement embodies a design choice, some design activity must have preceded writing the requirements for the system. Let us call this implicit design step system design-the activity which determines what the system must do as a whole, and how it will fit into the work of its users. Typical requirements capture some user needs and some parts of the system design, without making the whole design explicit.
When did this design happen? How was it produced? How is it represented?
The statement of requirements does not represent a design. It is only a list of parts. An architect cannot design a house using a list, but must use a floor plan. An electrical engineer cannot design a circuit from a list, but uses a circuit diagram. In the same way, a software engineer cannot design a system from a list-we must have a way to represent the system. This representation must show the whole system, the parts, and how the parts relate to each other. This representation makes the system coherent.
System design must precede analysis, because, as we have seen, the requirements embody this design. But the standard software life cycle models, of which Rumbaugh is only one example, include no such step. Why is system design not recognized?
System Design: The Missing Step
In looking for answers to this question, we found Keller and Shumate’s book, Software Specification and Design, extremely enlightening. Figure 1 shows their description of the system development process, slightly simplified.
Here is our system design step, explicitly called out. It is a separate step that precedes software requirements analysis. Keller and Shumate in their book on software, cover all the shaded areas including both Systems Engineering and Software Engineering. By this model, development of a software product does not start with “Software Requirements Analysis.” The necessary first steps are “System Requirements Analysis” and “System Design.” (And, of course, system requirements analysis itself depends on understanding the user needs the system is to meet.) Removing the hardware component of the system does not remove the need to design the system as a whole before designing the implementation.
The analysis and design phases of software engineering, as defined above, only cover the portions of the figure labeled Software Engineering. In fact, there are two preceding steps: one to understand the users’ needs, and one to design a response to those needs. This is why requirements specification is still something of a mystery-the system design step is hidden.
This is also why identifying initial objects is a mystery. Object-oriented software requirements analysis does not describe the real world. It describes the system design, an invented response to user needs. The objects identified by the analysis model are those found in the system design, not those from the real world.
This framework explains our example above. The statement that work may last for days or weeks describes a user need. The decision to use locks is part of the system design. The lock is a part of the solution, introduced to handle a specific need. Software analysis will identify the lock as a potential object for the implementation.
The traditional terminology for software development confuses the system design and software analysis steps. This clarifies an ambiguity in Rumbaugh’s definition-how can analysis model the real world and also state what the system must do? If the analysis model includes a new concept such as a lock, it is not modeling the real world. In Keller and Shumate’s framework, deciding what the system will do is the task of system design, a separate step.
Because of this confusion, current approaches to system development do not support system design well. As a result, it happens informally and is captured indirectly, as in our example. Non-traditional approaches, such as Jacobson’s Use Cases, come closer to considering the whole system design, but do not represent the design explicitly.
To design systems that work, system design must be an explicit step. To be a step in the software engineering process means that it must be driven by the results of the previous step, understanding the user. There must be well-defined formalism for recording the design. And there must be a clear way to drive software analysis and design from the system design.
Our Approach to Formalizing Design
In our approach to customer-centered design, we made system design an explicit step and developed a representation for it. The system design is constructed from detailed user data and verifies that we meet our users’ needs well. (How user data drives the system design is described in more detail in Beyer ’93.) It also acts as the basis for the implementation. Providing an explicit representation of the system design makes object-oriented analysis easier.
Figure 2 shows the design of a simple mail system. It is organized into focus areas. Each focus area collects everything necessary to one part of the work-the functions users need along with the objects they work on to perform a particular activity. These “work objects” represent those objects users are conscious of, manipulate, and think about in performing their work. They do not represent objects in the implementation-there will be other objects, necessary to support the implementation, which are not shown because users are not conscious of them.
Arrows show how the user can move between activities in the system as they perform their work. They do not represent flow of control or data. They show how the system supports the users’ shift in attention between activities in their work. (This formalism is described in Beyer 93 and Holtzblatt 93).
The system design structures the system and describes how it will meet user needs. The next step, object-oriented analysis, pulls objects directly out of our system design formalism. The following discussion shows the details.
Entity Object Derivation
We find it useful to consider three distinct types of objects in a system’s object model: entity objects, which represent static data, interface objects which define the user interface, and control objects, which define system processing. This division of objects is similar in essence to many others’-the model-view-controller paradigm of Smalltalk (Goldberg), Jacobson’s ObjectOry (to whom we are indebted for our terms), Normand’s division of objects into “core,” “adapter,” and “interface,” and Berard’s identification of “interface” and “design” objects.
The initial entity objects of the analysis model are the work objects of the system design. Work objects may appear in several focus areas. Analysis brings them together in a unified definition, as in the single definition of the Message object in figure 3. (In the figures, we have shown only a few focus areas for clarity.)
Services of the entity objects correspond to the functions performed on the objects in the different focus areas. Here, the Send function becomes the Send service on the Message entity object. Attributes and relationships of the objects are derived from the function and purpose of the focus areas-e.g. the Display Status function implies that a message has a status attribute.
Interface Object Derivation
Products usually need to run on several user interface platforms. We also want to separate the user interface code, which is subject to frequent change, from more stable parts of the system. For both reasons, we separate the code which is specific to a user interface platform from that which can be common across all platforms.
A common approach is to clearly identify the part of the object model specific to all platforms, and distinguish it from the part which implements a specific platform user interface. These two parts of the system communicate only through objects which hide the details of each from the other. (See, for example, the functional core adapter in the Seeheim model [Pfaff 85]).
In our model, these intermediary objects correspond directly to the focus areas themselves. Because a focus area supports a coherent task, each focus area maps to a coherent part of the user interface, such as a window, screen, or pane. User interface design determines which. In the object model, each focus area generates an object which interfaces between the platform-independent part of the system and the implementation of this part of the interface. The implementation can change from window to pane to screen, without any of the rest of the system being affected.
In figure 4, Composition implements the Compose Message focus area. It mediates between a user interface implementations-either Motif or character-cell, in this example-and an entity object, Message. (A complete model would show additional objects and services.) The user interface objects know nothing about the implementation-they only know what service they invoke in Composition. Core objects know nothing about the interface-they only receive messages from Composition. Composition is an intermediary encapsulating all state having to do with the organization of the user interface, without being specific to any platform.
Control Object Derivation
Control objects represent processing done by the system. The initial set of control objects correspond to hidden focus areas, which have no associated user interface. The function of the hidden focus area defines services. State information needed to track the progress of the work defines attributes. As the details of the system implementation are fleshed out during software design, additional control objects will be identified.
In our mail example, the Send function uses store-and-forward semantics. Our system design indicates this with the hidden Send Mail focus area. The Send service on Message objects creates a Send-In-Progress control object representing that the message has been sent but not yet received. This object has Send and Update Status services, and a Status attribute to indicate whether the message is pending, has been rejected, or has been sent. This design separates the algorithms used to implement store-and-forward from the message itself. These algorithms can change independently from the implementation of messages.
Once the system is designed and initial objects are identified, existing object-oriented approaches will serve to complete the design of the implementation. The above example shows how a system design can drive such object-oriented design.
The above reasoning leads us to the conclusion that today’s most common framework for thinking about the phases of software development is flawed. The steps we believe necessary are: understand user needs in detail; design a system to meet those needs; analyze the design to understand how it may be implemented; design the implementation in detail; build; and test. The system design step has no place in the traditional framework.
The description of software development which fits this framework most closely is that of Keller and Shumate. They make it clear that the critical decisions about what the system will do happen during system design. But this step is not generally made real or explicit. It is hidden, confused with other steps, and poorly supported by current approaches.
Making system design real for software is a large project. Our customer-centered approach is one example of making it a real and concrete step. Other individuals and organizations have also recognized system design as an activity and a discipline. The Association for Software Design has been formed to find ways to make the design step an accepted part of software engineering. Companies are starting to recognize design skill as critical to the development team and distinct from traditional software engineering.
System design ensures that the system works well. It is also the basis on which the rest of the development process builds. The software life cycle must make room for it.
Footnote[I] Contextual Design, developed by the author and Karen Holtzblatt.
References[Berard 93] E. Berard, Essays on Object-Oriented Software Engineering, Volume 1. Prentice Hall, 1993.[Beyer 93] H. Beyer and K. Holtzblatt, “Contextual Design: Toward a Customer-Centered Development Process,” Software Development ’93 Spring Proceedings, February 1993, Santa Clara, California.[Goldberg 83] A. Goldberg and D. Robson, Smalltalk-80: The Language and its Implementation. Reading, MA: Addison-Wesley, 1983.[Holtzblatt 93] K. Holtzblatt and H. Beyer, “Making Customer-Centered Design Work for Teams,” Communications of the ACM, (forthcoming).[Jacobson 92] I. Jacobson, Object-Oriented Software Engineering, A Use Case Driven Approach. ACM Press, 1992.[Keller 92] M. Keller and K. Shumate, Software Specification and Design, John Wiley and Sons, New York, 1992.[Normand 92] V. Normand and J. Coutaz, “Unifying the Design and Implementation of User Interfaces through the Object Paradigm,” ECOOP ’92: Proceedings of the European Conference on Object-Oriented Programming. Utrecht, the Netherlands.[Pfaff 85] User Interface Management Systems, G.E. Pfaff ed., Eurographics Seminars, Springer-Verlag, 1985.[Rumbaugh 91] J. Rumbaugh, M. Blaha, W. Premerlani, F. Eddy, W. Lorensen, Object-Oriented Modeling and Design, Prentice Hall, Englewood Cliffs, N.J., 1991.
Published in Software Development ’93 Fall Proceedings (August 1993)