Lecture
Classical and modern approaches
Ever since Plato, the problem of classification has occupied the minds of countless philosophers, linguists, cognitive scientists and mathematicians. It would therefore be sensible to study the experience that has been accumulated and apply it in object-oriented design. Historically, only three approaches are known:
Classical categorization. In the classical approach, "all the things that have a given property or collection of properties in common form a category. Moreover, the presence of these properties is a necessary and sufficient condition that defines the category" [18]. For example, bachelors form a category: every person is either unmarried or married, and this attribute is sufficient to decide which category a particular individual belongs to. On the other hand, tall people do not define a category, unless of course we specifically state a criterion that lets us clearly distinguish tall people from short ones.
Classical categorization came down to us from Plato and Aristotle. In his classification of plants and animals, the latter used a technique of reasoning reminiscent of the modern children's game of 20 questions (Is it a mineral, an animal or a plant? Is it covered with fur or with feathers? Can it fly? Does it smell?) [20]. This approach found followers, the most eminent of whom were Thomas Aquinas, Descartes and Locke. As Thomas Aquinas asserted: "We can name things according to our knowledge of their nature, which we obtain through knowledge of their properties and actions" [21].
The principles of classical categorization are reflected in the modern theory of child development. Piaget maintains that after the first year of life a child becomes aware of the existence of objects and then begins to acquire skills for classifying them, at first using basic categories such as dogs, cats and toys [22]. Later the child becomes aware, on the one hand, of more general categories (animals) and, on the other hand, of more specific ones (collies, Great Danes, sheepdogs) [23].
Thus the classical approach uses the relatedness of objects' properties as the criterion of their similarity. In particular, objects can be divided into disjoint sets depending on the presence or absence of some attribute. Minsky suggested that "the best sets of properties are those whose elements interact little with one another. This explains the universal fondness for such criteria as size, color, shape and material. Since these criteria do not overlap, one can assert of some object that it is large, gray, round and wooden" [24]. Generally speaking, properties need not be measurable; observable behavior can be used instead. The fact that birds fly and fish do not makes it possible to tell an eagle from a trout.
| The classification problem
Fig. 4-1 shows 10 trains, labeled with the letters A through J. Each picture consists of a locomotive and several cars. Before reading on, try for 10 minutes to identify several groups of pictures formed according to some logical attribute. For example, the pictures can be divided into three groups: in one group the trains have black wheels, in another white wheels, and in a third both white and black ones. This example is taken from Stepp and Michalski's work on conceptual clustering [19]. Obviously, there is no "correct" division into groups. Our pictures were classified in 93 different ways. The most common way of classifying is by the length of the train: three groups were singled out, trains with two, three and four cars. The second most popular kind of classification is by the color of the train's wheels. Forty of the ninety-three kinds of classification were unique (that is, the kind contained only one instance). Experimenting with this figure, we became convinced that Stepp and Michalski were right. Most of the people we surveyed proposed one of the two most popular kinds of classification (by train length and by wheel color). One respondent proposed the following: in one group the trains are marked with letters drawn using only straight lines (A, E, F, H and I), and in the other with letters containing curved lines. Now that really is an example of nontrivial thinking. If you have already coped with the task, let us change the conditions. Imagine that the circles denote a cargo of toxic substances, the rectangles timber, and all the other symbols denote passengers. Now try to classify the pictures and notice how the additional information affects your point of view. In our experiments most of the people surveyed classified the trains by whether or not the train carries toxic cargo. We concluded that new information about the real situation makes classification easier and better. |
Which properties specifically must be taken into account? That depends on the circumstances. For example, the color of a car has to be recorded in a task that keeps track of an automobile plant's output, but it is of no interest to a program controlling a street traffic light. This is why we say that there is no absolute criterion of classification; one and the same class structure may suit one problem and be unsuitable for another. James writes: "It cannot be claimed that some classification scheme reflects the structure and order of things in nature better than others. Nature is indifferent to our attempts to make sense of it. Some classifications really are more important than others, but only in connection with our interests, and not because they reflect reality more truly or more fully" [25].
Modern Western thinking is for the most part thoroughly permeated with classical categorization; however, as the example with tall and short people shows, this approach does not always work. Kosok notes that "natural categories are not sharply delimited from one another. Most birds fly, but not all. A chair may be wooden, metal or plastic, and the number of legs it has depends entirely on the designer's whim. It is practically impossible to enumerate the defining properties of a natural category so that there are no exceptions" [26]. These really are the fundamental flaws of classical categorization, which the modern approaches have tried to correct. We shall now turn to them.

