Executable UML: A Foundation for Model-Driven Architecture
When you start identifying classes in a new domain, you are likely to pick up a few candidates that appear to be classes when, in fact, they are not. Here are some checks that will help you reject these imposters. All of these checks require a firm grasp on the definition of the class. Each potential instance of a class should have the same characteristics and conform to the same rules as the others. (Interpret "rules" liberally here: laws, organizational policies, laws of physics, custom, and so forth.) In other words, each instance must have the same data and the same behavior as the others. If a class fails one or more of these checks, you may not have a good abstraction, or you may not have a good grasp of it. Writing down even one sentence to describe the abstraction will clarify your thinking greatly. We strongly recommend you do so as you invent your abstractions, no matter how agile your process. 5.5.1 Subject-Matter Check
Every class has to be a part of the domain at hand. For each candidate class, check it against the mission for the domain. If it does not support the mission, put the class into the domain it does support. For example, a class such as Login Screen more properly belongs in a user interface domain, as it represents a user interface concept and is not intrinsic to the Bookstore domain (the problem of selling books). Review the domain chart as you review the classes in each domain. 5.5.2 Abstraction Checks
Another set of checks examines the abstraction by looking at the class description. Note that problems with these checks could be the sign of a poorly written description as well as a poorly abstracted class. The OR check.
If the inclusion criteria stated in the description use the word "or" in a disjunctive way, you probably don't have a class, but a bunch of conglomerated ideas instead. For example, "A Drawing is an engineering drawing under formal revision control or the pictures my little girl made in kindergarten" is not OK, while "A Drawing is an engineering drawing or sketch under formal revision control" is. Note that in the previous sentence, the word "or" is used conjunctively to bring things together. The cure is to separate the kinds of things that have been mixed together. The more-than-a-list check.
If the inclusion criteria stated in the description amount only to a list of all the specific things, you probably don't have a good abstraction. For example, describing a Decadent Food[3] as a croissant, a cappuccino, a chocolate pie, a cheesecake, or a cannoli is just a list and provides the reader no basis for deciding whether some other food qualifies. Is a food that begins with "c," such as a cauliflower, also decadent? [3] This example is due to Leon Starr, who is fond of decadent things. Alternatively, "A Decadent Food is an addictive food that has a severely unhealthy effect. Every decadent food has an ecstasy rating and a death index" tells the reader what makes the food decadent. 5.5.3 Attribute Checks
Other checks look at the proposed class attributes. Problems with these checks could identify problems with the individual attribute or problems with the class itself. Composite value check.
Attributes in Executable UML may represent composite values, such as a MailingAddress (street, city, state, postal code) or a complex number (real and imaginary parts), only if the composite is treated as a single value. If you find that the components of a single value are important to the domain, then abstract one attribute for each component. For example, if the model needs to execute operations based on the city portion of the mailing address, or the area code of a telephone number, then each part should be abstracted as a separate attribute. There is a tension between composite types, such as mailing address, and the composite value check. Whether to represent a composite value as a single attribute or as many attributes depends upon the application of the attribute and its relationship to other values in the domain. Not-less-than-one check.
All attributes must have valid values for each thing, but sometimes an attribute has no value because it is not yet known. Consider, for example, the Shipment class in Figure 5.6. Figure 5.6. Accumulating AttributesThe value of the attribute timeDelivered is not known until the shipment's contents are delivered to the customer. In this case, we could choose to extend the domain of the attribute to include none, notKnown, undelivered, or (ugh!) null. But making up an otherwise unused name and extending the domain of the attribute to include it is make-work. Instead, we simply say the attribute has multiplicity 0..1. These situations, in which an object accumulates attribute values over time, are quite common. (Another example: A Customer's credit line amount is not determined until the customer's Credit Application is approved.) We'll see many such attributes, especially in classes with state machines.[4] [4] The stages of attribute value accumulation are often a good starting point for abstracting the states of a class. Never-meaningful attributes and nonuniform classes.
If, however, a zero multiplicity is trying to indicate "never meaningful," it may indicate an abstraction problem with the class. For example, the store sells more than just books; it also sells videotapes, CDs, DVDs, and computer software. All of these Products have a sale price and are identified by a universal product code (UPC). Books have an ISBN number, CDs, videotapes, and DVDs have a running time, computer software titles have version numbers. Consider a single Product class as in Figure 5.7. Figure 5.7. Never-Meaningful AttributesAttributes such as softwareProductVersion and recordingLength are never meaningful for some subset of instances. Having to ask "what kind of thing is it" in order to determine if an attribute is meaningful is a red flag that we have a uniformity problem. Remember that every attribute must be meaningful for the typical things at some time during the thing's life. The differences between objects are not "details" to be deferred. They are fundamental facts about the domain at hand.
Specialization (see Section 6.5: Generalization and Specialization) is a technique for solving such uniformity problems. Not-more-than-one check.
In Executable UML, all attributes must be single valued. A Book has multiple Authors; a SoftwareProduct runs on multiple Platforms; an Order has multiple ProductSelections. In such situations, create associations with related classes (see Section 6.1: Associations) and possibly introduce new association classes (Section 6.4: Association Classes). Sometimes the multiple values of a single attribute are really separate attributes with distinct meanings. Consider a (bad) Shipment attribute called timeList. The attribute description says: Shipment timeList: ListOfTimestamps Each of the times in the timeList represents the time and date when a specific event in the history of the Shipment occurs: when the shipment is packed, when it is picked up, when it is delivered, etc.
In this case, abstract separate Shipment attributes: timePrepared, timePickedUp, and timeDelivered, as in Figure 5.6. If the "etc." in the description means "there may be more events that we don't know yet," this is really a signal of an incomplete understanding. It may be true that there are multiple events in the history of the Shipment; in such cases, put the time in a separate but related ShippingEvent class. |