topical media & game development

object-oriented programming

Identifying objects

subsections:

Object-oriented design aims at describing a system in terms of objects (as the primary components) and the interaction between them. Motivated by the wish to arrive at stable abstractions, object-oriented design is often characterized as modeling reality, that is the application domain. However, many applications require, at least partly, a system-oriented view towards design, since they involve system artifacts for which there exist no clearly identifiable counterparts in the application domain. As an example, think of a window-based system. Many of the items (widgets) introduced in such a system belong to an artificial reality, which at best is only vaguely analogous with reality as we normally understand it. Irrespective of whether the design is intended as a preliminary study before the implementation or as a post hoc justification of the actual system, the most important and difficult part of design is the identification of objects and the characterization of their role in the system and interaction with other objects. As observed in  [McGregor92], object-oriented design is best seen as class oriented, that is directed towards the static description of (classes of) objects, rather than a description of the dynamic interaction between actual objects. In section prototypes, we will discuss class-less languages which are well suited for exploratory programming. However, from the perspective of design, we are more interested in a (static) abstract specification of the components that constitute the system.

Object-oriented design -- decomposition into objects

• application/system/class oriented

Identifying objects -- responsibilities

• data/procedure oriented

Layers of abstraction

• components, subsystems, frameworks

slide: Object-oriented design

In comparison with a functional approach, object-oriented design is clearly data oriented. However, although a data-oriented approach may provide a first guideline in developing the system, the primary concern in object-oriented design should be the responsibilities of an object rather than how it acts as a data manager, so to speak. For larger systems, the complexity of the design may necessitate the introduction of additional layers of abstraction. Apart from objects, which must be regarded as the basic components of a system, we may need to isolate subsystems, consisting of a number of related object classes. When we have developed a subsystem that can be used in a variety of contexts, such a subsystem may be used as a framework. A framework is generally not only a collection of classes but must also be seen as an approach or method in its own way, since it usually imposes additional constraints on the development. For example, most development environments for window-based applications provide a framework consisting of a number of predefined classes and functions, and guidelines or recipes that prescribe how to use or adapt these classes and functions. Also, most frameworks impose a specific control model, such as the event-driven control model imposed by window programming environments.

Modeling heuristics