Fig. 4-1. The classification problem.
Conceptual clustering. This is a more modern variant of the classical approach. It arose out of attempts at the formal representation of knowledge. Stepp and Michalski write: "In this approach, conceptual descriptions of classes (clusters of objects) are first formed, and then we classify entities in accordance with these descriptions" [27]. For example, take the notion of a "love song". This is precisely a concept, not an attribute or property, since the degree of a song's lovingness can hardly be measured. But if it can be asserted that a song is more about love than about anything else, then we place it in this category.
Conceptual clustering can be related to the theory of fuzzy (multivalued) sets, in which an object may belong to several categories at once with different degrees of precision. Conceptual clustering makes absolute judgments in classification, based on the best fit.
Prototype theory. Classical categorization and conceptual clustering are sufficiently expressive methods, quite suitable for designing complex software systems. Yet there are still situations in which these methods do not work. Let us consider a more modern method of classification, prototype theory, whose premises can be found in the book on the psychology of perception by Rosch and her colleagues [28].
There exist certain abstractions that have neither clear-cut properties nor a clear-cut definition. Lakoff explains this problem as follows: "According to Wittgenstein, there exist categories (for example, games) that do not fit the classical patterns, since there are no attributes common to all games... For this reason they can be united by so-called family resemblance... Wittgenstein maintains that the category of games has no clear-cut boundary. The category can be extended to include new kinds of games provided that they resemble games already known" [29]. This is why this approach is called prototype theory: a class is defined by a single prototype object, and a new object can be assigned to the class provided that it is endowed with essential similarity to the prototype.
Lakoff and Johnson apply prototype-based classification to the problem of chairs mentioned above. They note that "we count a beanbag, a barber's chair and a folding chair as chairs not because they satisfy some fixed set of prototype attributes, but because they have sufficient family resemblance to the prototype... No general set of prototype properties is required that would fit both the beanbag and the barber's chair, yet both are chairs, since each of them individually resembles the prototypical chair, even if each in its own way. Properties determined through interaction with an object (interactional properties) are the principal ones in determining family resemblance" [30].
The notion of interactional properties is central to prototype theory. In conceptual clustering we group according to various concepts. In prototype theory objects are classified by the degree of their similarity to a concrete prototype.
Applying the classical and the new theories. To a developer preoccupied with constantly changing requirements on the system and forever fighting a tight schedule with limited resources, the subject of our discussion may seem far removed from reality. In fact, the three approaches to classification we have examined bear directly on object-oriented design.
In practice we identify classes and objects first by the properties that matter in the given situation, that is, we try to single out and select structures and kinds of behavior with the help of the vocabulary of the problem domain. "As a rule, there are a great many potentially possible abstractions" [31]. If in this way we fail to build a palatable class structure, we try the conceptual approach. In this case attention centers on the behavior of objects when they interact with one another. Finally, we try to single out prototypes and associate objects with them.
These three ways of classifying constitute the theoretical foundation of the object-oriented approach to analysis, which offers many practical pieces of advice and rules that can be applied to identify classes and objects when designing a complex software system.
Object-oriented analysis
The boundaries between the stages of analysis and design are blurred, but the tasks they solve are defined quite clearly. In the process of analysis we model the problem, discovering the classes and objects that make up the vocabulary of the problem domain. In object-oriented design we invent the abstractions and mechanisms that provide the behavior required by the model [The notation and processes described in this book apply equally to the phases of both analysis and design (in the traditional sense), as we shall see in Chapter 6. It is precisely for this reason that in the second edition we changed the title of the book to "Object-Oriented Analysis and Design"].
We shall now consider several practice-proven approaches to the analysis of object-oriented systems.
Classical approaches. Different scholars find different sources of classes and objects consistent with the requirements of the problem domain. We call these approaches classical, since they rest upon classical categorization.
For example, Shlaer and Mellor propose the following candidates for classes and objects [32]:
| ® Tangible things | Automobiles, telemetry data, pressure sensors |
| ® Roles | Mother, teacher, politician |
| ® Events | Landing, interrupt, request |
| ® Interactions | Loan, meeting, intersection |
Ross proposes something of the same kind, proceeding from the perspective of database modeling [33]:
| ® People | Human beings who carry out certain functions |
| ® Places | Areas associated with people or things |
| ® Things | A tangible material object or group of objects |
| ® Organizations | A formally organized collection of people, resources and equipment that has a definite purpose and whose existence on the whole does not depend on individuals |
| ® Concepts | Principles and ideas, intangible in themselves, but intended to organize activity and/or communication, or else to observe them |
| ® Events | Something that happens to something at a given time or in sequence |
Coad and Yourdon proposed their own list [34]:
| ® Structures | "Whole-part" and "general-specific" relationships |
| ® Other systems | External systems with which the application interacts |
| ® Devices | Devices with which the application interacts |
| ® Events | Occurrences that must be remembered |
| ® Roles played | The roles played by the users working with the application |
| ® Places | Buildings, offices and other locations essential to the application's work |
| ® Organizational units | The groups to which the users belong |
At a higher level of abstraction Coad introduces the notion of a subject area, which is in essence a logically connected group of classes relating to the high-level functions of the system.
Behavior analysis. While the classical approaches concentrate attention on the tangible elements of the problem domain, another school of thought in object-oriented analysis focuses on dynamic behavior as the primary source of objects and classes [Shlaer and Mellor supplemented their earlier work by turning their attention to behavior as well. In particular, they studied the life cycle of an object as a means of understanding boundaries]. This is reminiscent of the conceptual clustering considered above: we form classes based on groups of objects that exhibit similar behavior.
Wirfs-Brock proposes the notion of an object's responsibilities, by which one should understand "its knowledge and its abilities. A responsibility is a way of expressing the purpose of an object and its place in the system. An object's responsibilities are the totality of all the services it can provide under all of its contracts" [36]. That is, we group together those objects that have similar responsibilities and build a class hierarchy in which each subclass, while fulfilling the obligations of the superclass, contributes its own additional services.
Rubin and Goldberg propose identifying classes and objects by analyzing the functioning of the system: "Our approach is based on studying the behavior of the system. We map forms of behavior onto parts of the system and try to understand which part initiates the behavior and which parts participate in it... The initiators and participants that play essential roles are recognized as objects and are made responsible for these roles" [37].
Rubin's ideas are closely related to the approach from the standpoint of functions proposed by Albrecht in 1979. By his definition, a function "is defined as a separate business action of the end user" [38], that is: input/output, inquiry, file or interface. Obviously, this conception originates in the field of information systems. However, it can be applied to any automated system. In essence, a function is any reliably externally visible and business-relevant behavior of the system.
Domain analysis. Up to now we have implicitly had in mind the single application we are developing. But sometimes, in the search for useful ideas that have already proved their workability, it is helpful to turn at once to all the applications within a given problem domain, such as, for example, keeping patients' medical records, securities trading, compiler development or missile control systems. If you are in the middle of a development effort and are stuck, an analysis of some narrow problem domain may help by pointing you to key abstractions that have proved useful in similar systems. Domain analysis works very well, except perhaps in only very special situations, since unique software systems are encountered extremely rarely.
The idea of domain analysis was first proposed by Neighbors. We shall define such analysis as "an attempt to single out those objects, operations and relationships that experts in the given field consider most important" [39]. Moore and Bailin define the following stages in domain analysis:
Domain analysis can be conducted with respect to analogous applications (vertically) or with respect to analogous parts of one and the same application (horizontally). For example, when beginning to design a patient records system, it makes sense to examine similar systems that already exist, in order to understand which of the key abstractions and mechanisms used in them will be useful to you and which will not. Similarly, an accounting system must present various kinds of reports. If reports are regarded as a certain problem domain, its analysis may lead the developer to an understanding of the key abstractions and mechanisms that serve all kinds of reports. The classes and objects obtained in this way constitute a set of key abstractions and mechanisms selected with the goal of the original problem in mind: creating a reporting system. The final design will therefore be simpler.
Let us now define who an expert is. The role of expert is often played simply by a user of the system, for example an engineer or a dispatcher. He need not be a programmer, but he must be closely familiar with the problem under investigation and speak the language of that problem.
Project managers are interested in direct cooperation between the users and the developers of the system. But for very complex systems domain analysis is a formal process requiring a large number of experts and developers over a long period of time. In practice such formal analysis is rarely required. Usually a short meeting of experts and developers is enough for an initial understanding of the problem. It is surprising how little information a developer needs in order to work productively. However, we consider such meetings extremely useful throughout the whole development effort. Domain analysis is best conducted step by step - analyze a little, then design a little, and so on.
Use-case analysis. Taken separately, the classical approach, the behavioral approach and the study of the problem domain considered above depend heavily on the individual abilities and experience of the analyst. For most real projects the simultaneous application of all three approaches is unacceptable, since the process of analysis becomes nondeterministic and unpredictable.
Use-case analysis is an approach that can be successfully combined with the first three, making their application more orderly. It was first formalized by Jacobson, who defined a use case as "a particular instance or pattern of use, a scenario that begins when a user of the system initiates an operation or a sequence of interrelated events" [41].
In short, this kind of analysis can be started together with requirements analysis. At this point users, experts and developers enumerate the scenarios most essential to the operation of the system (without yet going into details). Then they carefully work the scenarios through, laying them out frame by frame, as television and film people do [42]. In doing so they establish which objects take part in the scenario, what the responsibilities of each object are, and how they interact in terms of operations. The development team is thereby forced to distribute the spheres of influence of the abstractions clearly. Next the set of scenarios is expanded to take exceptional situations and secondary behavior into account (Goldstein and Alger call these peripheral aspects [43]). As a result new abstractions appear or existing ones are refined. Later, in Chapter 6, we shall show how scenarios are used for testing.
CRC cards. CRC stands for Class-Responsibilities-Collaborators. This is a simple and remarkably effective way of analyzing scenarios. CRC cards were first proposed by Beck and Cunningham for teaching object-oriented programming, but such cards turned out to be an excellent tool for brainstorming and for communication among developers.
Strictly speaking, these are ordinary 3x5 inch index cards (if your project budget allows, buy 5x7 ones; it is very good if the cards are ruled, and multicolored ones are simply a dream). On the cards you write (always in pencil) the name of the class at the top, what it is responsible for at the bottom in the left half, and whom it collaborates with in the right half. Going through the scenario, start a card for each class you discover and add new items to it. Each time, think over what comes of this, and "factor out the excess responsibility" into a new class or, which happens most often, move responsibilities from one large class to several more detailed classes, or perhaps hand over some of the duties to another class.
The cards can be laid out so as to represent forms of collaboration among objects. From the standpoint of the dynamics of a scenario, their arrangement can show the flow of messages between objects; from the standpoint of statics, they represent class hierarchies.
Informal description. A radical alternative to classical analysis was proposed in Abbott's extremely simple method. According to this method one must describe the problem or a part of it in plain English, and then underline the nouns and verbs [45]. The nouns are candidates for the role of classes, and the verbs may become the names of operations. The method can be automated, and such a system was built at the Tokyo Institute of Technology and at Fujitsu [46].
Abbott's approach is useful because it is simple and forces the developer to deal with the vocabulary of the problem domain. However, it is quite approximate and unsuitable for problems of any complexity. Human language is a terribly imprecise means of expression, and so the list of objects and operations depends on the developer's skill in writing down his thoughts. All the more so since for many nouns one can find a corresponding verb form and vice versa.
Structured analysis. A second alternative to the classical technique of object-oriented analysis uses structured analysis as the basis for object-oriented design. Such an approach is attractive because many analysts apply it and there are a great many CASE tools supporting the automation of these methods. Personally we do not like using structured analysis as the basis for object-oriented design, but for some organizations such a pragmatic approach has no alternative.
After carrying out structured analysis we already have a model of the system described by data flow diagrams and other products of structured analysis. These diagrams give us a formal model of the problem. Proceeding from the model, we can set about determining meaningful classes and objects in three different ways.
McMenamin and Palmer suggest first setting about forming a data dictionary and then analyzing the context diagrams of the model. They say:
"in examining the list of the principal data structures, one should think about what they say or what they describe. For example, if they are adjectives, then what nouns do they describe? The answers to such questions may add to your list of objects" [47]. These candidate objects come from the surrounding environment, from the essential input and output data, and also from the products, services and other resources that it manages.
The next two ways are based on the analysis of individual data flow diagrams. If we take some flow diagram (in the terminology of Ward and Mellor [48]), then the candidate objects are:
Candidate classes are:
There remains the data transformation, which we can regard either as operations on existing objects or as the behavior of some object that we have created specially to perform the required transformation.
Seidewitz and Stark propose yet another method, which they call abstraction analysis. The method is based on identifying central entities, which are by their nature analogous to the central transformations in structured design. As they say, "in structured analysis the input and output data are studied until the highest level of abstraction is reached. The process of transforming input data into output data is the central transformation. In abstraction analysis the developer does the same thing, and also studies the central transformation in order to determine which processes and states represent the best abstract model of the system" [49]. After determining the central entity in the data flow diagram, the analyst sets about studying the whole infrastructure, tracing the data flows entering and leaving the center and grouping the processes and states encountered along the way. For practical use the authors found abstraction analysis too complicated and propose object-oriented analysis as an alternative [50].
It must be noted that the principles of structured design, which naturally follows structured analysis, are completely orthogonal to the principles of object-oriented design. Our experience shows that using structured analysis in the process of object-oriented design often leads to complete failure, unless the developer is able to resist the desire to tumble into the structured abyss. Another very serious danger lies in the fact that many analysts like to draw data flow diagrams that represent a description of the design rather than a model of the essence of the system. It is very difficult to build an object-oriented system if the model is so obviously oriented toward algorithmic decomposition. We therefore prefer object-oriented analysis and domain analysis as the preparatory stage for object-oriented design. This reduces the risk of littering the design with elements of algorithmic analysis.
If, however, for some valid reason [Political and historical reasons are not accepted as valid] you have to take structured analysis as your basis, stop building diagrams as soon as they begin to look like a design of the program rather than a model of the problem domain. Remember that design materials, such as data flow diagrams, are not the end product but a tool of the developers. Usually diagrams are built and then the mechanisms that provide the required behavior of the system are developed, that is, the very act of designing modifies the initial model. Keeping the model and the evolving design in correspondence is a difficult matter and, frankly speaking, a useless one. It makes sense to preserve only the product of structured analysis at a high level of abstraction. It reflects the essential features and is sufficiently independent of the system design.
Comments