9.1 What Is Mechanistic Design?


Mechanistic design is concerned with adding and organizing classes to optimize a single collaboration. The mechanistic design process elaborates the analysis model and iterates it by adding objects to facilitate a particular design. As mentioned in Chapter 8, a set of classes and objects working together is called a collaboration. A collaboration is specified in terms of specific classes playing named roles (called classifier roles). When the collaborators may be replaced with others that can fulfill those roles, the collaboration is called a pattern. The roles define, in an abstract sense, the formal parameter list for the pattern. When bound with an actual parameter list (the classes whose instances will actually play the part of those roles at runtime), the pattern may be instantiated into a collaboration. A mechanism [1] is a type of pattern that is limited in scope to a few classes (i.e., it does not have architectural scope), but is generally applicable in many circumstances.

A typical real-time system may have dozens or even hundreds of mechanisms operating concurrently. While the analysis model identifies the classes and objects fundamental to the problem domain, mechanistic design reorganizes and optimizes the interaction of these entities to facilitate their collaboration. A common example is the addition of container classes to handle multivalued roles[1] in associations.

[1] A multivalued role of an association is defined to be an association role with a nonunity multiplicity, such as (0,1) or *.

In the analysis model, many associations will have multivalued roles. For example:

  • A customer can have many bank accounts.

  • An autopilot can use many sensors and actuators.

  • A physiological parameter can be shown in many different views simultaneously.

The most common implementation of a one-to-one association is a pointer or reference in the client allowing the client to send messages to the server (i.e., to call one of the server's member functions), such as that shown in Code Listing 9-1.

Code Listing 9-1. A Sample Pointer
 class Actuator {      int value; public:     int gimme(void) { return value; };     void set(int v) { value = v; }; }; class Autopilot {     Actuator *s; public:     void AutoPilot(Server *YourActuator):       s(YourActuator) { };     void setIt(int a) { s->set(a); } // send msg to       Server object s     void IncIt(void) {         int a = s->gimme();         s->set(++a);     }; }; 

The class Autopilot uses pointer s to locate its Actuator object. It can then send the object messages like s->set(a) and s->gimme(). The use of a simple pointer is appropriate because the multiplicity of the association is one-to-one. But what if the association is one-to-many?

It is entirely possible to build the ability to manage collections of Actuator objects directly into the Autopilot class. A strategy could be used, such as using a vector, linked list, or binary tree to manage the collection by adding operations into the class Autopilot for adding, finding, sorting, and deleting these objects in the collection.

This simple approach has a number of drawbacks. First of all, the machinery to manage the collection is entirely unrelated to the primary purpose of the class Autopilot. Inserting such methods would obscure this purpose. Second, depending on the nature of the collection itself, the management of the collection may be quite complex, such as balancing AVL or red-black trees. Adding this behavior would make the class larger and more complex. Further, managing collections is a subject domain of its own and such collection class packages may be purchased. Indeed, C++ provides one called the Standard Template Library (STL); the Rhapsody tool provides another or can automatically use the STL. Building the behavior directly into the Autopilot class makes reuse of these libraries impossible. If the system has 20 classes with multivalued roles, this behavior must be rewritten for each such class. Building the behavior directly into each class that uses it makes changing to a different kind of collection much more difficult.

The more common approach is to introduce a new class during mechanistic design, one to handle the vagaries of managing the contained objects. Such a class is called a collection or container class. This allows third-party libraries to be used, separates out unrelated concerns of container management, and allows the type of collection to be changed fairly easily. The analysis model identified the association and its multiplicity, but the use of a container class is a design decision because it is a specific way to implement the analysis model. The use of collection classes is so common that it can be reified into a design pattern:

When a class must manage a number of objects of the same class, a useful design approach is to add a container class between the primary class and the set of multiple objects.

The rest of mechanistic design proceeds in a similar vein. Classes are added to facilitate the implementation of the analysis model. When generalized solutions can be applied to the specifics of a particular design, this is called applying the design pattern. This is nothing more than the classic elaborative or iterative development method repeated refinement of the model via reorganization and addition.

In the following section, we will present a number of design patterns that can be profitably applied in the design of real-time systems. The use of these patterns simplifies the system's design and allows reuse on a grander scale than the reuse of individual objects and classes.



Real Time UML. Advances in The UML for Real-Time Systems
Real Time UML: Advances in the UML for Real-Time Systems (3rd Edition)
ISBN: 0321160762
EAN: 2147483647
Year: 2003
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net