Following  [Booch86], we may characterize objects as `crisp' entities that suffer and require actions. From the perspective of system development, objects must primarily be regarded as computational entities, embodying the means by which we may express a computation. Modeling a particular problem domain, then, means defining abstractions in terms of objects, capturing the functional characteristics of that domain. The question is, how do we arrive at such a model?

Objects -- crisp entities

• object = an entity that suffers and requires actions

The method:

• $\left[1\right]$ Identify the objects and their attributes
• $\left[2\right]$ Identify operations suffered and required
• $\left[3,4\right]$ Establish visibility/interface

slide: The Booch method

In  [Booch86], a straightforward method of object oriented development is proposed, which consists of the successive identification of objects and their attributes, followed by a precise characterization of the interobject visibility relations. In  [Booch91], a shift of emphasis has occurred towards determining the semantics of an individual object and the interaction between collections of objects.

Heuristics

• model of reality -- balance nouns (objects) and verbs (operations)

Associations

• directed action -- drives, instructs
• communication -- talks-to, tells, instructs
• ownership -- has, part-of
• resemblance -- like, is-a
• others -- works-for, married-to

slide: Heuristics for modeling

As a heuristic to arrive at the proper abstractions of the problem domain (in terms of object classes),  [Booch86] proposes scanning the requirements document for nouns, verbs and adjectives, and using these as initial suggestions for respectively objects, and operations and attributes belonging to objects (see slide 3-heuristics). This technique has been adopted and augmented by a number of other authors, among which  [WWW90] and  [Rum91]. For example,  [WWW90] illustrate the technique in fine detail in several examples, including the design of an automated teller machine and a document processing system. In addition to the interpretation of nouns as possible objects, verbs as possible operations on objects, and adjectives as possible attributes of objects,  [Rum91] suggest this technique to determine other relations and associations between object classes as well. For instance, a model of control and object interaction may be suggested by phrases indicating directed action or communication. Similarly, structural issues, such as whether an object owns another object or whether inheritance should be used, may be decided on the basis of resemblance or subordination relations.

Example -- ATM (1)

The example of an automated teller machine discussed in  [WWW90] nicely illustrates a number of the notions that we have thus far looked at only in a very abstract way. A teller machine is a device, presumably familiar to everyone, that allows you to get money from your account at any time of the day. Obviously, there are a number of constraints that such a machine must satisfy. For instance, other people should not be allowed to withdraw money from your account. Another reasonable constraint is that a user cannot overdraw more than a designated amount of money. Moreover, each transaction must be correctly reflected by the state of the user's account.

Candidate classes

ATM

• account -- represents the customer's account in the banks database
• atm -- performs financial services for a customer
• cashdispenser -- gives cash to the customer
• screen -- presents text and visual information
• keypad -- the keys a customer can press
• pin -- the authorization code
• transaction -- performs financial services and updates the database

slide: The ATM example (1)

An initial decomposition into objects based on these requirements is shown in slide 3-atm-1. In  [WWW90], a fully detailed account is given of how one may arrive at such a decomposition by carefully reading (and re-reading) the requirements document. What we are interested in here, however, is how we may establish that we have not overlooked anything when proposing a design, and how we may verify that our design correctly reflects the requirements. This particular example nicely illustrates the need for an analysis of the use cases. To develop a proper interface, we must precisely know what a user is expected to do (for instance, insert a bank card, key in a PIN code) and how the system must respond (what messages must be displayed, how to react to a wrong PIN code, etc.). Another decision that must be made is when the account will be changed as the result of a transaction. Also, we must decide what to do when a user overdraws. A very important issue that we will look at in more detail in the next sections is how the collection of objects suggested above will interact. What means do we have to describe the cooperation between the objects, and how do we show that the proposed system meets all the requirements listed above? Moreover, can we verify that the system satisfies all the constraints mentioned in the requirements document?

Validation

However, before examining these questions and trying out different scenarios, we may as well try to eliminate the spurious classes that came up in our initial attempt. In  [Rum91], a number of reasons are summarized that may be grounds on which to reject a candidate class. See slide 3-eliminating.

Eliminating spurious classes

• vague -- system, security-provision, record-keeping
• attribute -- account-data, receipt, cash
• redundant -- user
• irrelevant -- cost
• implementation -- transaction-log, access, communication

Good classes

• our candidate classes

slide: Eliminating spurious classes

For example, the notion underlying the candidate class may be too vague to be represented by a class, such as the notion of system or record-keeping. Another reason for rejecting a suggested class may be that the notion represents not so much a class, but rather a possible attribute of a class. Further, a proposed class may either be redundant, for example the class user, or simply irrelevant, as is the class cost. And finally, a class may be too implementation oriented, such as the class transaction-log or classes that represent the actual communication or access to the account. Looking back, our choice of candidate classes seems to have been quite fortunate, but generally this will not be the case, and we may use the checklist above to prune the list of candidate classes.

An interesting architectural issue is, how may we provide for future extensions of the system? How easily can we reuse the design and the code for a system supporting different kinds of accounts, or different input or output devices? And how can we establish that the objects, as identified, interact as desired?

Assigning responsibilities

Design is to a large extent a matter of creative thinking. Heuristics such as performing a linguistic scan on the requirements document for finding objects (nouns), methods (verbs) and attributes (adjectives) may be helpful, but will hopelessly fail when not applied with good taste and judgement. Not surprisingly, one of the classical techniques of creative writing, namely the shoe-box method, has reappeared in the guise of an object-oriented development method. The shoe-box method consists of writing fragments and ideas on note cards and storing them in a (shoe) box, so that they may later be retrieved and manipulated to find a suitable ordering for the presentation of the material. To find a proper decomposition into objects, the method creates for each potential (object) class a so-called CRC card, which lists the Class name, the Responsibilities and the possible Collaborators of the proposed class. In a number of iterations, a collection of cards will result that more or less reflects the structure of the intended system. According to the authors (see Beck and Cunningham, 1989), the method effectively supports the early stages of design, especially when working in small groups. An intrinsic part of the method consists of what the authors call dynamic simulation. To test whether a given collection of cards adequately characterizes the functionality of the intended system, the cards may be used to simulate the behavior of the system. When working in a group, the cards may be distributed among the members of the group, who participate in the simulation game according to their cards. See slide 3-crc.

Object-oriented thinking

CRC

• Immerse the reader in the {\em object-ness} of the material
• Give up global knowledge of control
• Rely on the local knowledge of objects

OO design with CRC cards

• Class, Responsibility, Collaborators

slide: The CRC method

A number of authors have adopted this method, or developed a very similar method, for identifying objects and characterizing their functionality in an abstract way. It is doubtful, however, whether the method has any significance beyond the early stages of analysis and design. Without any more formal means to verify whether the responsibilities listed adequately characterize the intended functionality of the system, the method amounts to not much more than brainstorming. Clearly, the method needs to be complemented by more formal means to establish whether the (implicit) protocols of interaction between the objects satisfy the behavioral requirements of the system. Nevertheless, the elegant simplicity of the method is appealing, and the card format lends itself to easy incorporation in an on-line documentation system. Moreover, since the method imposes no strict order, and has relatively little overhead, it is indeed a good way to get an initial idea of what objects the system will comprise.

Example -- ATM (2)

Actually, the ATM example is an interesting example for comparing the various approaches, since it is used by many authors to illustrate their methods. In  [WWW90] the example is used for spelling out all the steps that must be taken. In  [Rum91] it is extensively described to illustrate the various modeling techniques employed by the method. And in  [BC89] the CRC cards method is illustrated by sketching the design of an automated teller machine. The approaches presented in  [BC89] and  [WWW90] are actually very closely related. Both may be characterized as responsibility-driven, in that they concentrate on responsibilities and collaboration relations to model the interaction between objects. However, the method described in  [WWW90] is much more detailed, and to some extent includes means to formally characterize the behavior of an object and its interaction with other objects. To this end it employs an informal notion of contracts as originally introduced in  [Meyer88]. In section ATM-1 a number of candidate classes have been suggested for our ATM. Now, with the use of CRC cards, we will delineate the functionality of (a number of) these classes more precisely. Also we will establish how the various object classes must collaborate to perform their duties. At the highest level of the design, we may distinguish between two groups of classes: the classes representing the banking model (comprising the class account and the class transaction), and the classes that model the interaction with the user (comprising the class card-reader and the class cash-dispenser). At a lower level, we also need a class modeling the database that provides persistent storage for the user's account and the information needed for authorization. For each of these classes we will use a CRC card to indicate their responsibilities and the classes with which they need to collaborate. The banking model, depicted in slide 3-atm-2a, consists of the classes account and transaction. The class account keeps a record of the actual balance of the account and must allow a user to deposit or withdraw money. However, for safety reasons, these operations are never carried out directly, but are performed by an intermediary transaction object. The responsibilities of the transaction class may be summarized as: the validation of user requests and the execution of money transfers. The responsibility for maintaining audit information is also assigned to the transaction class. To act as required, a transaction object needs to communicate with a number of other objects. It must acquire information from both the card-reader and the database to check, for example, whether the user has entered the right PIN code. To validate a request, it must check whether the account will be overdrawn or not. To pay the requested money, it must instruct the cash-dispenser to do so. And it must contact the database to log the appropriate audit information. In contrast, an account only needs to respond to the requests it receives from a transaction. Apart from that, it must participate in committing the transaction to the bank's database. Note that the CRC method is non-specific about how the collaborations are actually realized; it is unclear which object will take the initiative. To model these aspects we will need a more precise notion of control that tells us how the potential behavior (or responsibility) of an object is activated. The second group of classes may be called interaction classes, since these are meant to communicate with entities in the outside world, outside from the perspective of the system. Also the bank's database may be considered as belonging to the outside world, since it stores the information concerning the account and the authorization of customers in a system-independent manner. See slide 3-atm-2b. Both the card-reader and the cash-dispenser rely on a class called event, which is needed to model the actions of the user. For example, when a user inserts a bankcard, we expect a transaction to start. For this to happen, we must presuppose an underlying system that dispatches the event to the card-reader, which in turn notifies the teller machine that a new transaction is to take place. The flow of control between a transaction object and the cash-dispenser is far more straightforward, since a transaction object only needs to issue the appropriate instruction. However, the actual interaction between the cash-dispenser and the underlying hardware, that turns out the money, may be quite intricate. The database may either respond directly to the request coming from the account or transaction object or it may respond to events by taking the initiative to call the appropriate methods of the account and transaction objects. Whether the database may be accessed directly or will only react to events is actually dependent on the control model we assume when developing the system model.

Object roles and interaction

Objects rarely live in isolation. In a system of some complexity, a number of different kinds of object classes may usually be distinguished. Each kind of class may be regarded as playing a specific role in the system. For example, when considering our ATM, classes such as card-reader and cash-dispenser are of a completely different kind, and play a completely different role, than the classes account and database for instance, or the classes event and transaction. Often it will take some experimentation to decide how control must be distributed among the objects comprising the system. Although the framework chosen for the development of the system may partly determine the control model, there will usually be ample choice left for the designer of the system to define the interactions between objects.

Object roles

• actor -- operates (suffers no operations)
• server -- suffers operations
• agent -- suffers and operates ( actor & server)

slide: Object roles

An important function of the design document is to elucidate the role of each object class in the system, and to point out how the objects cooperate to complete the task. In  [Booch86], a distinction is made between objects that suffer no operations (actors), objects that only suffer operations (servers) and objects that both suffer and require operations (agents). Such a characterization in terms of initiative may give a first indication of the role an object plays in the system. For example, the account class in our ATM example is best characterized as a server class, whereas the transaction class may be regarded, in the terminology of  [Booch86], as an actor class, since it actively controls the computation. In many cases, the software control model adopted will also influence the way in which individual objects are supposed to behave. See slide 3-roles. With respect to a global view of the system, it is necessary to ensure that each object class is completely defined, that is to establish that each class provides a sufficiently complete method interface. In  [Booch86], a characterization is given of the kinds of methods that may occur in an interface. These include methods to create or destroy an object, methods to modify the state of an object and methods that only provide information on the state of an object, or parts thereof. Before being able to make final decisions with respect to the functionality of a class, however, it is generally necessary to get a clear overall picture of the system first. This requires what  [Booch86] characterizes as round trip gestalt design, which in other words expresses the need to

analyze a little,

design a little,

implement a little,

test a little ... (The notion of gestalt comes from perception psychology, where it means a global perceptual configuration emerging from the background.)

(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.