Create Ports and Bind to Protocols
Consider the responsibilities of the capsule, creating an initial set of port classes. These port classes represent the
'interfaces' to the capsule. Port classes represent the realization of a Artifact: Protocol, which in turn represents a set of in and out signals used to communicate with capsules.
In creating ports, consider the Checklist: Protocol to determine whether the Protocol is appropriate. The port should reflect a singular set of related
responsibilities; having a similarly scoped protocol enables its re-use across a number of capsules. Once the
appropriate protocol is selected, bind the port to the appropriate protocol.
|
Validate Capsule Interactions
Once the ports are bound to protocols, the external behavior of the capsule must be evaluated and validated. Using
either manual walk-through techniques or automated simulation tools, test the behavior of the capsule by simulating the
events that will exercise the capsule behavior. Validation will also consider the capsules which interact with the
capsule under design. Using automated tools, write stub code within the capsule to allow the ports to be tested. When
errors in protocol or port definition, or in capsule responsibilities are detected, make appropriate changes to
capsule, port and protocol definitions.
|
Define Capsule State Machine
Once the capsule ports and protocols have been validated, define the internal behavior of the capsule. The behavior of
the capsule is defined using a statechart diagram. Reference: Guideline: Statechart Diagram . Other general capsule information can be obtained from the Guideline: Capsule , Checklist: Capsule.
First, identify the states in which the capsule can exist. The states must be unique (a capsule cannot be in two states
simultaneously) and descriptive. See the appropriate guidelines and checkpoints for more information.
Once states are defined, consider the transitions between states. Transition code should read like high level
application pseudo-code, it should consist primarily of real-time operating system service calls e.g., frame services,
time services, port operations, capsule operations and passive class operations.
When adding detail code to a Capsule transition:
-
If the code would be useful in other transitions consider delegating it to a Capsule operation.
-
Consider if the code implements capabilities which conform to the Capsule's responsibility.
When defining a Capsule operation:
-
Consider if the function would be useable at any time from any transition in the Capsule, and if whether any of the
work being done would ever be useful elsewhere in the system. If it is consider delegating it to a passive class
function.
-
If the code is too application-specific to be stored in a particular Data class, consider creating an additional
Data class as an abstraction for that code.
-
If the code handles data structure manipulation (e.g., maintaining lists), or performs complex (more than 1 line)
computations then it should be pushed into a data class.
|
Define Requirements on Passive Classes
Based on the capsule state machines, examine the passive classes referenced by the capsule. If there are new
requirements on these classes, change requests need to be generated to effect the required changes. If new classes have
been identified, the requirements on these classes (most specifically the required operations on them) should be
gathered together and the classes should be created. These classes will be further described in the Task: Class Design.
|
Introduce Capsule Inheritance
Capsule inheritance is used to implement generalization-specialization, to make use of polymorphism, to reuse
implementation. The key word here is 'implementation' - it is a technique that is used primarily to re-use the internal
structure of capsules, not the external behavior of capsules.
Inheritance is often misapplied to achieve something that could more easily have been achieved using simpler design
techniques.
Using inheritance for generalization-specialization
There are three kinds of inheritance. Listed from lowest complexity (most desirable) to most complex (least desirable),
they are:
-
Interface inheritance - just inherits ports and protocols, this is the type of inheritance that is most
desirable
-
Structural inheritance - inherits interface plus structural containment hierarchies (useful for frameworks)
-
Behavioral inheritance - in addition to interface and structural inheritance, also reuses behavioral code
and state machines
Structural and behavioral inheritance pose some problems:
-
The very strong degree of coupling provided by inheritance causes changes to cascade to subclasses when changes are
made to superclasses.
-
The need to override and delete superclass behavior and structure in subclasses indicates inappropriate use of
inheritance (usually for tactical code re-use). Re-factoring classes and capsules and appropriate use of delegation
is a more appropriate strategy.
-
Inheritance means moving design decisions up the class hierarchy, causing undesirable design and compilation
dependencies.
Other problems include:
-
Decisions may not be appropriate in all usage situations.
-
Introducing inheritance actually makes reuse more difficult, since design elements are more tightly coupled.
-
The design becomes more fragile because any new requirement that invalidates the decision causes large problems.
-
The design has to be made extremely flexible to compensate, which is often difficult. This is what makes designing
reusable frameworks such an effort!
All designs containing structure/behavior have decisions and assumptions built in (either explicit or implicit). The
critical question to ask is: are you absolutely sure that decision/assumption will always be valid? If not, what can
you do to remove it or make it possible to change?
|
Validate Capsule Behavior
As a final step, the behavior of the capsule must be evaluated and validated. Using either manual walk-through
techniques or automated simulation tools, the behavior of the capsule should be tested by simulating the events that
will exercise the capsule behavior. In addition, the internal structure of the capsule should be validated, ensuring
that not only the external behavior but also the internal implementation of that behavior is validated. Using automated
tools, stub code may need to be written to simulate the implementation of passive data classes and external capsules
with which the capsule interacts. Defects detected should be documented and appropriate changes to capsule definitions
should be made.
|
|