ood 03062015

advertisement
16. Designing with Objects
16.1 The ‘object concept’
For our purposes, we can regard an object as some form of entity that performs computations and has some kind of
local state that may be modified by the computations. On this basis, an object possesses a state, exhibits behaviour,
and has some form of distinct identity, as illustrated in Figure 16.2
n abstraction
It is an essential property for any form of design object that its characteristics should be capable of being identified
in an abstract manner. For the ‘object-oriented’ forms of design process, abstraction performs an important role in
modelling the objects in a system, and indeed object-oriented design is largely about how to select the ‘correct’ set
of abstractions for use in modelling a problem.
n encapsulation
This is basically a term used to describe a realization of the concept of informationhiding, whereby we seek to
conceal those features of an object that are not essential to its abstraction. By concealing the implementation details
of an object, it is then much easier to make changes to them without creating side-effects for the system as a whole.
n modularity
Basically it is concerned with partitioning the model of a system into individual components (often termed
‘separation of concerns’), and an important criterion in evaluating any choice of components is the complexity of the
interfaces between the resulting modules.
For many action-oriented design strategies, the basic level of modularity is the subprogram, and the interconnection
mechanism is a combination of the subprogram calling mechanism (invocation) and the parametrization of the
subprogram interface.
n hierarchy
1
While
inheritance is concerned with identifying how the properties of objects are derived from those of their parents, the
uses hierarchy, as shown in Figure 16.4, identifies the extent to which the operations of one object (module) depend
upon the availability of the services provided by other objects (modules).
2
3
Figure 16.5 illustrates schematically a key difference between ‘conventional’ program forms, based upon using
subprograms in a call-and-return architectural style, and the form of an object-oriented solution. (From an
implementational viewpoint, this distinction is sometimes further confused by the way that object-oriented
programming languages such as Java can be used to construct both types of solution, admittedly at the price of some
distortion.)
In Figure 16.5(a) we show a program that is constructed from four subprograms, A, B, C and D, rather as it might be
mapped on to a computer’s memory through the processes of compilation and link-editing. Figure 16.5(b) shows the
corresponding call graph (equivalent to a Structure Chart) that shows how the subprograms are connected at run
time. The data components are either ‘global’ to the program as a whole, or contained as local data within the
subprograms. Linkages and connections between the subprogram and the data within such a program are effectively
determined at the time when it is compiled and linked, and hence can be regarded as being static in nature.
The object-oriented equivalent is shown in Figure 16.5(c). Since this is purely a schematic illustration, we need not
concern ourselves here with how the functionality is redistributed between the three objects X, Y and Z (which we
will also assume are created from different classes). Each object provides a set of methods that provide access to its
encapsulated data. (In many object-oriented programming languages,
methods use a restricted form of the procedure/subprogram constructs.) So now, if object X wishes to access data
held in object Y, it might do so by using the methods Y.b() or Y.c() for this purpose. (It is a common convention to
give the full reference to a method as object-identifier.method-identifier.)
However, we might also note that object Z also provides a method b(). Since this can be referenced from X (or Y),
as Z.b(), no confusion need arise. More usefully though, in an object-oriented system, whenever object X makes a
reference to a method b(), we can expect that the context of that reference will be used to determine whether the
appropriate method to use is Y.b() or Z.b(), with the appropriate choice being made automatically and at run-time.
(The mechanism for determining which one is used will depend upon implementation detail.) Because in Figure
16.5(c) the bindings between the objects are created dynamically when the system runs, the decision about which
method to use can be made at run-time. In contrast, in the statically-bound structure of Figure 16.5(a), the equivalent
bindings are determined at time of compilation and cannot thereafter be modified.
It is this ability to select the appropriate method from a number of methods with the same name (or identifier), but
originating in different classes, that is termed polymorphism. (Strictly, although our example is couched in terms of
objects, the methods themselves are defined in the parent classes.) To return for a moment to the earlier example of
the Bank Account and its subclasses, we might expect that all classes will provide a withdraw() method, but that the
detailed form of the withdraw() operation will differ according to the type of account involved. So when this
operation is used with any given account, the form used will depend upon the class of that account. We can therefore
regard methods as being typed by the class that contains them, as well as by any data values that they return.
4
A summary of the core concepts of the proposed model is given below: it seems to summarize
the issues of the object-oriented paradigm very well.
n Objects embody an abstraction that is meaningful to their clients.
n Objects provide services characterizing the abstraction that is embodied in an object, where such a service may
access or modify data within an object and may affect other objects.
n Clients issue requests for the services that are provided by objects.
n Objects are encapsulated so that clients cannot directly access or manipulate data associated with objects.
n Requests identify operations in terms of the service that an object is required to provide.
n Requests can identify objects, so that in issuing a request a client can identify the object that should service it.
n New objects can be created to support parallel operations and the time-varying behaviour of a system.
n Operations can be generic in that a service can have different implementations for different objects.
n Objects can be classified in terms of their services through the interface that they present to clients.
n Objects can have a common implementation so that objects may share code, although generally they do not share
data, making for efficiency of implementation where multiple instances of objects exist in a system.
n Objects can share partial implementations so that not all elements of the behavior of objects need be shared where
the objects are sharing an implementation.
Some conceptual issues presented by the object model
One of the arguments that is apt to be made in favour of the object-oriented style is that it is more ‘natural’ than
(say) pipe and filter or call and return. The basis for this argument is that the object-oriented style is one that more
closely reflects ‘real world’ structures, whereas these other styles are based upon ‘artificial’ computing constructs.
Hence (so the argument quite reasonably continues), the process of analysis should be able to identify the objects in
the problem domain, and then use the resulting model to help formulate a set of corresponding ‘solution objects’.
However, in practice this approach has not proved to be a particularly effective strategy
16.2 Design practices for the object-oriented paradigm
The main steps in this design strategy are:
n produce a written description of a ‘rough’ design solution;
n analyse this description in terms of the nouns and the verbs, using the former to help with identifying the design
objects and the latter to help with identifying the operations (methods) associated with the objects;
n refine the descriptions of the objects to help produce a more complete solution.
16.3 Object-Oriented frameworks
n White
box frameworks employ object-oriented mechanisms such as inheritance and polymorphism as the means of
configuration. Such frameworks clearly need to make the structure of the parent classes ‘visible’, and are apt to be
language-specific in their form. A good example of such a white box framework is Java’s Applet structure,
illustrated in Figure 16.7(a). The abstract class Applet defines the operations
that individual applets can perform (and provides empty methods for these), with an actual applet then providing
over-riding methods to replace these as necessary. As a result, all applets conform to a given structure, which is why
their operations can be called from any browser which knows about the form of that framework.
n Black box frameworks define interfaces that enable other elements to be ‘plugged in’ to the framework code.
However, while this makes it unnecessary for a user to know any details of the inner workings of the framework, the
5
development of such frameworks is made correspondingly more difficult, since the framework designer needs to
anticipate all of the ways in which the framework is likely to be employed.
In exchange, though there is also more scope to make such a framework independent of specific programming
languages (such as occurs with CORBA), although other forms such as Java’s AWT (Abstract Window Toolkit) are
still essentially language-specific.
16.4 Object-based design
The HOOD (Hierarchical Object-Oriented Design) method
http://www.esa.int/TEC/Software_engineering_and_standardisation/TECKLAUXBQE_0.html
HOOD representation forms
The difficulty of identifying and modelling both problem and solution ‘objects’ using diagrammatical forms means
that, as one of the earliest methods, HOOD leans heavily on the use of written text to describe the abstract design
models. It does, however, have a diagrammatical representation, although this essentially provides only a
constructional viewpoint of the design model, and so is used mainly to represent the
outcome of design rather than to support the individual development steps. There are no specific forms used for
capturing behavioural, functional or data-modelling aspects of the object model.
HOOD concepts:
n HOOD recognizes the existence of both ‘passive’ and ‘active’ objects in a system. A passive object essentially
provides a service, in that it provides a set of operations and associated abstract data types. The operations of a
passive object can be activated only when control is passed to them directly, as occurs during the invocation
(calling) of a method. An active object can provide a parallel thread of execution that can respond to synchronous
and asynchronous ‘events’ (or timeouts) needed for handling real-time features. Active objects may interact with
both passive and active objects, but passive objects may make use only of other passive objects, and so cannot be
used to activate active objects.
n The hierarchy described in a HOOD diagram can also take two forms. The first is a uses hierarchy. Such a
hierarchy shows the dependence of one object on the services provided by other objects, as shown earlier in Figure
16.4. For this relationship, the above rules governing interaction between active and passive objects will apply, with
the added constraint that passive objects may not use one another in a cyclic manner. The second form of hierarchy
is based on functional composition, whereby an object may be internally composed from child objects. The child
objects provide the functionality of the enveloping object.
The basic form of representation used to denote a passive object is that shown in Figure 16.8. The outer bounds of
the object are indicated by a box with rounded corners. An object has an ‘object identifier’ at the top of the box, and
a ‘boundary box’ on its perimeter, which lists the ‘provided operations’ that are visible for this object. The uses
relationship is then represented by a broad arrow drawn between object boxes, as can be seen in Figure 16.9, which
shows such relationships between a number of passive objects.
6
An active object is described by essentially the same form, but an additional zigzag arrow is also drawn next to the
‘provided operations’ box to denote the use of an external trigger, in order to show that the associated ‘provided
operation’ is invoked in response to an event, rather than by a fully synchronous procedure call. (This aspect of the
notation seems rather clumsy.) Figure 16.10 shows an example of the representation of an active object.
The parent–child composition hierarchy is shown by drawing the child objects inside the parent object, as shown in
Figure 16.11. The provided operations of the parent object are also linked to those of the child objects, to indicate
which child object will be responsible for implementing each operation. In Figure 16.11, the objects Child_1 and
Child_2 supply the provided operations of the parent object. Data-flow
arrows can also be used to show the flow of data between child objects. Where an active object is composed in this
way, there is the added possibility of composing it from a mix of active and passive child objects. An example of
this is also shown in Figure 16.11, where Child_3 is a passive object.
7
Before concluding our description of the HOOD representation forms, we need to include a brief description of the
textual notation that is used to form an intermediary between the diagrammatical forms and the Ada language. (It
does not really play any part in the development of the object model, only in its eventual refinement.) The Object
Description Skeleton, or ODS, is a structured textual description of an object which refines and extends the
information provided in the diagrammatical notation.
In version 3.1 of HOOD, an ODS contains seven main sections, which provide structured descriptions of the
following object features.
1. The object definition, giving basic information about the object: name, whether passive or active, a textual
description of what it does, and a description of any constraints affecting it, such as synchronization with other
objects or events.
2. The provided interface specifies the resources that are provided by this object for use by other objects (types,
constants, operations (methods), exceptions).
3. The Object Control Structure (OBCS) is provided for active objects only, and is itself a structured description,
concerned primarily with object synchronization details (in terms of Ada-83’s rendez-vous mechanism).
4. The required interface describes the use made by the object of the resources that are provided from other objects.
5. Data and exception flows is a heading concerned with describing the flow of data and control between the object
and other objects.
6. The internals describes child objects and their use, as well as any types, constants, data and operations that are
used within the object.
7. The Operation Control Structure (OPCS) is a structured description of a provided operation, with an OPCS being
specified for each operation provided by the object.
8
From ftp://ftp.estec.esa.nl/pub/wm/anonymous/wme/Web/HUM.ps.gz : HOOD
USER MANUAL,
RELEASE 1.0, HOOD USERs GROUP, HOOD USER’sMANUAL
Issue: Working Document 1.0
Created: July 27, 1994
Reference: HUM3-1
Prepared by: HUM Working Group
Approved by: HOOD Technical Group
Diffusion HOOD USERs Group
9
10
11
The HOOD process
12
The overall strategy used in HOOD is described as ‘globally top-down’ in form, and it consists of a sequence of
refinements to an object-based model of the problem. The basic process can be summarized as a sequence of four
transformations, termed design ‘steps’. These are:
1. definition and analysis of the problem
2. elaboration of an informal strategy
3. formalization of the strategy
4. formalization of the solution
and for each step the HOOD design process identifies:
n the activities the designer should perform;
n the input ‘documents’ required;
n the output ‘documents’ to be generated;
n any validation procedures to be used.
An outline description of the main transformations involved in the HOOD design process is shown in Figure 16.12.
The first activity of the design process in step 1 requires the designer to perform an initial analysis of the problem.
This is really a major task, and ideally would itself be undertaken in an object-oriented fashion, so that the analysis
of the problem in terms of its constituent objects could be used to provide guidance to the designer in the next task,
which is to identify suitable candidates for solution (design) objects.
The first activity of the design process in step 1 requires the designer to perform an initial analysis of the problem.
This is really a major task, and ideally would itself be undertaken in an object-oriented fashion, so that the analysis
13
of the problem in terms of its constituent objects could be used to provide guidance to the designer in the next task,
which is to identify suitable candidates for solution (design) objects.
DFDs and SADT are, of course, based on the use of functional decomposition rather than on a true object-oriented
strategy, and indeed, the enforced separation of date storage and data processing is incompatible with the object
model. The unsatisfactory form of step 1 (in terms of building an object-oriented model from the beginning) leads to
the difficulties of step 2. This step essentially requires the
designer to ‘rough out’ an initial architectural solution to the problem, which can then be analysed to provide a more
detailed object-based design model.
Step 2 therefore has to act as a ‘bridge’ between the (possibly function-oriented) model produced by the analysis of
step 1, and the object-centred needs of the succeeding steps. Without doubt this remains an inelegant and poorly
structured transformation, and one that has probably most inhibited the further development of HOOD.
Object-Oriented design
The Fusion method
This was developed at HP Laboratories in the UK (1994) and, as implied by the name ‘Fusion’, the aim of the
development team was to integrate and extend the most successful elements of existing practices.
The Fusion representation forms
14
The Fusion process
Figure 16.14 summarizes the overall design process.
15
Step 1 (analysis): Develop the object model One of the tasks of this first step is to identify a set of candidate classes,
relationships and attributes to place in the data dictionary.
Step 2 (analysis): Determine the system interface This step extends the (essentially) static model developed in the
first step to describe the dynamic behaviour of the system as a whole. In so doing, it also clarifies the system bounds
by determining what is or is not included in the system itself. The designer is therefore encouraged to consider:
n how is the system to respond to external input events?
n what events are the system to generate when inputs are processed?
The process suggested for this is to identify a set of scenarios of system use. A further effect of this step is to extend
the data dictionary to include descriptions of both events (and the agents which instigate them) and also system
operations.
Step 3 (analysis): Development of the interface model There are two elements to this step, with one providing
assistance with the development of the second. The first element involves constructing a ‘life-cycle’ model
containing what are effectively use cases that generalize the scenarios produced in the previous step. (In Fusion
these are termed life-cycle expressions.)
The second element is the ‘operation model’ that defines the semantics (meaning) for each system operation in
terms of informal pre-condition and post-condition specifications, and hence can be considered as providing a
functional description of the system. These can (in part at least) be created by considering the effect of the life-cycle
model upon the system. The outcome from this is of course a new set of entries in the data dictionary that describe
the operations and their contexts.
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.48.5677&rep=rep1&type=pdf
tsiehnhiag aaic nttnthu.tcar achnnhi na,gareecr ads aocc nattts enheirds eriti yzz suees mposfdtathathkweteeeoadaelml _ntohdeowcr daottebuhl olgseef:hoaosuepuqtptpultiuec hntaecteeidvos eenvoneftslsesor eptvrhmvic eieec yns etsii enpnnvr dtooeccrteamos tsis.othnoesf Thenotati onus edintheObj ectM odelis ummariz edi nFigure
16
Step 4 (analysis): Check the analysis models The purpose of this step is to ensure completeness and consistency in
the analysis model, rather than to extend the model in any way, preliminary to beginning the white box design tasks.
An assessment of completeness is largely a matter of cross-referencing with the requirements specification, to
determine whether there are any aspects of this that have not been covered by the black box model produced from
the previous three steps. (Since requirements specifications are not necessarily complete in themselves, the
comparisons may of course identify gaps either in the specification or in the analysis model.) The primary concerns
here are to check the completeness of the set of scenarios
(life-cycles) and operations, and to ensure that all invariants have been recognized and included.
Assessing consistency is really a process of ensuring that the different viewpoint models developed in the previous
three steps form projections from the same overall design model. The constructional, behavioural and functional
models (and the invariants) need to be checked against each other. Techniques that can be used include using
scenarios to aid tracing of event paths through objects.
Step 5 (design): Develop object interaction graphs These are used to describe the designer’s intentions concerning
how the objects will interact at run-time in order to provide the required functionality, and so this forms the first step
in developing a white box model of the system. The step involves creating an object interaction graph for each
system operation and, in doing this, making any related decisions about message passing between objects and
resulting state changes to these. The sequences of messages
passing between the design objects then determines the combined functional behaviour of these objects. One of the
elements also clarified in this step is just when objects should be created from the classes. (Although the
descriptions tend to be couched in terms of objects, since these are the executable elements of the eventual system,
the model itself is really described in terms of classes, while recognizing that many classes will only lead to the
creation of a single instance or object.)
Each object interaction graph has a single controller object which has a message entering from outside the particular
set of objects involved in the operation, and also one or more collaborator objects which make up the rest of the set.
Identification of the controller is an important design decision, and may well involve comparing several candidate
object interaction graphs. In addition, new objects (classes) may need to be introduced in order to provide some of
the required functionality.
17
Download