Download (direct link):
For each of the DCEntityContract classes in our example, one attribute is stereotyped <<UniqueId>>, demonstrating that stereotypes can extend other UML metamodel elements besides Class. A UniqueId is an attribute whose values constitute unique identifiers for components that support the contract that the class defines. The fact that an attribute is a UniqueId is expressed by prepending the <<UniqueId>> keyword to the attribute declaration in the class box.
Figure 6.1's class model (partially) defines some contracts that components can support. As alluded to earlier, it is at a level of abstraction above component middleware such as EJB and .NET. A generator could refine this model into a middleware-specific UML model expressed in a middleware-specific profile, or it could directly produce artifacts for the chosen middleware. An EJB-specific generator, for example, would map a <<UniqueId>> stereotyped attribute to an EJB primary key class. Compilers targeting other middleware would map the <<UniqueId>> attribute differently.
Stereotypes can extend any kind of UML metamodel element. Our example profile has two stereotypes that extend the Class element and one that extends Attribute, but we could also define stereotypes that extend Association, Parameter, and so on. In fact, stereotypes are not limited to extending elements used for class modeling. They can also extend elements used for state modeling, activity modeling, and so forth.
It's also possible to define an icon for a stereotype, and to represent a stereotyped model element via the icon. Some people prefer denoting stereotypes via keywords and some by icons; it's largely a matter of personal taste, and UML's graphical notation permits either approach.
Tagged Values of Stereotypes
The definition of a stereotype can include the definition of tags. For example, the <<UniqueId>> stereotype of Attribute could define a tag that indicates whether the identifier's values are user-assigned or system-assigned. Other properties pertaining to unique identifiers that are not supported by the base UML language could be defined as tags of <<UniqueId>> as well.
148 Chapter 6
Figure 6.1 illustrates a simple way to encode values of tags—that is, tagged values—in a model. I've defined a tag for <<UniqueId>> named isUser-Assigned whose values can be true or false. Our class model encodes concrete values of this defined tag—false for Customer and Invoice and true for ReceivablesAccount. The encoding is delimited by curly braces, and the syntax inside the curly braces is <tag name> "=" <tagged value>.
Standalone Tagged Values
You can also define tags that are not part of any stereotype definition. The modeler adds the values of such tags to instances of the UML model elements that the tags extend.
For example, let's define two tags that extend the UML metamodel's Operation element. The first tag, named isTx indicates whether an operation is transactional, that is, whether it is necessary to roll back any state changes the operation makes if it is not completed successfully. This is an appropriate specification for a model at this abstraction level, even though at this level we do not specify the mechanism used to ensure transactional integrity.
The second tag, named isIdempotent, indicates whether an operation is idempotent, that is, whether it is benign to execute the operation more than once.
If you're not familiar with the concept of idempotency, consider a clustered, distributed infrastructure that seeks to recover gracefully from system failure by failing over to another system that resumes processing. Such a system can make good use of an idempotency indicator on operations. In certain situations it can be very expensive for the infrastructure to keep track of whether an operation that was in progress when failure occurred ever finished executing and thus whether the infrastructure needs to reexecute the operation automatically when fail over recovery occurs.
If an operation is marked as idempotent, a smart infrastructure does not pay the price to ensure that it knows, upon fail over, whether the operation has actually executed or not—it simply invokes the operation, knowing that if it executes a second time, no harm is done. It is appropriate to specify idempo-tency at our platform-independent abstraction level because it is a characteristic of the fundamental logic of the operation irrespective of whether the implementation platform is EJB, .NET, and so on.
Figure 6.2 encodes concrete values of the isTx and isIdempotent tags as part of operation declarations. Note that it's permissible to encode more than one tagged value within the curly braces and that a comma delimits the two values.
The ProcessInvoices operation is idempotent because it only handles unprocessed invoices. If it executes when all invoices have already been processed, it detects that there are no unprocessed invoices and does nothing else. This rule holds regardless of the middleware implementation platform and thus is appropriately manifested in the platform-independent model.