Purpose
|
To identify the design elements which formalize the seams in the system.
|
Interfaces define a set of operations which are realized by some classifier. In the Design Model, interfaces are
principally used to define the interfaces for subsystems. This is not to say that they cannot be used for classes as
well, but for a single class it is usually sufficient to define public operations on the class which, in effect, define
its 'interface'. Interfaces are important for subsystems because they allow the separation of the declaration of
behavior (the interface) from the realization of behavior (the specific classes within the subsystem which realize the
interface). This de-coupling provides us with a way to increase the independence of development teams working on
different parts of the system, while retaining precise definitions of the 'contracts' between these different parts.
For each subsystem, identify a set of candidate interfaces. Using the grouped collaborations identified in the
previous step, identify the responsibility which is 'activated' when the collaboration is initiated. This
responsibility is then refined by determining what information must be provided by the 'client' and what information is
returned when the collaboration is complete; these sets of information become the prototype input and output parameters
and return value for an operation which the subsystem will realize. Define a name for this operation, using the naming
conventions defined in the Artifact: Project-Specific Guidelines. Repeat this until all
operations which will be realized by the subsystem have been defined.
Next, group operations together according to their related responsibilities. Smaller groups are preferable to larger
groups, since it is more likely that a cohesive set of common responsibilities will exist if there are fewer operations
in the group. Keep an eye toward reuse as well - look for similarities that may make it easier to identify related
reusable functionality. At the same time, though, don't spend a great deal of time trying to find the ideal grouping of
responsibilities; remember, this is just a first-cut grouping and refinement will proceed iteratively throughout the
elaboration phase.
Look for similarities between interfaces. From the candidate set of interfaces, look for similar names, similar
responsibilities, and similar operations. Where the same operations exist in several interfaces, re-factor the
interfaces, extracting the common operations into a new interface. Be sure to look at existing interfaces as well,
re-using them where possible. The goal is to maintain the cohesiveness of the interfaces while removing redundant
operations between interfaces. This will make the interfaces easier to understand and evolve over time.
Define interface dependencies. The parameters and return value of each interface operation each have a
particular type: they must realize a particular interface, or they must be instances of a simple data type. In cases
where the parameters are objects that realize a particular interface, define dependency relationships between the
interface and the interfaces on which it depends. Defining the dependencies between interfaces provides useful coupling
information to the software architect, since interface dependencies define the primary dependencies between elements in
the design model.
Map the interfaces to subsystems. Once interfaces have been identified, create realization associations
between the subsystem and the interfaces it realizes. A realization from the subsystem to an interface indicates that
there are one or more elements within the subsystem that realize the operations of the interface. Later, when the
subsystem is designed, these subsystem-interface realizations will be refined, with the subsystem designer specifying
which specific elements within the subsystem realize the operations of the interface. These refined realizations are
visible only to the subsystem designer; from the perspective of the subsystem client, only the subsystem-interface
realization is visible.
Define the behavior specified by the interfaces. Interfaces often define an implicit state machine for the
elements that realize the interface. If the operations on the interface must be invoked in a particular order (e.g. the
database connection must be opened before it can be used), a state machine that illustrates the publicly visible (or
inferred) states that any design element that realizes the interface must support should be defined. This state machine
will aid the user of the interface to better understand the interface, and will aid the designer of elements which
realize the interface to provide the correct behavior for their element.
Package the interfaces. Interfaces are owned by the software architect; changes to interfaces are always
architecturally significant. To manage this, the interfaces should be grouped into one or more packages owned by the
software architect. If each interface is realized by a single subsystem, the interfaces can be placed in the same
package with the subsystem. If the interfaces are realized by more than one subsystem, they should be placed within a
separate package owned by the software architect. This allows the interfaces to be managed and controlled independently
of the subsystems themselves.
Purpose
|
To identify the design elements which formalize the seams in the system (RT design only).
|
Protocols are similar to interfaces in event-driven systems: they identify the 'contract' between capsules by defining
a matched set of signals which are used to communicate between independent threads of control. While interfaces are
primarily used to define synchronous messaging using a function call model of invocation, protocols are primarily used
to define asynchronous communication using signal-based messaging. Protocols allow the separation of the declaration of
behavior (the set of signals) from the realization of behavior (the elements within the subsystem which realize the
interface). This de-coupling provides us with a way to increase the independence of development teams working on
different parts of the system, while retaining precise definitions of the 'contracts' between these different parts.
For each capsule, identify a set of in and out signals. Using the grouped collaborations identified in earlier
steps, identify the responsibility which is 'activated' when the collaboration is initiated. This responsibility is
then refined by determining what information must be provided by the 'client' and what information is returned when the
collaboration is complete; these sets of information become the prototype input parameters for a signal which the
capsule will realize through one of its ports. Define a name for this signal, using the naming conventions defined in
the Artifact: Project-Specific Guidelines. Repeat this until all signals
which will be realized by the capsule have been defined.
Next, group signals together according to their related responsibilities. Smaller groups are preferable to larger
groups, since it is more likely that a cohesive set of common responsibilities will exist if there are fewer signals in
the group. Keep an eye toward reuse as well - look for similarities that may make it easier to identify related
reusable functionality. At the same time, though, don't spend a great deal of time trying to find the ideal grouping of
responsibilities; remember, this is just a first-cut grouping and refinement will proceed iteratively throughout the
elaboration phase. Give the protocol a meaningful name, one that describes the role the protocol plays in capsule
collaborations.
Look for similarities between protocols. From the candidate set of protocols, look for similar names, similar
responsibilities, and similar signals. Where the same signals exist in several protocols, re-factor the protocols,
extracting the common signals into a new interface. Be sure to look at existing protocols as well, re-using them where
possible. The goal is to maintain the cohesiveness of the protocols while removing redundant signals between protocols.
This will make the protocols easier to understand and evolve over time.
Map the protocols to capsules. Once protocols have been identified, create ports on the capsules which
realize the protocols. The ports of the capsule define its 'interfaces', the behavior that can be requested from the
capsule. Later, when the capsule is designed, the behavior specified by the ports will be described by the state
machine for the capsule.
Define the behavior specified by the protocols. Protocols often define an implicit state machine for the
elements that realize the interface. If the input signals on the interface must be received in a particular order (e.g.
a 'system-ready' signal must be received before a particular error signal can be received), a state machine that
illustrates the publicly visible (or inferred) states that any design element that realizes the protocol must support
should be defined. This state machine will aid the user of the capsules which realize the protocol to better understand
their behavior, and will aid the designer of capsules to provide the correct behavior for their element.
Package the protocols. Protocols are owned by the software architect; changes to protocols are always
architecturally significant. To manage this, the protocols should be grouped into one or more packages owned by the
software architect. This allows the protocols to be managed and controlled independently of the capsules which realize
the protocols.
|