CS616 – Software
Engineering II
|
Lecture 5
|
Larman:
Chapter 10
DOMAIN
MODEL: VISUALIZING CONCEPTS
A domain model is a representation of real-world conceptual classes, not of software components. It is not a set of diagrams describing software classes, or software objects with responsibilities.
A domain model is widely used as a source of inspiration for designing software objects, and will be a required input to several subsequent artifacts discussed in this book. Therefore, it is important to read this chapter if the subject of domain modeling is unfamiliar.
A domain model illustrates meaningful (to the modelers) conceptual classes in a problem domain; it is the most important artifact to create during object-oriented analysis.1 This chapter explores introductory skills in creating domain models. The following two chapters expand on domain modeling skills—adding attributes and associations.
Identifying a rich set of objects or conceptual classes is at the heart of object-oriented analysis, and well worth the effort in terms of payoff during the design and implementation work.
The identification of conceptual classes is part of an investigation of the problem domain. The UML contains notation in the form of class diagrams to illustrate domain models.
The quintessential object-oriented step in analysis or
investigation is the decomposition of a domain of interest into individual
conceptual classes or objects— the things we are aware of. A domain model is a visual
representation of conceptual classes or real-world objects in a domain of
interest [M095, Fowler96]. They have also been called conceptual
models (the term used in the first edition of this book), domain object models, and analysis object models.2
The UP defines a Domain Model3 as one of the artifacts that may be created in the Business Modeling discipline.
Using UML notation, a domain model is illustrated with a set of class diagrams in which no operations are defined. It may show:
· domain objects or conceptual classes
· associations between conceptual classes
· attributes of conceptual classes
For example, Figure 10.1 shows a partial domain model. It illustrates that the conceptual class of Payment and Sale are significant in this domain, that a Payment is related to a Sale in a way that is meaningful to note, and that a Sale has a date and time. The details of the notation are not important at this time.
Please reflect on Figure 10.1 for a moment. It visualizes and relates some words or conceptual classes in the domain. It also depicts an abstraction of the conceptual classes, because there are many things one could communicate about registers, sales, and so forth. The model displays a partial view, or abstraction, and ignores uninteresting (to the modelers) details.
The information it illustrates (using UML notation) could alternatively have been conveyed in prose, in statements in the Glossary or elsewhere. But it is easy to comprehend the discrete elements and their relationships in this visual language, since a significant percentage of the brain participates in visual processing—it is a human strength.
Thus, the domain model may be considered a visual dictionary of the noteworthy abstractions, domain vocabulary, and information content of the domain.
A domain model, as shown in Figure 10.2, is a visualization of things in the realworld domain of interest, not of software components such as a Java or C++ class (see Figure 10.3), or software objects with responsibilities. Therefore, the following elements are not suitable in a domain model:
· Software artifacts, such as a window or a database, unless the domain being modeled is of software concepts, such as a model of graphical user interfaces.
· Responsibilities or methods.
The domain model illustrates conceptual classes or vocabulary in the domain. Informally, a conceptual class is an idea, thing, or object. More formally, a conceptual class may be considered in terms of its symbol, intension, and extension [M095] (see Figure 10.4).
· Symbol—words or images representing a conceptual class.
· Intension—the definition of a conceptual class.
· Extension—the set of examples to which the conceptual class applies.
For example, consider the conceptual class for the event of a purchase transaction. I may choose to name it by the symbol Sale. The intension of a Sale may state that it “represents the event of a purchase transaction, and has a date and time.” The extension of Sale is all the examples of sales; in other words, the set of all sales.
When creating a domain model, it is usually the symbol and intensional view of a conceptual class that are of most practical interest.
Software problems can be complex; decomposition—divide-and-conquer—is a common strategy to deal with this complexity by division of the problem space into comprehensible units. In structured analysis, the dimension of decomposition is by processes or functions. However, in object-oriented analysis, the dimension of decomposition is fundamentally by things or entities in the domain.
A central distinction between object-oriented and structured analysis is: division by conceptual classes (objects) rather than division by functions.
Therefore, a primary analysis task is to identify different concepts in the problem domain and document the results in a domain model.
For example, in the real-world domain of sales in a
store, there are the conceptual classes of Store,
Register, and Sale. Therefore, our
domain model, shown in Figure 10.5, may include Store, Register, and Sale.
Store Register Sale
Figure 10.5 Partial domain model in the domain of
the store.
Our goal is to create a domain model of interesting or meaningful
conceptual classes in the domain of interest (sales). In this case, that means
concepts related to the use case Process
Sale.
In iterative development, one incrementally builds a domain model over several iterations in the elaboration phase. In each, the domain model is limited to the prior and current scenarios under consideration, rather than a “big bang” model which early on attempts to capture all possible conceptual classes and relationships. For example, this iteration is limited to a simplified cash-only Process Sale scenario; therefore, a partial domain model will be created to reflect just that—not more.
The central task is therefore to identify conceptual classes related to the scenarios under design.
The following is a useful guideline in identifying conceptual classes:
It is better to overspecify a domain model with lots of fine-grained conceptual classes than to underspecify it.
Do not think that a domain model is better if it has fewer conceptual classes; quite the opposite tends to be true.
It is common to miss conceptual classes during the initial identification step, and to discover them later during the consideration of attributes or associations, or during design work. When found, they may be added to the domain model.
Do not exclude a conceptual class simply because the requirements do not indicate any obvious need to remember information about it (a criterion common in data modeling for relational database design, but not relevant to domain modeling), or because the conceptual class has no attributes.
It is valid to have attributeless conceptual classes, or conceptual classes which have a purely behavioral role in the domain instead of an information role.
Two techniques are presented in the following sections:
1. Use a conceptual class category list.
2. Identify noun phrases.
Another excellent technique for domain modeling is the use of analysis patterns, which are existing partial domain models created by experts, using published resources such as Analysis Patterns [Fowler96] and Data Model Patterns [Hay9 6].
Start the creation of a domain model by making a list of candidate
conceptual classes. Table 10.1 contains many common categories that are usually
worth considering, though not in any particular order of importance. Examples
are drawn from the store and airline reservation domains.
Conceptual Class Category |
Examples |
physical or
tangible objects |
Register Airplane |
specifications,
designs, or descriptions of things |
ProductSpecification FlightDescription |
places |
Store Airport |
transactions |
Sale, Payment Reservation |
transaction
line items |
SalesLineltem |
roles of
people |
Cashier Pilot |
containers of
other things |
Store, Bin Airplane |
things in a
container |
Item Passenger |
other computer
or electro-mechanical systems external to the system |
CreditPaymentAuthorizationSystem AirTrafficControl |
abstract noun
concepts |
Hunger |
organizations |
SalesDepartment ObjectAirline |
events |
Sale, Payment, Meeting Flight, Crash, Landing |
processes |
SellingAProduct BookingASeat |
rules and
policies |
RefundPolicy CancellationPolicy |
catalogs |
ProductCatalog PartsCatalog |
records of
finance, work, contracts, legal matters |
Receipt, Ledger, EmploymentContract Main
tenanceLog |
financial
instruments and services |
LineOfCredit Stock |
manuals, documents,
reference papers, books |
DailyPriceChangeList
RepairManual |
Table 10.1 Conceptual Class Category List.
Another useful technique (because of its simplicity) suggested in [AbbotS3I is linguistic analysis: identify the nouns and noun phrases in textual descriptions of a domain, and consider them as candidate conceptual classes or attributes.
Care must be applied with this method; a mechanical noun-to-class mapping isn’t possible, and words in natural languages are ambiguous.
Nevertheless, it is another source of inspiration. The fully dressed use cases are an excellent description to draw from for this analysis. For example, the current scenario of the Process Sale use case can be used.
Main
Success Scenario (or Basic Flow):
1 Customer arrives
at a P0S checkout with goods and/or services
to
purchase.
2. Cashier
starts a new sale.
3. Cashier
enters item identifier.
4. System records sale line item and presents item description, price, and running total. Price calculated from a set of price rules.
Cashier repeats steps 2-3
until indicates done.
5. System
presents total with taxes calculated.
6. Cashier tells Customer the total, and asks for payment.
7. Customer
pays and System handles payment.
8. System logs the completed sale and sends sale and payment information to the external Accounting (for accounting and commissions) and Inventory systems (to update inventory).
9. System
presents receipt.
10 Customer leaves with receipt and goods (if any).
Extensions (or Alternative
Flows):
…
7a. Paying by cash:
1.
Cashier enters the cash amount tendered.
2. System
presents the balance due, and releases the cash drawer.
3. Cashier deposits
cash tendered and returns balance in cash to Customer.
4. System
records the cash payment.
The domain model is a visualization of noteworthy domain concepts and vocabulary. Where are those terms found? In the use cases. Thus, they are a rich source to mine via noun phrase identification.
Some of these noun phrases are candidate conceptual classes, some may refer to conceptual classes that are ignored in this iteration (for example, “Accounting” and “commissions”), and some may be attributes of conceptual classes. Please see the subsequent section and chapter on attributes for advice on distinguishing between the two.
A weakness of this approach is the imprecision of natural language; different noun phrases may represent the same conceptual class or attribute, among other ambiguities. Nevertheless, it is recommended in combination with the Conceptual Class Category List technique.
From the Conceptual Class Category List and noun phrase
analysis, a list is generated of candidate conceptual classes for the domain.
The list is constrained to the requirements and simplifications currently under
consideration—the simplified scenario of Process
Sale.
Register |
ProductSpecification |
Item |
SalesLineltem |
Store |
Cashier |
Sale |
Customer |
Payment |
Manager |
ProductCatalog |
|
There is no such thing as a “correct” list. It is a somewhat arbitrary collection of abstractions and domain vocabulary that the modelers consider noteworthy Nevertheless, by following the identification strategies, similar lists will be produced by different modelers.
A receipt is a record of a sale and payment and a relatively prominent conceptual class in the domain, so should it be shown in the model?
Here are some factors to consider:
· A receipt is a report of a sale. In general, showing a report of other information in a domain model is not useful since all its information is derived from other sources; it duplicates information found elsewhere. This is one reason to exclude it.
· A receipt has a special role in terms of the business rules: it usually confers the right to the bearer of the receipt to return bought items. This is a reason to show it in the model.
Since item returns are not being considered in this iteration, Receipt will be excluded. During the iteration that tackles the Handle Returns use case, it would be justified to include it.
Apply the following steps to create a domain model:
1. List the candidate conceptual classes using the Conceptual Class Category List and noun phrase identification techniques related to the current requirements under consideration.
2. Draw them in a domain model.
3. Add the associations necessary to record relationships for which there is a need to preserve some memory (discussed in a subsequent chapter).
4. Add the attributes necessary to fulfill the information requirements (discussed in a subsequent chapter).
An adjunct useful method is to learn and copy analysis patterns, which are discussed in a later chapter.
The mapmaker strategy applies to both maps and domain models.
Make a domain model in the spirit of how a cartographer or mapmaker works:
· Use the existing names in the territory.
· Exclude irrelevant features.
· Do not add things that are not there.
A domain model is a kind of map of concepts or things in a domain. This spirit emphasizes the analytical role of a domain model, and suggests the following:
· A mapmaker uses the names of the territory—they do not change the names of cities on a map. For a domain model, this means use the vocabulary of the domain when naming conceptual classes and attributes. For example, if developing a model for a library, name the customer a “Borrower” or “Patron”—the terms used by the library staff.
· A mapmaker deletes things from a map if they are not considered relevant to the purpose of the map; for example, topography or populations need not be shown. Similarly, a domain model may exclude conceptual classes in the problem domain not pertinent to the requirements. For example, we may exclude Pen and PaperBag from our domain model (for the current set of requirements) since they do not have any obvious noteworthy role.
· A mapmaker does not show things that are not there, such as a mountain that does not exist. Similarly, the domain model should exclude things not in the problem domain under consideration.
The principle is also named the Use the Domain Vocabulary strategy [Coad9S].
Perhaps the most common mistake when creating a domain model is to represent something as an attribute when it should have been a concept. A rule of thumb to help prevent this mistake is:
If we do not think of some conceptual class X as a number or text in the real world, X is probably a conceptual class, not an attribute.
As an example, should store
be an attribute of Sale, or a
separate conceptual class Store?
Sale |
|
or...? |
Sale |
|
Store |
store |
|
|
|
|
phoneNumber |
In the real world, a store is not considered a number or text—the term suggests a legal entity, an organization, and something occupies space. Therefore, Store should be a concept.
As another example, consider the domain of airline
reservations. Should destination be
an attribute of Flight, or a separate
conceptual class Airport?
Flight |
or...? |
Flight |
|
Airport |
destination |
|
|
|
name |
In the real world, a destination airport is not considered a number or text—it is a massive thing that occupies space. Therefore, Airport should be a concept.
POST stands for point-of-sale terminal. In computerese, a terminal is any
endpoint device in a system, such as a client PC, a wireless networked PDA,
and so forth. In earlier times, long before POSTs, a store maintained a register—a book that logged sales and
payments. Eventually, this was automated in a mechanical “cash register.”
Today, a POST fulfills the role of the register (see Figure10.6).
A register is a thing that records sales and payments, but
so is a POST. However, the term register
seems somewhat more abstract and less implementation oriented than POST. So, in the domain model, should the symbol Register be used instead of P0577?
First, as a rule of thumb,
a domain model is not absolutely correct or wrong, but more or less useful;
it is a tool of communication. |
By the mapmaker principle, “POST” is a term familiar in the territory, so it is a useful symbol from the point of view of familiarity and communication. By the goal of creating models that represent abstractions and are implementation independent, Register is appealing and useful.5 Register may be fairly considered to represent both the conceptual class of a place to register sales, andlor an abstraction of various kinds of terminals, such as a POST.
Both choices have merit; Register has been chosen in this case study somewhat arbitrarily, but POST would also have been understandable to the stakeholders.
Figure 10.6 POST and register are similar conceptual classes.
Some software systems are for domains that find very little analogy in natural or business domains; software for telecommunications is an example. It is still possible to create a domain model in these domains, but it requires a high degree of abstraction and stepping back from familiar designs.
For example, here are some candidate conceptual classes
related to a telecommunication switch: Message,
Connection, Port, Dialog, Route, Protocol.
The following discussion may at first seem related to a rare, highly specialized issue. However, it turns out that the need for specification conceptual classes (as will be defined) is common in many domain models. Thus, it is emphasized.
Assume the following:
· An Item instance represents a physical item in a store; as such, it may even have a serial number.
· An Item has a description, price, and itemlD, which are not recorded anywhere else.
· Everyone working in the store has amnesia.
· Every time a real physical item is sold, a corresponding software instance of Item is deleted from “software land.”
With these assumptions, what happens in the following scenario?
There is strong demand for the popular new vegetarian burger—ObjectBurger. The store sells out, implying that all Item instances of ObjectBurgers are deleted from computer memory
Now, here is the heart of the problem: If someone asks, “How much do Object-Burgers cost?”, no one can answer, because the memory of their price was attached to inventoried instances, which were deleted as they were sold.
Notice also that the current model, if implemented in software as described, has duplicate data and is space-inefficient because the description, price, and itemlD are duplicated for every Item instance of the same product.
The preceding problem illustrates the need for a concept of objects that are specifications or descriptions of other things. To solve the Item problem, what is needed is a ProductSpecification (or ItemSpecification, ProductDescription, ...) conceptual class that records information about items. A ProductSpecification does not represent an Item, it represents a description of information about items. Note that even if all inventoried items are sold and their corresponding Item software instances are deleted, the ProductSpecifications still remain.
Description or specification objects are strongly related to the things they describe. In a domain model, it is common to state that an XSpecification Describes an X (see Figure 10.7).
The need for specification conceptual classes is common in sales and product domains. It is also common in manufacturing, where a description of a manufactured thing is required that is distinct from the thing itself Time and space have been taken in motivating specification conceptual classes because they are very common; it is not a rare modeling concept.
The following guideline suggests when to use specifications:
Add a specification or description conceptual class (for example, ProductSpecification) when:
· There needs to be a description about an item or service, independent of the current existence of any examples of those items or services.
· Deleting instances of things they describe (for example, Item) results in a loss of information that needs to be maintained, due to the incorrect association of information with the deleted thing.
· It reduces redundant or duplicated information.
As another example, consider an airline company that suffers a fatal crash ol one of its planes. Assume that all the flights are cancelled for six months pending completion of an investigation. Also assume that when flights are cancelled. their corresponding Flight software objects are deleted from computer memory Therefore, after the crash, all Flight software objects are deleted.
If the only record of what airport a flight goes to is in the Flight softwarE instances, which represent specific flights for a particular date and time, then there is no longer a record of what flight routes the airline has.
Note that the prior example is about a service (a flight) rather than a good (such as a veggieburger). Descriptions of services or service plans are commonly needed.
As another example, a mobile phone company sells packages
such as “bronze,” “gold,” and so forth. It is necessary to have the concept of
a description of the package (a kind of service plan describing rates per
minute, wireless Internet content, the cost, and so forth) separate from the
concept of an actual sold package (such as “gold package sold to Craig Larman
on Jan 1, 2002 at $55 per month”). Marketing needs to define and record this
service plan or MobileCommunicationsPackageDescription
before any are sold.
The UP defines something called a Domain Model, which is illustrated with UML notation. However, there is no term “Domain Model” to be found in the official UML documentation. This points to an important insight:
The UML simply describes
raw diagram types, such as class diagrams and sequence diagrams. It does not
superimpose a method or modeling perspective on these. Rather, a process
(such as the UP) applies raw UML in the context of methodologist-defined
models. |
For example, raw UML class diagramming notation can be used to create pictures of domain conceptual classes (a domain model), software classes, relational database tables, and so forth.
Thus, do not confuse the basic UML diagram notation with its application to visualizing various kinds of models defined by methodologists (see Figure 10.9). This point applies not only to UML class diagrams, but to most UML notation.
As another example of raw diagrams being interpreted differently in different models, UML sequence diagrams can be used to illustrate messaging between software objects (as in the UP Design Model), or interaction between people and parties in the real world (as in the UP Business Object Model).
This insight was emphasized in the Syntropy object-oriented method rCD94I, and reiterated by Martin Fowler in UML Distilled [FSOO]. That is, the same diagramming notation may be used for three perspectives and types of models:
1. Essential or conceptual perspective—the diagrams are interpreted as describing things in the real world or domain of interest.
2. Specification perspective—the diagrams (using the same notation as for essential models) are interpreted as describing software abstractions or components with specifications and interfaces, but no commitment to a particular implementation (for example, not specifically a class in C# or Java).
3. Implementation perspective—the diagrams (using the same notation as for essential models) are interpreted as describing software implementations in a particular technology and language (such as Java).
In the raw UML, the rectangular boxes shown in Figure 10.9 are called classes, but note that in the UML, this term encompasses a variety of phenomenon— physical things, software things, events, and so forth.6 A process or method will superimpose alternative terminology on top of the UML. For example, in the UP, when the IJML boxes are drawn in the Domain Model, they may be called domain concepts or conceptual classes; the Domain Model offers a conceptual perspective. In the UP, when UML boxes are drawn in the Design Model, they are officially called design classes; the Design Model offers a specification or implementation perspective, as desired by the modeler.
Regardless of the definition, the bottom line is that it is useful to distinguish between the perspective of an analyst looking at real-world concepts such as a sale (a conceptual perspective), and software designers specifying software components such as a Sale software class (a specification or implementation perspective).
The UML can be used to illustrate both perspectives with very similar notation and terminology, so it is important to bear in mind which perspective is being taken.
To keep things clear, this
book will use class-related terms as follows, which is consistent with the
IJML and the IJP: · Conceptual class—real-world concept
or thing. A conceptual or essential perspective. The IJP Domain Model contains
conceptual classes. · Software class—a class representing a
specification or implementation perspective of a software component,
regardless of the process or method. · Design class—a member of the IJP Design Model. It is a synonym
for software class, but for some reason I wish to emphasize that it is a
class in the Design Model. The IJP allows a design class to be either a
specification or implementation perspective, as desired by the modeler. · Implementation class—a class implemented in an
object-oriented language such as Java. · Class—as in the IJML, the general term representing either a
real-world thing (a conceptual class) or software thing (a software class). |
Please consider Figure 10.10. Why do books and educators discussing object design common only show the use of software classes whose names reflect domain vocabulary? Why choose a software class name such as Sale, and what does a Sale do?
Simply, choosing names that reflect the domain vocabulary (Sale) enhances quick comprehension and provides a clue as to what to expect from the chunk of code in a Sale software class. We have a mental or domain model of the domain in question (for example, a store selling things). In the real world, we know that a sale has a date. Consequently, if we create a Java class named Sale, and give it the responsibility of knowing about a real sale and its date, then the Java class Sale somewhat corresponds to our mental or domain model of the real domain; that is, it appeals to our “intuitions” of the domain.
This relates to the issue of representational
gap or
semantic gap—the gap between our mental model of the domain and its
representation in software. |
The Domain Model provides a visual dictionary of the domain
vocabulary and concepts from which to draw inspiration for the naming of some
things in the software design.
At one extreme, we could directly program the NextGen POS application in raw binary code to invoke the processor instruction set. We understand that the gap in representations is huge, and there will be a real cost—albeit hard to quantify—in software with such a large representational gap because it is hard to comprehend or relate to the problem domain. Closer to the other end of the spectrum are object technologies that allow us to chunk code into classes whose names reflect the kind of chunking we perceive in the domain. In the real world we perceive a chunk” (or event) called a sale, so in software land we have a software class called Sale. This closer one-to-one mapping between the domain vocabulary and our software vocabulary and its chunking reduces the representational gap. This speeds comprehension of existing code (because it works in ways we expect, knowing the domain) and suggests “natural” ways to extend the code in ways that similarly correspond to the domain, or appeal to our intuitions of the domain. Put simply, the software model reminds us of the conceptual or mental model, and works in predictable ways.
There is a practical advantage to software models that reduce the representational gap. Most software engineers know this is true, even if it is hard to quantify Indeed, a proof of this is that Java obfuscators make source code hard to practically reverse-engineer from bytecode by changing the names of Java
classes and methods so they are unintelligible, and thus no longer appeal to our intuitions of the domain, even though the control and data structures are unchanged.
Of course, object technology is also of value because it can support the design of elegant, loosely coupled systems that scale and extend easily, as will be explored in the remainder of the book. A lowered representational gap is useful, but arguably secondary to the advantage of objects to support ease of change and extension, and their support to manage and hide complexity.
The list of conceptual classes generated for the NextGen POS domain may
be represented graphically (see Figure 10.11) to show the start of the Domain
Model.
Register |
|
Item |
|
Store |
|
Sale |
|
|
|
||||||
Sales Lineltem |
|
Cashier |
|
Customer |
|
Manager |
|
|
|
||||||
Payment |
|
Product Catalog |
|
Product Specification |
|
|
|
Figure 10.11 Initial Domain Model.
Consideration of attributes and associations for the Domain Model will be deferred to subsequent chapters.
As suggested in the example of Table 10.2, a Domain Model is usually both started and completed in elaboration.
Domain models are not strongly motivated in inception, since inception’s purpose is not to do a serious investigation, but rather to decide if the project is worth deeper investigation in an elaboration phase.
Discipline |
Artifact |
Incep. |
Elab. |
Const. |
Trans. T1..T2 |
Business Modeling |
Domain Model |
|
s |
|
|
Requirements |
IJse-Case Model (SSDs) |
s |
r |
|
|
Vision |
s |
r |
|
|
|
Supplementary Specification |
s |
r |
|||
Glossary |
s |
r |
|||
Design |
Design Model |
|
s |
r |
|
SW Architecture Document |
|
s |
|
|
|
Data Model |
|
|
r |
|
|
Implementation |
Implementation Model |
|
s |
r |
r |
Project Management |
SW Development Plan |
s |
r |
r |
r |
Testing |
Test Model |
|
s |
r |
|
Environment |
Development Case |
s |
r |
|
|
Table 10.2 Sample IJP artifacts and timing. 5 - start; r - refine
The Domain Model is primarily created during elaboration iterations, when the need is highest to understand the noteworthy concepts and map some to software classes during design work.
Although ironically a significant number of pages will be devoted to explaining domain object modeling, in experienced hands the development of a (partial, incrementally growing) domain model in each iteration should only take a few hours. This is further shortened by the use of predefined analysis patterns.
The IJP Domain Model is an official variation of the less common IJP Business Object Model (BOM). The IJP BOM—not to be confused with how other people or methods may define a BOM, which is a widely used term with different meanings—is a kind of enterprise model used to describe the entire business. It may be used when doing business process engineering or reengineering, independent of any one software application (such as the NextGen POS). To quote:
[The IJP BOM] serves as an abstraction of how business workers and business entities need to be related and how they need to collaborate in order to perform the business. [RIJP]
The BOM is represented with several different diagrams (class, activity, and sequence) that illustrate how the entire enterprise runs (or should run). It is most useful if doing enterprise-wide business process engineering, but that is a less common activity than creating a single software application.
Consequently, the IJP defines the Domain Model as the more commonly created subset artifact or specialization of the BOM. To quote:
You can choose to develop an “incomplete” business object model, focusing on explaining “things” and products important to a domain.... This is often referred to as a domain model. [RIJP]
It is useful to identify those associations of conceptual classes that are needed to satisfy the information requirements of the current scenarios under development, and which aid in comprehending the domain model. This chapter explores the identification of suitable associations, and adds associations to the domain model for the NextGen case study
An association is a relationship between types (or more specifically, instances of those types) that indicates some meaningful and interesting connection (see Figure 11.1).
In the UML associations are defined as “the semantic relationship between two or more classifiers that involve connections among their instances.”
Figure 11.1 Associations.
Criteria for Useful Associations
Associations worth noting usually imply knowledge of a relationship that needs to be preserved for some duration—it could be milliseconds or years, depending on context. In other words, between what objects do we need to have some memory of a relationship? For example, do we need to remember what SalesLineltem instances are associated with a Sale instance? Definitely, otherwise it would not be possible to reconstruct a sale, print a receipt, or calculate a sale total.
Consider including the following associations in a domain model:
· Associations for which knowledge of the relationship needs to be preserved for some duration (“need-to-know” associations).
· Associations derived from the Common Associations List.
By contrast, do we need to have memory of a relationship between a current Sale and a Manager? No, the requirements do not suggest that any such relationship is needed. It is not wrong to show a relationship between a Sale and Manager, but it is not compelling or useful in the context of our requirements.
This is an important point. On a domain model with n different conceptual classes, there can be n*(n-1) associations to other conceptual classes—a potentially large number. Many lines on the diagram will add “visual noise” and make it less comprehensible. Therefore, be parsimonious about adding association lines. Use the criterion guidelines suggested in this chapter.
An association is represented as a line between classes with an association name. The association is inherently bidirectional, meaning that from instances of either class, logical traversal to the other is possible.
This traversal is purely abstract; it is not a statement about connections between software entities.
Figure
11.2 The UML notation for associations.
The ends of an association may contain a multiplicity expression indicating the numerical relationship between instances of the classes.
An optional “reading direction arrow” indicates the direction to read the association name; it does not indicate direction of visibility or navigation.
If not present, it is conventional to read the association from left to right or top to bottom, although the UML does not make this a rule (see Figure 11.2).
The reading direction arrow has no meaning in terms of the model; it is only an aid to the reader of the diagram.
Start the addition of associations by using the list in Table 11.1.
It contains common categories that are usually worth considering. Examples are drawn from the store and airline reservation domains.
Category |
Examples |
|
A is a
physical part of B |
Drawer—Register (or more specif
ically, a POST) Wing—Airplane |
|
A is a logical part of B |
SalesLineltem—Sale FlightLeg—FlightRoute |
|
A is physically contained in/on B |
Register—Store, Item—Shelf
Passenger—Airplane |
|
A is logically contained in B |
ItemDescription—Catalog Flight—FlightSchedule |
|
A is a description for B |
ItemDescription—Item
FlightDescription—Flight |
|
A is a line item of a transaction or report B |
SalesLineltem—Sale |
|
A is knownflogged/recordedlreported!cap-tured in B |
Sale—Register |
|
A is a member of B |
Cashier—Store Pilot—Airline |
|
A is an organizational subunit of B |
Department—Store Maintenance—Airline |
|
A uses or manages B |
Cashier—Register Pilot—Airplane |
|
A communicates with B |
Customer—Cashier
ReservationAgent—Passenger |
|
A is related to a transaction B |
Customer—Payment Passenger—Ticket |
|
A is a transaction related to another trans-action B |
Payment—Sale |
|
A is next to B |
SalesLineltem—SalesLineltem City—City |
|
A is owned
by B |
Register—Store Plane—Airline |
|
A is an event related to B |
Sale—Customer, Sale—Store
Departure—Flight |
|
Table
11.1 Common Associations List.
Here are some high-priority association categories that are invariably useful to include in a domain model:
· A is a physical or logical part of B.
· A is physically or logically contained in/on B.
· A is recorded in B.
· Focus on those associations for which knowledge of the relationship needs to be preserved for some duration (“need-to-know” associations).
· It is more important to identify conceptual classes than to identify associations.
· Too many associations tend to confuse a domain model rather than illuminate it. Their discovery can be time-consuming, with marginal benefit.
· Avoid showing redundant or derivable associations.
Each end of an association is called a role. Roles may optionally have:
· name
· multiplicity expression
· navigability
Multiplicity is examined next, and the other two features are discussed in later chapters.
Multiplicity defines how many instances of a class A can be associated with one instance of a class B (see Figure 11.3).
Figure 11.3 Multiplicity on an association.
For example, a single instance of a Store can be associated with “many” (zero or more,indicated by the * ) Item instances.
Some examples of multiplicity expressions are shown in Figure 11.4.
Figure 11.4 Multiplicity values.
The multiplicity value communicates how many instances can be validly associated with another, at a particular moment, rather than over a span of time. For example, it is possible that a used car could be repeatedly sold back to used car dealers over time. But at any particular moment, the car is only Stocked-by one dealer. The car is not Stocked-by many dealers at any particular moment. Similarly, in countries with monogamy laws, a person can be Married-to only one other person at any particular moment, even though over a span of time, they may be married to many persons.
Multiplicity should “1” or
“0..1”?
The answer depends on our
interest in using the model. Typically and practically, the muliplicity
communicates a domain constraint that we care about being able to check in
software, if this relationship was implemented or reflected in software objects
or a database. For example, a particular item may become sold or discarded, and
thus no longer stocked in the store. From this viewpoint, “0.1” is logical, but
Do we care about that
viewpoint? If this relationship was implemented in software, we would probably
want to ensure that an /tem software instance would always be related to 1
particular Store instance, otherwise
it indicates a fault or corruption in the software elements or data.
This partial domain model
does not represent software oblects, but the multiplicities record constraints
whose practical value is usually related to our interest in building software
or databases (that reflect our real-world domain) with validity checks. From
this viewpoint, “1” may be the desired value.
The multiplicity value is dependent on our interest as a modeler and software developer, because it communicates a domain constraint that will be (or could be) reflected in software. See Figure 11.5 for an example and explanation.
Figure 11.5 Multiplicity is context dependent.
Rumbaugh gives another example of Person and Company in the Works-for association [Rumbaugh9 1]. Indicating if a Person instance works for one or many Company instances is dependent on the context of the model; the tax department is interested in many; a union probably only one. The choice usually practically depends on whom we are building the software for, and thus the valid multiplicities in an implementation.
Associations are important, but a common pitfall in creating domain models is to spend too much time during investigation trying to discover them.
It is critical to appreciate the following:
Finding conceptual classes is more important than finding associations. The majority of time spent in domain model creation should be devoted to identifying conceptual classes, not associations.
Name an association based on a TypeName-VerbPhrase-TypeName format where the verb phrase creates a sequence that is readable and meaningful in the model context.
Association names should start with a capital letter, since an association represents a classifier of links between instances; in the UML, classifiers should start with a capital letter. Two common and equally legal formats for a compound association name are:
· Paid-by
· PaidBy
In Figure 11*6, the default direction to read an association name is left to right or top to bottom. This is not a IJML default, but a common convention.
Two types may have multiple associations between
them; this is not uncommon. There is no outstanding example in our P05 case study, but an example
from the domain of the airline is the relationships between a Flight (or perhaps more precisely, a FlightLeg) and an Airport (see Figure 11.7); the flying-to and flying-from
associations are distinctly different relationships, which should be shown
separately
Figure 11.7 Multiple associations.
During domain modeling, an association is not a statement about data flows, instance variables, or object connections in a software solution; it is a statement that a relationship is meaningful in a purely conceptual sense—in the real world. Practically speaking, many of these relationships will typically be implemented in software as paths of navigation and visibility (both in the Design Model and Data Model), but their presence in a conceptual (or essential) view of a domain model does not require their implementation.
When creating a domain model, we may define associations that are not necessary during implementation. Conversely, we may discover associations that need to be implemented but were missed during domain modeling. In these cases, the domain model can be updated to reflect these discoveries.
Suggestion
Should prior investigative models such as a domain model be updated with insights (such as new associations) revealed during implementation work? Do not bother unless there is some future practical use for the model. If it is just (as is sometimes the case) a temporary artifact used to provide inspiration for a later step, and will not be meaningfully used later on, why update it? Avoid making or updating any documentation or model unless there is a concrete justification for future use.
Later on we will discuss ways to implement associations in an object-oriented programming language (the most common is to use an attribute that references an instance of the associated class), but for now, it is valuable to think of them as purely conceptual expressions, not statements about a database or software solution. As always, deferring design considerations frees us from extraneous information and decisions while doing pure “analysis” investigations and maximizes our design options later on.
We can now add associations to our P05 domain model. We should add those associations which the requirements (for example, use cases) suggest or imply a need to remember, or which otherwise are strongly suggested in our perception of the problem domain. When tackling a new problem, the common categories of associations presented earlier should be reviewed and considered, as they represent many of the relevant associations that typically need to be recorded.
The following sample of associations is justified in terms of a need-to-know. It is based on the use cases currently under consideration.
Register Records Sale |
To know the current sale, generate a total, print a
receipt. |
Sale Paid-by Payment |
To know if the sale has been paid, relate the amount
tendered to the sale total, and print a receipt |
ProductCatalog Records ProductSpecification |
To retrieve an ProductSpecification, given an itemlD |
We will run through the checklist, based on previously identified types, considering the current use case requirements.
Category |
System |
A is a physical part of B |
Register—CashD rawer |
A is a logical part of B |
SalesLineltem—Sale |
A is physically contained in/on B |
Register—Store Item—Store |
A is logically contained in B |
ProductSpecification—Product- |
A is a description for B |
ProductSpecification—Item |
A is a line item of a transaction or report B |
SalesLineltem—Sale |
A is logged!recorded!reported!captured in B |
(completed) Sales—Store (current)
Sale—Register |
A is a member of B |
Cashier—Store |
A is an organizational subunit of B |
not applicable |
A uses or manages B |
Cashier—Register |
A communicates with B |
Customer—Cashier |
A is related to a transaction B |
Customer—Payment Cashier—Payment |
A is a transaction related to another trans-action B |
Payment—Sale |
A is next to B |
SalesLineltem—SalesLineltem |
A is owned by B |
Register—Store |
The domain model in Figure 11.8 shows a set of conceptual classes and associations that are candidates for our POS application. The associations were primarily derived from the candidate association checklist.
The set of associations shown in the domain model of Figure 11.8 were, for the most part, mechanically derived from the association checklist. However, it may be desirable to be more choosy in the associations included in our domain model. Viewed as a tool of communication, it is undesirable to overwhelm the domain model with associations that are not strongly required and which do not illuminate our understanding. Too many uncompelling associations obscure rather than clarify
As previously suggested, the following criteria for showing associations is recommended:
· Focus on those associations for which knowledge of the relationship needs to be preserved for some duration (“need-to-know” associations).
· Avoid showing redundant or derivable associations.
Based on this advice, not every association currently shown is compelling. Con-sider the following:
Association |
Discussion |
Sale Entered-by Cashier |
The requirements do not indicate a need-to-know or record the current cashier. Also, it is derivable if the Register Used-by Cashier asso ciation is present. |
Register Used-by Cashier |
The requirements do not indicate a need-to-know or record the current cashier. |
Register Started-by Manager |
The requirements do not indicate a need-to-know or record the manager who starts up a Register. |
Sale Initiated-by Customer |
The requirements do not indicate a need-to-know or record the current customer who ini tiates a sale. |
Store Stocks Item |
The requirements do not indicate a need-to-know or maintain inventory information. |
SalesLineltem Records-sale-of
Item |
The requirements do not indicate a need-to-know or maintain inventory information. |
Note that the ability to justify an association in terms of need-to-know is dependent on the requirements; obviously a change in these—such as requiring that the cashier’s ID show on a receipt—changes the need to remember a relationship.
Based on the above analysis, it may be justifiable to delete the associations in question.
A strict need-to-know criterion for maintaining associations will generate a minimal “information model” of what is needed to model the problem domain— bounded by the current requirements under consideration. However, this approach may create a model that does not convey (to us or anyone else) a full understanding of the domain.
In addition to being a need-to-know model of information about things, the domain model is a tool of communication in which we are trying to understand and communicate to others important concepts and their relationships. From this viewpoint, deleting some associations that are not strictly demanded on a need-to-know basis can create a model that misses the point—it does not communicate key ideas and relationships.
For example, in the POS application: although on a strict need-to-know basis it might not be necessary to record Sale Initiated-by Customer, its absence leaves out an important aspect in understanding the domain—that a customer generates sales.
In terms of associations, a good model is constructed somewhere between a minimal need-to-know model and one that illustrates every conceivable relationship. The basic criterion for judging its value?—Does it satisfy all need-to-know requirements and additionally clearly communicate an essential understanding of the important concepts in the problem domain?
Emphasize need-to-know associations, but add choice comprehension-only associations to enrich critical understanding of the domain.
It is useful to identify those attributes of conceptual classes that are needed to satisfy the information requirements of the current scenarios under development. This chapter explores the identification of suitable attributes, and adds attributes to the domain model for the NextGen domain model.
An attribute is a logical data value of an object.
Include the following attributes in a domain model: Those for which the requirements (for example, use cases) suggest or imply a need to remember information.
For example, a receipt (which reports the information of a sale) normally includes a date and time, and management wants to know the dates and times of sales for a variety of reasons. Consequently, the Sale conceptual class needs a date and time attribute.
Attributes are shown in the second compartment of the class box (see Figure 12.1). Their type may optionally be shown.
Figure 12.1 Class and attributes.
There are some things that should not be represented as attributes, but rather as associations. This section explores valid attributes.
Intuitively, most simple attribute types are what are often thought of as primitive data types, such as numbers. The type of an attribute should not normally be a complex domain concept, such as a Sale or Airport. For example, the following currentRegister attribute in the Cashier class in Figure 12.2 is undesirable because its type is meant to be a Register, which is not a simple attribute type (such as Number or String). The most useful way to express that a Cashier uses a Register is with an association, not with an attribute..
The attributes in a domain model should preferably be simple attributes or data types.
Very common attribute data types include: Boolean, Date, Number, String (Text), Time
Other common types include: Address, Color, Geometries (Point, Rectangle), Phone Number, Social
Security Number, Universal Product Code (UPC), SKU~ ZIP or postal codes, enumerated
types
To repeat an earlier example, a common confusion is modeling a complex domain concept as an attribute. To illustrate, a destination airport is not really a string; it is a complex thing that occupies many square kilometers of space. Therefore, Flight should be related to Airport via an association, not with an attribute, as shown in Figure 12.3.
Relate conceptual classes with an association, not with an attribute.
The restriction that attributes in the domain model be only of simple data types does not imply that C++ or Java attributes (data members, instance fields) must only be of simple, primitive data types. The domain model focuses on pure conceptual statements about a problem domain, not software components.
Later, during desigu and implementation work, it will be seen that the associations between objects expressed in the domain model will often be implemented as attributes that reference other complex software objects. However, this is but one of a number of possible design solutions to implement an association, and so the decision should be deferred during domain modeling.
|
Attributes should generally be data types. This is a UML term that implies a set of values for which unique identity is not meaningful (in the context of our model or system) [RJB99]. For example, it is not (usually) meaningful to distinguish between:
· Separate instances of the Number 5.
· Separate instances of the String ‘cat’.
· Separate instances of PhoneNumber that contain the same number.
· Separate instances of Address that contain the same address.
By contrast, it is meaningful to distinguish (by identity) between two separate instances of a Person whose names are both “Jill Smith” because the two instances can represent separate individuals with the same name.
In terms of software, there are few situations where one would compare the memory addresses of instances of Number, String, PhoneNumber, or Address; only value-based comparisons are relevant. By contrast, it is conceivable to compare the memory addresses of Person instances, and to distinguish them, even if they had the same attribute values, because their unique identity is important.
Thus, all primitive types (number, string) are UML data types, but not all data types are primitives. For example, PhoneNumber is a non-primitive data type.
These data type values are also known as value objects.
The notion of data types can get subtle. As a rule of thumb, stick to the basic test of “simple” attribute types: Make it an attribute if it is naturally thought of as number, string, boolean, date, or time (and so on); otherwise, represent it as a separate conceptual class.
The type of an attribute may be expressed as a non-primitive class in its own right in a domain model. For example, in the POS system there is an item identifier. It is typically viewed as just a number. So should it be represented as a non-primitive class? Apply this guideline:
Represent what may initially be considered a primitive data type (such as a number or string) as a non-primitive class if:
· It is composed of separate sections.
o phone number, name of person
· There are operations usually associated with it, such as parsing or validation.
o social security number
· It has other attributes.
o promotional price could have a start (effective) date and end date
· It is a quantity with a unit.
o payment amount has a unit of currency
· It is an abstraction of one or more types with some of these qualities.
o item identifier in the sales domain is a generalization of types such as Universal Product Code (UPC) or European Article Number (EAN)
Applying these guidelines to the POS domain model attributes yields the following analysis:
· The item identifier is an abstraction of various common coding schemes, including UPC-A, UPC-E, and the family of EAN schemes. These numeric coding schemes have subparts identifying the manufacturer, product, country (for EAN), and a check-sum digit for validation. Therefore, there should be a non-primitive ItemID class, because it satisfies many of the guidelines above.
· The price and amount attributes should be non-primitive Quantity or Money classes because they are quantities in a unit of currency
· The address attribute should be a non-primitive Address class because it has separate sections.
The classes ItemID, Address, and Quantity are data types (unique identity of instances is not meaningful) but they are worth considering as separate classes because of their qualities.
Should the ItemID class be shown as a separate conceptual class in a domain model? It depends on what you want to emphasize in the diagram. Since ItemID is a data type (unique identity of instances is not important), it may be shown in the attribute compartment of the class box, as shown in Figure 12.4. But since it is a non-primitive class, with its own attributes and associations, it may be interesting to show it as a conceptual class in its own box. There is no correct answer; it depends on how the domain model is being used as a tool of communication, and the siguificance of the concept in the domain.
A domain model is a tool of communication; choices about what is shown should be made with that consideration in mind.
Attributes should not be used to relate conceptual classes in the domain model. The most common violation of this principle is to add a kind of foreign key attribute, as is typically done in relational database desigus, in order to associate two types. For example, in Figure 12.5 the currentRegisterNumber attribute in the Cashier class is undesirable because its purpose is to relate the Cashier to a Register object. The better way to express that a Cashier uses a Register is with an association, not with a foreign key attribute. Once again, relate types with an association, not with an attribute.
There are many ways to relate objects—foreign keys being
one—and we will defer how to implement the relation until desigu, in order to
avoid design creep.
Most numeric quantities should not be represented as plain numbers. Consider price or velocity. These are quantities with associated units, and it is common to require knowing the unit, and to support conversions. The NextGen POS software is for an international market and needs to support prices in multiple currencies. In the general case, the solution is to represent Quantity as a distinct conceptual class, with an associated Unit [Fowler96]. Since quantities are considered data types (unique identity of instances is not important), it is acceptable to collapse their illustration into the attribute section of the class box (see Figure 12.6). It is also common to show Quantity specializations. Money is a kind of quantity whose units are currencies. Weight is a quantity with units such as kilograms or pounds.
The attributes chosen reflect the requirements for this iteration—the Process Sale scenarios of this iteration.
Payment |
amount—To
determine if sufficient payment was provided, and to calculate change, an
amount (also known as “amount tendered”) must be captured.
|
Product-Specification |
description—To show the description on a display or receipt. |
|
id—To look up a ProductSpecification, given an entered
itemID, it is necessary to relate them to a id. |
|
price—To calculate the sales total, and show the line item price. |
Sale |
date, time—A receipt is a
paper report of a sale. It normally shows date and time of sale.
|
SalesLineltem |
quantity—To record the
quantity entered, when there is more than one item in a line item sale (for
example, five packages of tofu).
|
Store |
address, name—The receipt requires the name and address of the store. |
It is possible for a cashier to receive a group of like items (for example, six tofu packages), enter the itemID once, and then enter a quantity (for example, six). Consequently, an individual SalesLineltem can be associated with more than one instance of an item.
The quantity that is entered by the cashier may be recorded as an attribute of the SalesLineltem (Figure 12.8). However, the quantity can be calculated from the actual multiplicity value of the relationship, so it may be characterized as a derived attribute—one that may be derived from other information. In the UML, a derived attribute is indicated with a “/“ symbol.
Combining the conceptual classes, associations, and attributes discovered in the previous investigation yields the model illustrated in Figure 12.9.
A relatively useful domain model for the domain of the P08 application has been created. There is no such thing as a single correct model. All models are approximations of the domain we are attempting to understand. A good domain model captures the essential abstractions and information required to understand the domain in the context of the current requirements, and aids people in understanding the domain—its concepts, terminology, and relationships.
Contracts for operations can help define system behavior; they describe the outcome of executing system operation in terms of state changes to domain objects. This chapter explores their use.
Use cases are the primary mechanism in the UP to describe system behavior, and are usually sufficient. However, sometimes a more detailed description of system behavior has value. Contracts describe detailed system behavior in terms of state changes to objects in the Domain Model, after a system operation has executed.
Contracts may be defined for system operations—operations that the system as a black box offers in its public interface to handle incoming system events. System operations can be identified by discovering these system events, as shown in Figure 13.1.
Figure 13.1 System operations handle input system events.
The entire set of system operations, across all use cases, defines the public system interface, viewing the system as a single component or class. In the UML, the system as a whole can be represented by a class.
Before examining the reason to write a contract, an example is worthwhile. The following describes a contract for the enterltem system operation.
Contract
C02: enteritem
Operation: Cross References: Preconditions: |
enterltem(itemlD:
ItemID, quantity: integer) Use Cases: Process
Sale There is a sale
underway. |
Postconditions: |
— A SalesLineltem instance sli was created
(instance creation). — sli was associated with the current Sale
(association formed). — sli.quantity became quantity (attribute
modification). — sli was
associated with a ProductSpecification, based on itemlD match (association
formed). |
A description of each section in a contract is shown in the following schema.
Operation: |
Name of operation, and
parameters |
Cross References: |
(optional) Use cases this
operation can occur within |
Preconditions: |
Noteworthy assumptions about the state of the
system or objects in the Domain Model before execution of the operation.
These will not be tested within the logic of this operation, are assumed to
be true, and are non-trivial assumptions the reader should know were made. |
Postconditions: |
The state of objects in
the Domain Model after completion of the operation. Discussed in detail in a
following section. |
Notice that each of the postconditions in the enterltem example included a categorization such as instance creation or association formed. Here is a key point:
The postconditions describe changes in the state of objects in the Domain Model. Domain Model state changes include instances created, associations formed or broken, and attributes changed.
Postconditions are not actions to be performed during the
operation; rather, they are declarations about the Domain Model objects that
are true when the operation has finished—after the smoke has cleared.
To summarize, the postconditions fall into these categories:
· Instance creation and deletion.
· Attribute modification.
· Associations (to be precise, UML links) formed and broken.
As an example of a post-condition that breaks an association, consider an operation to allow the deletion of line items. The post-condition could read “The selected SalesLineltem’s association with the Sale was broken.” In other domains, when a loan is paid off or someone cancels their membership in something, associations are broken.
Instance deletion postconditions are most rare, because one does not usually care about explicitly enforcing the destruction of a thing in the real world. However, as an example: In many countries, after a person has declared bankruptcy and seven or ten years have passed, all records of their bankruptcy declaration must be destroyed, by law. Note that this is a conceptual perspective, not implementation. These are not statements about freeing up memory in a computer occupied by software objects.
The important quality is to be declarative and state change-oriented rather than action-oriented, since postconditions are declarations about states or outcomes rather than a description of actions to execute, or a design of a solution.
These postconditions are expressed in the context of the Domain Model objects. What instances can be created?—those from the Domain Model; What associations can be formed?—those in the Domain Model; and so on.
Expressed in a declarative state-change fashion, the contract is an excellent tool for requirements analysis that describes the state changes required of a system operation (in terms of the Domain Model objects) without having to describe how they are to be achieved. In other words, the software design and solution can be deferred, and one can focus analytically on what must happen, rather than how it is to be accomplished. Furthermore, the postconditions support finegrained detail and specificity in declaring what the outcome of the operation must be.
It is also possible to express this level of detail in the use cases, but usually undesirable, as they would then become overly verbose and detailed.
Consider the postconditions:
Postconditions: — A SalesLineltem
instance sli was created (instance creation).
— sli was associated with the current Sale (association formed).
—
sli.quantity became quantity (attribute modification).
—
sli was associated with a ProductSpecification, based on itemlD match
(association formed).
No comment is made about how a SalesLineltem instance is created, or associated with a Sale. This could be a statement about writing on bits of paper and stapling them together, using Java technologies to create software objects and connect them, or inserting rows in a relational database.
Express postconditions in the past tense, to emphasize they are declarations about a state change in the past. For example:
· (better) A SalesLineltem was created.
rather than
· (worse) Create a SalesLineltem.
Think about postconditions using the following image:
The system and its objects are presented on a theatre stage.
1. Before the operation, take a picture of the stage.
2. Close the
curtains on the stage, and apply the system operation (background noise of clanging, screams, and screeches...).
3. Open the curtains and take a second picture.
4. Compare the
before and after pictures, and express as postconditions the changes in the
state of the stage (A SalesLineltem was
created...).
First, contracts may not be needed. This question is discussed in a subsequent section. But assuming some contracts are desired, generating a complete and detailed set of postconditions for a system operation is not likely—or even necessary—during requirements work. Treat their creation as an initial best guess, with the understanding that the contracts will not be complete. Their early creation—even if incomplete—is certainly better than deferring this investigation until design work, when developers should be concerned with the design of a solution, rather than investigating what should be done.
Some of the fine details—and perhaps even larger ones—will be discovered during the design work. That is not necessarily a bad thing; there is a diminishing return on effort expended during requirements analysis if it is drawn out too long. Some discovery naturally arises during design work, which can then inform the requirements work of a later iteration. This is one of the advantages of iterative development: discoveries generated during a prior iteration can enhance the investigation and analysis work of the following one.
The following section dissects the motivation for the postconditions of the enter-Item system operation.
After the itemlD and quantity of an item have been entered, what new object should have been created? A SalesLineltem. Thus:
· A SalesLineltem instance sli was created (instance creation).
Note the naming of the instance. This name will simplify references to the new instance in other post-condition statements.
After the itemlD and quantity of an item have been entered by the cashier, what attributes of new or existing objects should have been modified? The quantity of the SalesLineltem should have become equal to the quantity parameter. Thus:
· sli.quantity became quantity (attribute modification).
After the itemlD and quantity of an item have been entered by the cashier, what associations between new or existing objects should have been formed or broken? The new SalesLineltem should have been related to its Sale, and related to its Prod uetSpeeification. Thus:
· sli was associated with the current Sale (association formed).
· sli was associated with a ProductSpecification, based on itemlD match (association formed).
Note the informal indication that it forms a relationship with a particular ProductSpecification—the one whose itemlD matches the parameter. More fancy and formal language approaches are possible, such as using the Object Constraint Language (OCL). Recommendation: Keep it plain and simple.
It is common during the creation of the contracts to discover the need to record new conceptual classes, attributes, or associations in the Domain Model. Do not be limited to the prior definition of the Domain Model; enhance it as you make new discoveries while thinking through the operation contracts.
The use cases are the main repository of requirements for the project. They may provide most or all of the detail necessary to know what to do in the desigu, in which case, contracts are not helpful. However, there are situations where the details and complexity of required state changes are awkward to capture in use cases.
For example, consider an airline reservation system and the system operation addNewReservation. The complexity is very high regarding all the domain objects that must be changed, created, and associated. These fine-grained details can be written up in the use case associated with this operation, but it will make the use case extremely detailed (for example, noting each attribute in all the objects that must change).
Observe that the contract post-condition format offers and encourages a very precise, analytical, exacting language that supports detailed thoroughness.
If, just based on the use cases and through ongoing (verbal) collaboration with a subject matter expert, the developers can comfortably understand what to do, then avoid writing contracts.
However, in those situations were there is high complexity and detailed precision adds value, contracts are another requirements tool.
They will not be practically motivated very often, so if a team is making contracts for every system operation of every use case, it is a warning that either the use cases are poorly done, there is not enough ongoing collaboration or access to a subject matter expert, or the team is doing too much unnecessary documentation.
This NextGen POS case study shows more contracts than are probably necessary, for educational reasons. In practice, most of the details they record are obviously inferable from the use case text. On the other hand, “obvious” is a very slippery concept.
Apply the following advice to create contracts:
To make contracts:
1. Identify system operations from the SSDs.
2. For system operations that are complex and perhaps subtle in their results, or which are not clear in the use case, construct a contract.
3. To describe
the postconditions, use the following categories:
o instance creation and deletion
o attribute modification
o associations formed and broken
· State the postconditions in a declarative, passive past tense form (was ...) to emphasize the declaration of a state change rather than a design of how it is going to be achieved. For example:
o (better) A SalesLineltem was created.
o (worse)
Create a SalesLineltem.
· Remember to establish a memory between existing objects or those newly created by defining the forming of an association. For example, it is not enough that a new SalesLineltem instance is created when the enterltem operation occurs. After the operation is complete, it should also be true that the newly created instance was associated with Sale; thus:
o The SalesLineltem was associated with the Sale (association formed).
The most common problem is forgetting to include the forming of associations. Particularly when new instances are created, it is very likely that associations to several objects need be established. Don’t forget!
Operation: Cross References: Preconditions: |
makeNewSaleo Use Cases: Process
Sale none |
Postconditions: |
— A Sale instance s
was created (instance creation). — s was associated
with the Register (association formed). — Attributes of s
were initialized. |
Note the vague description in the last post-condition. If sufficient, this is fine.
On a project, all these particular postconditions are so obvious from the use case that the inakeNewSale contract should probably not be written.
Recall one of the guiding principles of healthy process and the UP: Keep it as light as possible, and avoid all artifacts unless they really add value.
Operation: Cross References: Preconditions: |
enterltem(itemlD :
ItemID, quantity: integer) Use Cases: Process Sale There is a sale
underway. |
Postconditions: |
— A
SalesLineltem instance sli was created (instance creation). — s/i was associated with the current Sale
(association tormed). — sli.quantity became quantity (attribute
moditication). — sli was associated with a ProductSpecification, based on itemlD match (association tormed). |
Operation: Cross References: Preconditions: |
endSale() Use Cases: Process Sale There
is a sale underway |
Postconditions: |
- Sale.isComplete became
true (attribute modification) |
Operation: Cross References: Preconditions: |
makePayment(
amount: Money) Use Cases: Process
Sale There is a sale
underway. |
Postconditions: |
— A Payment instance p was created (instance
creation). — p.amount Tendered became amount (attribute
moditication). — p was associated with the current Sale
(association tormed). — The current Sale was associated with the
Store (association tormed); (to add it to the historical log ot completed
sales) |
There is one datum suggested by these contracts that is not yet represented in the domain model: completion of item entry to the sale. The endSale specification modifies it, and it is probably a good idea later during design work for the makePayment operation to test it, to disallow payments until a sale is complete.
One way to represent this information is with an isComplete attribute in the Sale, of boolean data type:
Sale |
isComplete: Boolean date time |
There are alternatives, especially considered during design work. One technique is called the State pattern, which is explored in Chapter 34. Another is the use of “session” objects that track the state of a session and disallow out-of-order operations; this too will be explored later.
The UML formally defines operations. To quote:
An operation is a specification of a transformation or query that an object may be called to execute [RdB99]
For example, the elements of an interface are operations, in UML terms. An operation is an abstraction, not an implementation. By contrast, a method (in the UML) is an implementation of an operation.
A UML operation has a signature (name and parameters), and also an operation specification, which describes the effects produced by executing the operation; that is, the postconditions. The UML operation specification format is flexible, and does not have be the contract format shown in this chapter. However, the UML documents give as examples the contract style with pre- and postconditions, as this is the most well-known approach to formal operation specifications.
To summarize: The UML defines operation specifications, which are specifiable in the pre- and post-condition contract style. Note that, as emphasized in this chapter, a UML operation specification may not show an algorithm or solution, but only the state changes or effects of the operation.
In addition to using contracts to specify public operations of the entire System (system operations), contracts can be applied to operations at any level of granularity: the public operations (or interface) of a subsystem, an abstract class, and so forth. The operations discussed in this chapter belong to a System class. In the UML operations belong to classes. Furthermore, in the UML, “subsystems” are modeled as classes (and simultaneously also as packages). In the UML, the overall “system” is the top-level subsystem, and modeled as a class named System (actually, any name is legal) with public operations and specifications.
Operation Contracts Expressed with the OCL
Associated with the UML is a formal language called the Object Constraint Language (OCL) [WK99], which can be used to express constraints in models. The OCL could be used instead of the informal natural language used in this chapter; the UML allows any format for an operation specification.
Suggestion
Unless there is a compelling practical reason to require people to learn and use the OCL, keep things simple and use natural language.
The OCL defines an official format for specifying pre- and postconditions for operations, as demonstrated in this fragment:
pre
: <statements in OCL>
post
The pre- and post-condition contract form used for UML operation specifications has been promoted for many years by Bertrand Meyer, formalized in a design approach called Design by Contract [Meyer97 (first ed. 1989)1, although its origin is from earlier work in the 1960s on formal specification languages. In Design by Contract, contracts are also written for operations of fine-grained classes, not only the public operations of systems or subsystems.
In addition, Design by Contract promotes the inclusion of an invariant section, as is common in thorough contract specifications. Invariants define things that must not change state before and after the operation has executed. Invariants have not been used in this chapter for the sake of simplicity.
Some languages, such as Eiffel, have first-class support for invariants and preand postconditions. There are pre-processors that provide similar support in Java.
A pre- and postcondition contract is a well-known style to specify an operation in the UML. In the UML, operations exists at many levels, from System down to fine-grained classes, such as Sale. Operation specification contracts for the System level are part of the Use-Case Model, although they were not formally highlighted in the original RUP or UP documentation; their inclusion in this model was verified with the RUP authors.1
Inception——Contracts are not motivated during inception——they are too detailed.
Elaboration——If used at all, most contracts will be written during elaboration, when most use cases are written. Only write contracts for the most complex and subtle system operations.