Chapter 5. Requirements Analysis of Real-Time Systems

Real-time systems interact with their external environment. The set of external objects of significance and their interactions with the system form the basis for the requirements analysis of the system. In the UML, this is captured by the use case model. A use case is a system capability that is detailed with accompanying text, examples (scenarios) or state models. The use case model decomposes the primary functionality of the system and the protocols necessary to meet these functional requirements.

Notations and Concepts Discussed

Actors

State

Statechart

Events

Use Case Diagrams

Scenarios

Sequence Diagram

Requirements

Requirements are specifications of what a system must do independently of how the system is designed. Requirements are not first-order elements defined in the UML; however, they are specified to be in the upcoming UML Profile for Systems Engineering [1]. A taxonomy of requirements is shown in Figure 5-1. A set of requirements specifies one or more systems, while in turn a system realizes a set of requirements. Use cases organize sets of requirements. Requirements are validated by tests applied to the system. Tests are part of test suites. Test fixtures optionally drive the system under test according to the specific test. Requirements relate to other requirements in a couple of ways. Requirements may contain nested, or sub, requirements. This allows us to view requirements at various levels of abstraction, such as “Get a rock on Mars” and “Attain Mars Orbit.” This is shown as the aggregation of requirement by requirement. A slightly different relation is the association with the role end “derivedRequirement.”In this case, design constraints may interact with requirements to result in more specific forms of a requirement.

Requirements Taxonomy

Figure 5-1. Requirements Taxonomy

At the high level of the requirements taxonomy are three requirements: operational, functional, and quality of service (QoS).[1] Operational requirements have two primary subtypes: interaction requirements and interface requirements. Interaction requirements have a system representation as a scenario, modeled as a sequence, timing, or communication, or possibly an activity diagram. Functional requirements are met by collaborations (sets of interacting object roles). QoS requirements are typically modeled as constraints and come in a variety of types: performance and timeliness; safety; reliability; security; and a variety of quality requirements. Quality requirements may include reusability, portability, adherence to standards and guidelines, and meeting objective quality metrics.

This requirements taxonomy helps us understand the relation of requirements to the system and its test, as well as understand how requirements tend to be represented.

Use Cases

A use case is a named capability of a structural entity in a model. Most often, use case analysis is applied only to the system as a whole, but use cases can be applied to any structural entity, including subsystems[2] or even classes. Use cases define a system-level capability without revealing or implying any particular implementation or even design of that capability. That is to say that use cases are part of the functional view of the system. As we will see shortly, use cases are implemented (realized in UML-speak) by collaborations of classes.

Use cases exist within a structural context. In the case of the system, this context consists of the system and associated actors. An actor is an object outside the scope of the system under discussion, which nevertheless interacts with it. In order to be a use case, the capability must return a result visible to one or more actors. If a capability of a system is invisible from the outside, then it is not a use case and should not be captured during requirements analysis (since it is a design concern). Figure 5-2 shows a simple use case diagram.

Use Case Diagram

Figure 5-2. Use Case Diagram

The ovals in Figure 5-2 are the use cases and the stick figures are the actors. The lines connecting the use cases with the actors are associations, meaning that the actor interacts with the system as it executes the use case; that is, messages are either sent to the actor or received from the actor while the use case is executed. The large square is called the system boundary and is optional. The diagram also shows dependency relations between the use cases, generalization of use cases, constraints (the statements inside curly braces), and comments.

Used primarily in early analysis, the use case diagram shows the black-box functional capabilities provided by the system. These capabilities manifest themselves as interactions among the system and the external objects.

One of the advantages of use case diagrams is their ability to capture a broad view of the primary functionality of the system in a manner easily grasped by nontechnical users. The use case diagrams can become a centralized roadmap of the system usage scenarios for people specifying the requirements of the system.

It is important to note that use cases are not themselves requirements. Rather, they organize requirements into chunks, based on the organizational principle of common operational capability. This principle can be used regardless of the more detailed representation of the requirements themselves, whether it is text, sequence diagrams, state machines, or activity diagrams. It is common for a use case to represent and organize many pages of textual requirements or dozens of usage scenarios.

Actors

As mentioned earlier, an actor is an object outside that scope of the system under consideration that has significant interactions with it. The icon for an actor, as shown in Figure 5-2, is a stick figure. Many people misconstrue this to mean that actors must therefore be human users of the system. An actor is any object that interacts directly with the system in ways that important to be modeled—this means that they either provide information (or control inputs) to the system or receive information (or control outputs) from the system. Some writers have mistakenly stated that all use cases must be initiated from an actor or that each use case should have a single primary actor. As a matter of fact, use cases can initiate themselves (usually based on the passage of time) and often interact with many actors.

Actors should be named with singular nouns[3] and represent objects outside the scope of the system under consideration that have important interactions with the system. If the use cases are being applied to a piece of a large system, such as a component or subsystem, then some of the actors will be outside the overall system while other, “internal,” actors will be peer architectural pieces of the system such as other components or subsystems. From the perspective of the unit of concern, these peer architectural units are actors even though they are parts of the entire system being constructed.

Figure 5-3 shows some of the use cases for an air traffic control system. Note that of the several actors identified, only one of them (the Controller) is a human user. All the rest are legacy systems, or devices to which the system must integrate or interface. Packages are used to group the use cases into broad categories of concern, Execution_UseCases and Management_UseCases. Packages may be used to organize systems with many use cases as appropriate.

Air Traffic Control System Use Cases

Figure 5-3. Air Traffic Control System Use Cases

In general, not all actors participate in all use cases. The two radar actors in Figure 5-3, for example, interact with the Locate Tracks use case, but not with the other use cases. The use cases with which the actor interacts are indicated by the association drawn between the actor and the related use case. Of course, an actor can participate in more than a single use case, just as a use case may interact with multiple actors.

Associations among actors are not drawn (since they are outside the scope of the system of concern), but sometimes actor generalization is shown. For example, a user in a library may participate in a Check Out Book use case, but only a certain type of user, called Librarian, may add new books to the library system or register a new user. Generalization is therefore sometimes shown among the actors.

At the system level, the actors for use cases are objects outside the entire system. However, if the use case is applied to an internal subsystem or class, then the actors will be truly external actors (as in the system case) plus the peer-level subsystems or classes with which that the element under analysis associates.

Consider the use cases in Figure 5-4. Here, the anesthesia system interfaces with an external ECG monitor and chart recorder. The other two actors are human users of the system—the physician and the patient.

Anesthesia Machine Use Cases

Figure 5-4. Anesthesia Machine Use Cases

Now, consider a breakdown of the anesthesia machine into some large-scale subsystems, as shown in the class diagram in Figure 5-5.[4] This diagram shows the anesthesia system as a structured class containing the various subsystems as parts. Note that the subsystem stereotype is shown using two notations—the iconic form for a subsystem (using a custom icon inside the object rectangle) and text. Usually only one form will be shown, but the diagram illustrates how both look.

Anesthesia Subsystems

Figure 5-5. Anesthesia Subsystems

Figure 5-4 shows the use cases for the entire system. Use case analysis may be applied recursively to these subsystems as well—that is, it is useful to define a set of use cases for each of the subsystems so that the subsystem teams clearly understand the responsibilities and requirements for their subsystem. In principle, these subsystem use cases should be derived from two distinct sources. First of all, the subsystem requirements must be derived from system-level requirements; they are, in essence, a project of the portion of the system requirements that the subsystem fulfills. The second source is the subsystem architecture. Even though architecture is really part of design, it groups the functionality into these large architectural units called subsystems. The subsystem requirements must take into account both the system level requirements and the architecture decomposition of the system.

The question is, how do I formally (or informally) derive my subsystem-level use cases from the system-level use cases? Technically, the ROPES process does this via the «include» stereotype of dependency. This means that one use case includes or contains the smaller “part” use case, but for some reason the part use case has been extracted out and given a name. Typically, this extraction of an included use case might be done because the same “part” use case is used in more than one larger use case and extraction allows the use case to be referenced in multiple places rather than replicated. However, in this usage, the «include» relation is used to decompose a system-level use case into part use cases that will be realized by different subsystems. The extracted use cases are then realized by a single subsystem each. A system-level use case can then be decomposed into a set of subsystem-level use cases, each of which is realized by a single subsystem. Each subsystem then has a set of use cases, derived from the set of system-level use cases that define the requirements for that particular subsystem. The subsystem design and development team then has a coherent set of requirements for their subsystem.

Figure 5-6 takes one of the system-level use cases, Deliver Anesthesia and performs this decomposition. This system-level use case is decomposed into 12 included use cases, each of which is realized by one subsystem. The Agent Monitor subsystem, for example, will realize the requirements specified in the derived use cases: Monitor Agent Concentration, Calibrate, and Configure. Similarly, most of the remaining subsystems must realize some other requirements for the system to meet the Deliver Anesthesia use case, including the User Interface, Ventilator, Vaporizer, and Breathing Circuit subsystems. For simplicity, the subsystem-level use cases in Figure 5-6 don't show their associated actors. Instead the actors appear on the more detailed, subsystem diagrams , Figures 5-8 through 5-14.

Decomposition of Deliver Anesthesia Use Case

Figure 5-6. Decomposition of Deliver Anesthesia Use Case

An assistive approach to constructing the decomposition is to decompose a system-level use case into a partially ordered sequence of activities on an activity diagram, mapping the activities to the subsystems with swim lanes. Figure 5-7 does this for the Deliver Anesthesia use case. Note the forks and joins among some of the activities—this indicates that we really don't care which of these is performed first (the fork), only that they are all completed before the next step (the join). These subsystem-level activities can be represented or mapped onto subsystem-level use cases.

Use Case Activity Breakdown

Figure 5-7. Use Case Activity Breakdown

Note that the actors for the subsystem use cases may be actors that exist outside the entire system; they may also be other peer architectural subsystems. For convenience, we stereotype these actors with «internal» to indicate that they are inside the scope of the entire system but outside the current scope of concern. In addition, I have prefaced the name of the subsystem with an “a” to indicate that this in an internal piece of the system in an actor role in this context, such as aVentilator and aUserInterface. This is shown in the next several figures.

Figure 5-8 is a use case diagram for the Ventilator subsystem. The primary use cases are to deliver ventilation (of which there are three specialized forms for different modes or kinds of ventilation) and to monitor the output of the breathing circuit. Of course, we still need to detail all the dozens or hundreds of requirements of those use cases, but that will be discussed later in this chapter.

Ventilator Use Cases

Figure 5-8. Ventilator Use Cases

The user interface subsystem use cases are defined in Figure 5-9. Because the user interface is the means by which the physician controls and monitors the execution of the system, there are many smaller use cases (mostly specialized use cases of the Configure Device use case).

User Interface Use Cases

Figure 5-9. User Interface Use Cases

The Vaporizer subsystem's use cases are shown in Figure 5-10. We see that the Deliver Drug use case is decomposed into Vaporize Drug and Mix Drug with Airflow use cases. The SPO2 Monitor and CO2 Monitor use cases (Figures 5-11 and 5-12) look similar, but the details of how they operate and how they are set up will differ. Figure 5-13 for the Agent Monitor subsystem use cases is similar, but it also includes a constraint showing what agents may be monitored with this device. The Breathing Circuit use cases in Figure 5-14 deal with setting the gas concentration and flows, the actual delivery of the gas flows with the set concentrations and the mixing of the gases.

Vaporizer Use Cases

Figure 5-10. Vaporizer Use Cases

SPO2 Monitor Use Cases

Figure 5-11. SPO2 Monitor Use Cases

CO2 Monitor Use Cases

Figure 5-12. CO2 Monitor Use Cases

Agent Monitor Use Cases

Figure 5-13. Agent Monitor Use Cases

Breathing Circuit Use Cases

Figure 5-14. Breathing Circuit Use Cases

Use cases are interactions between the system and some set of associated actors. It is important to understand what use cases are not, as it is common to waste time during use case analysis either capturing design details or functionally decomposing the internals of a system. A use case is not any of the following:

  • A single message or event: The details of a use case are represented with scenarios, consisting of many, potentially dozens of messages flowing back and forth between the system and the actors. If you identify a use case that consists of handling a single message or event, you have probably actually identified a (rather small) piece of another use case. Remember that a use case typically represents many (possibly dozens or, in some cases, hundreds of) pages of textual requirements.

  • A low-level interface: Low-level interfaces are the means by which use cases are realized. For example, if a hard disk is an actor, the low-level commands passing between the system and the actor, such as move head and spin up, are not use cases. Remember that the use case is why the actor communicates with the system not how it actually does it. Use cases should be expressed using the vocabulary of the user's problem domain not the engineering design domain.

  • A functional decomposition of the system design: Later, we will see relations among use cases, such as generalization and dependency. The point of use case relations is not to decompose the system into a design that can be implemented directly in C! The purpose of use case relations is to allow a parsimonious description of the capabilities (i.e., requirements) of the system. Such relations can be useful but they are optional.

Figure 5-15 shows some of the unfortunately too-common ways to model use cases badly. A common problem is that as engineers we are primarily trained to design systems, and when first exposed to use cases, we may see them as design tools. The Make TCP Datagrams and Switch to Backup Power use cases are examples of that, but so is the use of the actors Ethernet Network Interface Card (ENIC) and Battery. The ENIC is a both a low-level interface and a design element internal to our system, and is inappropriate as an actor. What would be better? How about a use case such as Store Patient Data with an actor of Hospital Information System? The use case should be something in the user's vocabulary, not something in the engineer's design vocabulary. Similarly, the Switch to Backup Power use case is both internal and over-decomposed. A better choice would be Reliably Deliver Power, and Mains might be a reasonable actor (since it is outside the system and internally a battery can provide backup as necessary).

Bad Use Case Modeling

Figure 5-15. Bad Use Case Modeling

The Turn On Machine use case is probably not only a single scenario, it is probably a single message, “turn on.” This is over-decomposed if this is the case. If the Turn On use case includes “perform POST” (power-on self-test), calibration, and configuration, and all of that is captured, then this would be a reasonable use case.

The delivered gas mixture's relative concentrations are set via Set O2 Concentration and Set Balance Gas use cases. However, while good use cases are highly independent, these are highly interdependent. When I set the O2 concentration to 30%, I am necessarily setting the balance gas concentration to 70%. These should be collapsed into a single Set Gas Concentration use case.

Perform Memory Test is a bad use case because it presumes a particular design (you can build an anesthesia machine without any computer components!) and it is outside what the user cares about. That doesn't mean that performing memory tests is bad, nor that testing shouldn't be part of the system design—only that it is part of the system design and not part of the requirements. The Perform System Checkout use case is okay, though, because in typical usage the physician (or more likely, the technician) will perform periodic maintenance.

The Perform Memory Test use case is then decomposed into what looks like a flow of smaller use cases—Test RAM, Test FLASH, Test and ROM. Use cases do not show flow, although flow can be shown on more detailed views of requirements, including sequence diagrams, statecharts, and activity diagrams. Even if the dependency relations aren't depicting flows, they are over-decomposing the problem. Remember that a use case represents a coherent set of requirements that constitute a user-visible capability of a system without revealing or implying how that capability is achieved.

Different authors will tell you different things about use cases, not all of them useful. Some authors will say that all use cases are initiated by actors. This precludes systems that have autonomous behavior—a property of many real-time and embedded systems. Other authors will say that all use cases have a single primary scenario. Again, this is often—but not always—the case. In fact, some use cases have a number of equally important scenario variations.

Use Cases and Text

As developers we are all too familiar with the “Victorian novel” approach to capturing requirements—the generation of hundreds or thousands of pages of text specifying requirements of complex systems. Using text alone to capture requirements is problematic because text is difficult to make simultaneously precise, unambiguous, and understandable. Besides that, textual requirements commonly lack sufficient rigor to adequately capture exactly what is meant by the requirements, allowing different interpretations to arise. Further, requirements documents are often conflicting, having requirements mismatched in different parts of large documents. Nevertheless, text is useful because it is so expressive and flexible. It is possible to employ a use case approach and specify requirements entirely in text—it is simply a matter of using use cases to specify organizational units (e.g., chapters) within the Victorian novel. This approach, while having some merit, still suffers from the problems identified previously.

The UML provides more formal languages (notably, statecharts, activity diagrams, and sequence diagrams) for capturing the details of requirements, as we shall see later. However, text is still useful in conjunction with these more formal approaches. It is common, for example, to provide textual information to characterize the use case. Different authors have defined different contents and formats for such textual characterizations. What I have found most useful appears in Figure 5-16.

Textual Characterization of Use Cases

Figure 5-16. Textual Characterization of Use Cases

The figure shows several fields of information that can be entered into the use case description provided by most UML tools. The Name field is optional and need only be entered if it is otherwise impossible to disambiguate the use case in question. The Purpose field provides a location for a high-level statement as to the user purpose for the capability of the use case. The Description field is where detailed textual requirements may be stated. The Preconditions, Postconditions, and Other Constraints fields hold explicit constraints about the execution of the use case. Preconditions are conditions that must be true before the use case begins, while postconditions are conditions that are guaranteed to be true by the system after the use case is finished. The Other Constraints field is commonly used to hold (QoS requirements for the use case, such as worst-case execution time, average-case execution time, reliability, maintainability, and so on. If the description field can contain hyperlinks,[5] as they can in Rhapsody from I-Logix, then text, mathematical models, or other navigable references can be made in the UML tool. Hyperlinks are very useful in this context because clicking on them invokes the external tool to bring up the referenced document or, if an internal hyperlink, the document or referenced model elements are brought to the fore.

Use Case Relations

The UML defines three distinct relationships among use cases. Generalization means that one use case is a more specialized or refined version of another. For example, the Validate User use case can be specialized into Check Password, Check Fingerprint Scan, and Check Retinal Scan use cases. Each of these subuse cases is a specialized version of the base use case.

The other two kinds of use case relations are stereotypes of dependency. «include» is used when the capability described in the client use case uses the capability described in another use case. «include» should only be used when the behavior is shared among two or more use cases or is mapping the “part” use case to a system architectural component and is required for all of the client use case scenarios.

The third kind of relation is «extend». «extend» is used when one use case provides an optional additional capability within a client use case. This optional capability is inserted at a named extension point. Figure 5-17 shows the syntax of the use case relations. Remember that the closed arrowhead indicates generalization with the arrow pointing to ward the more general use case. Dependency is shown with an open arrowhead and a dashed line. For an «include» relation, the arrow points to the part use case. “The Take Picture use case includes the Adjust Spacecraft Attitude use case.” Perhaps confusing, but the arrowhead on the «extend» relation points in the opposite direction! “The Lossy Compression use case extends the Execute Scheduled Downlink use case.”

Use Case Relations

Figure 5-17. Use Case Relations

In Figure 5-17, the spacecraft turns in order to achieve two capabilities—taking a picture (under the premise that you must point at something to take its picture) and executing a scheduled downlink of information. Because this common capability is required for both these use cases, it is extracted out and put into its own use case. The two means by which the spacecraft can be turned are specialized use cases of the Adjust Attitude base use case. In one case, rockets can be fired to turn the spacecraft, and in the other, reaction wheels are activated. Finally, the scheduled downlink can optionally compress images, either using lossy or non-lossy compression algorithms. Because this is an option, it is shown as an «extends» relation. Also, for risky command sequences, a high-level security clearance may be required. Note that the extension points are identified in the base use case and then referred to by the extending use cases.

A caution: Too often, beginners overuse the use case relations and use them to capture the wrong things. Remember that you can model the requirements of systems without using generalization, «extends», or «includes». Their use can make a requirements model a little simpler, but not if they are misused.

Using Use Cases

Use cases can provide a unifying strategy for the entire project development. They are an embodiment of what the customer wants and expects to see when the dust settles[6] and the product ships. Use cases group together scenarios related to the system capability described by the use and provide valuable information into all phases, as shown in Table 5-1.

Table 5-1. Using Use Cases in Development

Phase

Application of Use Cases

Analysis

  • Suggest large-scale partitioning of the domain

  • Provide structuring of analysis objects

  • Clarify system and object responsibilities

  • Capture and clarify new features as they are added during development

  • Validate analysis model

Design

  • Validate the elaboration of analysis models in the presence of design objects

Coding

  • Clarify purpose and role of classes for coders

  • Focus coding efforts

Testing

  • Provide primary and secondary test scenarios for system validation

Deployment

  • Suggest iterative prototypes for spiral development

Identifying Use Cases

There are four primary approaches to identifying use cases:

  • List the primary capabilities of the system, then identify the actors and scenarios within each use case.

  • Identify the actors to the system and the messages they send or receive (the scenarios), and then group them into use cases.

  • Start with system scenarios, identify the actors that participate in them, and then lump them into use cases.

  • Identify a system workflow with an activity diagram at the highest level and from there determine how these might be mapped into use cases.

All of these approaches can work well.

How does the analyst extract the primary capabilities of the system? Although some domain experts may think in abstract terms, the vast majority will be more comfortable identifying specific scenarios or specific system workflows rather than use cases. The analyst must identify the dozens (or hundreds) of scenarios that map the important system aspects and from these deduce the use cases. A number of approaches to identifying the scenarios are possible.

The analyst can sit with the customer and ask probing questions, such as these:

  • What are the primary functions of the system?

  • What are the secondary functions of the system?

  • Why is this system being built? What is it replacing and why?

The analyst must then identify the following for each use case:

  • The role the actors and system play in each scenario

  • The interactions (flows) necessary to complete the scenario

  • The sequence of events and data needed to realize the scenario

  • The variations on the scenario that are possible (other related scenarios)

For example, the primary functions of an ECG monitor are to display waveforms for the physician, provide discrete patient numeric values (such as heart rate), and sound an alarm when the patient is at risk. Secondary functions might be to provide a remote display for the surgeon, provide a reliable software upgrade facility, allow configuration, and even support a demonstration mode of operation for the sales reps. Why is the system being built? Perhaps it provides better arrhythmia detection, color displays for better differentiation of lead configurations, or faster response times, or it interfaces to the hospital network and the operating room anesthesia machines. Figure 5-18 shows a reasonable use case model for an ECG monitor. Note that this use case diagram uses all three kinds of relations among use cases—includes, extends, and generalization.

ECG Use Cases

Figure 5-18. ECG Use Cases

Use cases are used primarily during requirements analysis, but Figure 5-19 shows that use cases have a role in other phases of the ROPES process as well. Once the system is broken down into its primary subsystems (in the systems analysis phase), use cases may be applied to each of the subsystems in turn to define its requirements with respect to the other elements of the system. As the object model becomes fleshed out, the system- and subsystem- level use cases may be refined in more detail, replacing the system with the objects collaborating within the system to realize the specific use case. The need for additional use cases having to do with the concurrency and component models is normally uncovered during architectural design as well. Even in testing, the use cases and their associated scenarios form the key set of tests to be applied to the system.

Use Cases in Development

Figure 5-19. Use Cases in Development

Use cases are a powerful tool for capturing requirements and for binding those requirements into design and testing as development continues.

Detailing the Use Cases

So far, we've identified what a use case is: a named system operational capability. We've also noted that use cases organize functional and quality of service requirements. However, a name alone isn't enough to understand what a use case means. For example, consider the use case Set Ventilator Tidal Volume[7]—the user turns a knob and sets the amount of mixed breathing gas pumped out per breath for the ventilator. That's not enough detail to understand how it actually works. For example:

  • What is the maximum value that can be selected? What is the minimum value that can be selected?

  • What is the accuracy of the delivery of tidal volume with respect to its set value? +/- 10 ml? +/- 5%?

  • Are there different ranges, such as one range for adults, another for pediatrics, and another for neonates?

  • What happens if the knob is turned accidentally—does tidal volume change directly or is an explicit confirmation required?

  • If there is a confirmation, can the user cancel the operation?

  • What happens if the user tries to set a different value, say respiration rate, before confirmation?

  • How does the user know whether a value is currently being set (waiting for confirmation)?

  • Does anything have to either precede or come after setting tidal volume, such as setting patient age or weight?

In requirements analysis, the devil is in the details and answering these questions is crucial. The process of identifying the dozens or perhaps hundreds of detailed, specific requirements is known as “detailing the use case” in the ROPES process. Two categories of approaches are possible. A specification can be written for the requirements. This specification can be either informal (text) or formal using a formal or semi-formal language such as statecharts or activity diagrams. The other approach is to provide examples of operational usage. Remember that in Section 5.1, we identified three kinds of requirements. Functional requirements are best captured in specifications. Operational requirements are best captured in scenarios or activity diagram workflows. QoS requirements are added to both representations as modifiers of the primary requirements. It should be noted that functional requirements can be defined in scenarios just as operational requirements can be defined in specifications. However, the general rule is that functional requirements are most often captured in specifications and operational requirements are most often captured in scenarios.

Scenarios for Use Cases

A scenario is a particular actor-system interaction corresponding to a use case—it is a specific example of a use case execution in the system's operational environment. Scenarios model order-dependent message sequences among object roles collaborating to produce system behavior in its operational environment. Different scenarios within a given use case show permutations of object interactions. Even early in analysis, the advantage of scenarios is that domain experts and users can usually quite easily walk the analyst through dozens of typical system usage scenarios. The domain expert can explain why each step is taken, who initiates it, what the appropriate responses are, and what kinds of things can go awry. In going through this process, the analyst will uncover many important facets of the system behavior not mentioned within the problem statement. Scenarios provide an invaluable tool for validating the problem statement against the user's expectations as well as uncovering the less obvious requirements. Late in analysis, they can be used to test the object structure by ensuring the appropriate participation by each object in each scenario.

Generally, a medium-sized system will have a few to a few dozen use cases. Each use case will have anywhere from a few to a few dozen scenarios of interest. There are an infinite set of scenarios, but it is only necessary to capture the ones that are interestingly different—that is, the ones that capture operational, functional, or QoS requirements, including exceptions and error identification, isolation and recovery, as appropriate. The scenario set is said to be complete when all of the operational requirements are covered in at least one scenario. This, of course, is a small subset of all possible scenarios. Some use cases have a “sunny day” or primary scenario. In this case, most or all of the other scenarios for the use case are variants on the primary scenario.

Every scenario has an underlying structural context. This structural context is the set of object roles that may appear in the interactions. Early in analysis, the structural context is the use case diagram; the objects available for scenarios are the system (or the use case, which isn't an object, but is a classifier and may be used for a lifeline in a sequence diagram) and the actors identified on use case diagram. The structural context is shown on the use case diagram, but if desired, a Context Diagram (i.e., a class diagram with the actors and the system) can be drawn. In most cases, I have found the system use case diagram sufficient for this purpose.

Use cases are realized by collaborations of objects inside the system working together. Later analysis decomposes the system into such objects, and the use case scenarios can be refined by adding these additional levels of detail. It is important that you only use objects in the scenario that appear in the structural context. That means that if the use case diagram has two actors and the system, only three objects can appear in the scenario. Later, once the system is opened up and is under design, internal objects are identified. At that time, these internal objects may then appear in the scenarios as well, but to do so too early is a common and fundamental mistake in requirements analysis. Requirements should be as free of design as is possible. This means not mixing in design elements too early—that is, the purpose of the identification of the structural context for the scenario. It is crucial to make sure you always know the structural context. Otherwise, you'll be making stuff up on the fly with only a vague notion as to the underlying structural model. If you have a number of people doing this, the chances the models will all play together later is vanishingly small because each designer will be making up different (and incompatible) pieces. At the end, the system requirements will be specified in terms of mutually incompatible design decisions and must be thrown away and redone. By drawing and agreeing on the structural context before beginning the scenario analysis, the scenarios from use cases elaborated by different analysts will all play together when it comes time to decompose or implement the model.

It is important to stress that building and analyzing scenarios is a creative process of discovery. It is not simply a matter of starting with postulates and applying mathematical deduction to derive all possible behavior paths. Deep within the crevices of the domain experts' minds are hidden requirements that may never be explicitly identified.[8] These cannot be deduced from the problem statement per se. The process of scenario modeling brings these hidden requirements to the surface so they can be added to the system features.

Three primary scenario representations exist within the UML: sequence, communication (formerly collaboration), and timing diagrams. Sequence diagrams, the most commonly used, emphasize messages and their sequence. Communication diagrams are less popular and tend to stress the system object structure. Timing diagrams are best applied when the requirements are highly time-sensitive. All of these diagram types show scenarios but differ in what they emphasize. Almost exclusively, in use case analysis, sequence diagrams are preferred over communication diagrams. Communication diagrams are not used until the object model of the system stabilizes (and even then, many people prefer sequence diagrams anyway). Timing diagrams are less applied, but are useful when timing is crucial. In this chapter, we will primarily focus on sequence diagrams.

Sequence Diagrams for Requirements Capture

Sequence diagrams represent scenarios. A scenario is a specific interaction of object roles consisting of a potentially large number of scenario steps. Each scenario step may be a message, stimulus, event reception, or action. In requirements analysis, scenarios are used to capture operational requirements; that is, requirements around the interaction of the system with its environment. This means that the operational requirements include not only the specification of the services provided by the object roles, but also the allowed and disallowed sequences of those services and their QoS requirements.

Most development organizations have a history of using textual specifications for capturing requirements. Even after adopting the UML, many organizations continue using text as an adjunct to scenarios and statecharts to capture requirements in a more formal way. Figure 5-20 illustrates the trace relationships between textual requirements and use cases and their scenarios. If the requirements are captured entirely, or mostly, in the UML model, then internal «trace» stereotyped dependency relations can provide traceability inside the model. If extensive external textual documents are used, then requirements traceability tools can provide the link to navigate between model elements and the requirements that they represent or realize.

Relating Text and Scenarios

Figure 5-20. Relating Text and Scenarios

An example sequence diagram from the anesthesia machine is shown in Figure 5-21. This diagram has several aspects worthy of note. First, the diagram has a descriptive note in the upper right corner that names the sequence diagram (not required if you're using the sd operator for UML 2.0 sequence diagrams), a brief description, and the preconditions and postconditions. While every use case has pre- and postconditions, use case sequence diagrams usually have a more constrained set of them and it is useful to specify it. In this sequence diagram, the use case is used as a lifeline rather than the system. The appropriate interpretation for this lifeline is “the system executing the use case.” If you prefer the System object instead, that is equivalent.

Use Case Sequence Diagram

Figure 5-21. Use Case Sequence Diagram

The sequence diagram shows one particular path through the execution of the use case, that is, it represents one of many scenarios. This scenario was captured because it was both a reasonable use of the system and because it showed an important operational interaction of the system, as specified by the sequence of message exchanges. In addition, note the use of constraints to add functional and QoS specifications, such as the allowed set of anesthetic agents, the allowable settings for concentration of these agents, and the accuracy of the delivery of the drugs with respect to those settings.

Of course, to capture the operational (and other) requirements of the Deliver Anesthesia use case, several dozen scenarios would be provided, using different drugs, concentrations, and operational sequences. A non-trivial number of these would capture the exceptional scenarios—the scenarios that involve something going wrong, such as system misuse, failures, errors, or unexpected events. The scenario in Figure 5-21 gives an example of what might happen if the drug reservoir runs low—the system triggers an alarm, and the physician silences the alarm and adds more drugs to the reservoir. Other scenarios might detail the operational sequences when the system can't maintain the proper drug concentration, there is a failure in one or more of the gas supplies, the ventilator (shaping the breaths) fails, there is a breathing circuit disconnection, there is a kink in the gas delivery line to the patient, the agent monitor reports an internal failure, the delivered agent is different than the commanded agent, and so on.

As we've seen, it is important to only use elements on the sequence diagram that appear in the problem context. At the systems level for the anesthesia machine, that means that only the system actors (e.g., the Patient or Physician) and either the System or the relevant use case. What about moving forward into the subsystem architecture or even the semantic object model? How do we know that we've done a good job of the subsystem architecture or specifying the semantic objects of the system?

Remember that we've captured the requirements at least in part in sequence diagrams. Therefore a measure of goodness of the architecture or object model is that the design (at the level of abstraction being considered) can realize the operational scenarios defined at the system level. If it can realize all of the scenarios defined at the system level, then the architecture or object model is good and if not, then it is inadequate. To demonstrate this is true, we elaborate the scenarios by adding the level of detail from the architecture or the object model and then we execute the system to demonstrate that the elaborated scenario executes properties.

Consider the object model in Figure 5-22. This shows three subsystems working together to realize the Deliver Anesthesia use case, with the internal structure of the Vaporizer subsystem detailed (with respect to this collaboration—it may well contain other elements not used in this collaboration). A very relevant question to ask of this collaboration is “Is this good?” That is the same as asking, “Does this collaboration meet its requirements?”

Deliver Anesthesia Collaboration

Figure 5-22. Deliver Anesthesia Collaboration

To find out, we can elaborate the system-level scenario in Figure 5-21 with these semantic elements to see. The elaboration is shown in Figures 5-23 and 5-24. The lifeline elements for the semantic objects are taken from the class diagram shown in Figure 5-22 and are added to the elements shown on the original sequence diagram. To highlight the original elements, the arrows from the original scenario are made with heavier lines.

Elaborated Scenario Part 1

Figure 5-23. Elaborated Scenario Part 1

Elaborated Scenario Part 2

Figure 5-24. Elaborated Scenario Part 2

As a matter of personal preference, when I elaborate scenarios in this way, I like to leave the original scenario exactly the same and add the more detailed elements to it. This greatly facilitates tracing the elaborated scenario back to the original system scenario and helps ensure that the elaborated scenario is in fact an elaboration of the original. If elements are removed in the elaboration, then demonstrating the equivalence is much more difficult. Thus the elaborated scenario shows the use case from the original as the mediator of messages into the system. Because some developers find this odd, they prefer to use the System object there instead, which is equivalent. The point is to demonstrate that the design elements of the system collaborate together to realize the set of scenarios used to capture the requirements for the system.

In UML 2.0, this elaboration can be done by decomposing the Use Case or System lifeline, representing its internal structure on a separate (referenced) sequence diagram. The primary advantages of this approach are that it keeps the original sequence diagram the same and scales up to possibly many levels of decomposition as the system design progresses. The disadvantage is that the more detailed interaction cannot be seen on a single diagram.

Capturing QoS Requirements on Sequence Diagrams

The single most differentiating characteristic of real-time systems is their concern and treatment of time, as discussed in the previous chapters. In the realm of real-time systems, defining the external timeliness requirements is crucial to understanding the problem. However, most timing requirements are derived rather than primary requirements. That is, a specific timing constraint may arise from a need for accuracy or fault tolerance. Because these requirements are derived, it is all too common for them to be missed by systems designers, leading to unstable system performance. Thus, it is vital that these time constraints be captured as part of the system model so that they can be treated appropriately.

A number of time values can be captured. Those time values that are QoS requirements can be captured as constraints applied against the actions or messages. Those time values that are estimates, used for the purpose of analysis, can be captured as tagged values (user-added properties of model elements). Tagged values are shown as { property = value} pairs in constraints.

A number of parameters are required to specify the timing requirements for real-time systems. Naturally, incoming messages must have their timing characterized. If they are periodic, then their periods and jitter must be identified. If they are aperiodic, then appropriate values, such as their minimum interarrival times and averages rate, must be defined. The system response timing is commonly defined in terms of deadlines. If the response has a hard deadline, then missing the deadline constitutes a systems failure. In a soft deadline response, the response performance must be stochastically specified. Soft systems are permitted to lag in their response but are expected to maintain an average throughput or system response. Firm deadlines have both a hard deadline as well as an average throughput requirement.

Response performance may be further specified into a worst-case hard deadline and an average response time when appropriate. Some performance requirements must be met only in the long run, and occasionally missing a deadline creates no difficulties. These soft deadlines may be defined as average response time requirements or a bounded mean lateness. Firm deadlines have both a hard deadline and a shorter average response time.

More complex timing behavior requires more complex modeling, as noted in Chapter 4. In some cases, scalars cannot adequately specify the timing of behavioral responses. Many actions require relatively long periods of time to perform and intermediate responses may be important. For example, an emergency shutdown of a nuclear reactor is implemented by insertion of control rods into the core. This may be initiated by an event such as a coolant leak or an explosive temperature and pressure buildup. This takes time. To avert an incident, it is preferable to insert the rods 90% of the way as soon as possible even if the remaining 10% takes much longer. Control loops are another example. Quick, if incomplete, responses stabilize PID control loops, even if the system response asymptotically converges much later.

These issues are domain- and system-specific. For many situations, the only concerns are service time and latency. Modeling 50% or 80% response times may be important in some special applications. In other applications, several points from a stimulus-response curve may be required to adequately characterize the performance requirements.

In most real-time systems, the time-response requirements are crucial because they define a performance budget for the system. As objects and classes are defined, this performance budget propagates through the analysis and design phases. Ultimately, they define a performance (sub)budget for each and every operation and function call in the thread of execution responding to the event. The sum of the (sub)budgets must meet the specified overall system performance requirement. For example, a message and the completion of its reaction may have a hard deadline at 500 ms. The overall response may be implemented via a chain of six operations. Each of these operations must be allocated some portion of the overall performance budget.

Statecharts

Statecharts are a formal behavioral language that lends itself to the specification of use case behavior. The use case formal language has a number of advantages over text:

  • It is verifiable, through mathematical analysis or execution.

  • It is precise, and not nearly as likely to be misinterpreted.

  • It is generative, meaning that creation of an executable requirements model is possible.

The primary disadvantage of using statecharts is that because they are a precise formal language, most customers and marketers will not understand them and will not be able to assist directly in validation or verification. However, this limitation can be addressed very easily by generating scenarios traversing the various paths in the statechart. Customers and marketers can understand scenarios very easily. I have found it very useful to generate both statecharts and sets of sequence (or timing) diagrams that traverse the statecharts. This topic will be discussed later in this section.

The semantics and syntax of statecharts was described in some detail in Chapter 3. We will concern ourselves here with their application in the capture and analysis of requirements. Statecharts are particularly effective when the use case is reactive; that is, it has inherent states (conditions) and remains in those conditions until an event of interest has occurred. Events and messages from the actors are modeled as events in the statechart while messages to the actors are modeled as actions on the state machine.

Consider the requirements for the Alarm On Critical Event, shown in Figure 5-25. We see a relatively small number of requirements, but they are still nonetheless nontrivial to understand. One can envision a number of scenarios traversing different paths through that textual specification, some with the alarm ceasing before the acknowledgment, some after, and some never ceasing. A statechart shows the interaction of the requirements more clearly, as shown in Figure 5-26.

Alarm On Critical Event Requirements

Figure 5-25. Alarm On Critical Event Requirements

Alarm On Critical Event Statechart

Figure 5-26. Alarm On Critical Event Statechart

The and-states show the independent aspects of the processing of the incoming events—the silence, the acknowledgement semantics, the display, and the sounding of the tone. The GEN() operation generates events that are consumed by the other and-states. For example, when the use case is in the state AlarmToneInactive (because the alarm silence button was pressed), and the silence time elapses, then a stopSilence event is produced which is consumed by each active and-state that needs it.[9]

Statecharts can be related to the text in a straightforward fashion, as was shown with sequence diagrams. Figure 5-27 uses trace dependencies to show where the alarming requirements are represented in the statechart.

Statecharts and Text

Figure 5-27. Statecharts and Text

As mentioned previously, statecharts can be related to scenarios as well. Different operational scenarios take different paths through the statechart, allowing us to easily relate to two notational forms. How many scenarios are represented by the statechart in Figure 5-26? The answer is infinitely many—not only do we have loops (and one time through a loop is different than 10 times through the loop), we also have concurrent and-state regions in which the relative processes of each with respect to each other is not defined.

Figure 5-28 shows one such path through the statechart, but we can see that there are very many more. In this scenario, the ECG machine actor detects that the patient goes into asystole (i.e., the patient's heart stops beating). The system then prints an alarm message to the Chart Recorder and begins annunciating the tone. Simultaneously (hence the use of the par or parallel operator in the sequence diagram), the display accepts the scrollDown() message from the physician and scrolls the alarm into view. Now the alarm is in the Viewed state. The alarm continues to sound until the physician sends the silence() message (mostly likely by pressing a button dedicated for that purpose). Now the alarms are silenced and the alarm display is grayed out. The physician gets the patient's heart to beat (perhaps he shows him the bill), and the ECG machine detects that the alarm condition has ceased and sends a message to that effect to the system. The system responds as specified by the use case statechart, transitioning to the AlarmHandled state.

Statecharts and Sequence Diagrams

Figure 5-28. Statecharts and Sequence Diagrams

Activity Diagrams

In UML 1.x, activity diagrams are isomorphic with statecharts. In UML 2.0 they are a superset, since their semantic basis is now token flow semantics, which represent Turing machines. However, the most common use of activity diagrams in the development of real-time and embedded systems will still most likely be in their use as concurrent flowcharts. Activity diagrams are most commonly used when a behavior can be specified as a set of control flows with operators (sequence, alternative, loop, fork, and join), and progress is made primarily on the completion of actions rather than waiting in a state until an external event is received. That is, activity diagrams are most commonly used to represent algorithms that, once initiated, proceed inexorably to their conclusion. Statecharts can represent algorithms as well by using null-triggered (anonymous) events connecting states although their most common use is with explicit triggering events.

For example, consider the control algorithm for processing incoming waveforms shown in Figure 5-29. This activity diagram includes the acquisition of the waveform data from the ECG acquisition module. The first transition, in fact, is triggered by an incoming event from that module, perhaps implemented as an interrupt, indicating that some data samples are ready (probably somewhere between two and 10, depending on a number of factors). The subsequent processing proceeds from activity to activity as the actions within the activities complete. After the data is enqueued, two independent processing threads (these are logical threads and do not necessarily imply OS threads or tasks) proceed independently. One of them scans the data stream for evidence of a QRS complex indicating a ventricular contraction (heartbeat), and if found, uses this information to calculate the instantaneous heart rate (the reciprocal of the time between this and the last beat). Since individual heartbeats vary based on many factors—such as pressure on the chest, the presence of an inspiration or expiration, blood gas concentration, and so on—the physician is actually interested in the average heart rate, so a moving average filter is applied to reduce the high-frequency variance artifacts in the heart rate. The second logical thread performs a data reduction because it is typically sampled four times or more faster than it needs to be for display purposes. The physician scales the waveform display in time (displaying the waveform at 50 mm/sec, 25 mm/sec, or 12.5 mm/sec) and in amplitude to adjust for variances in electrode placement, subcutaneous adipose tissue, and other factors. Finally, a curve is drawn from the last displayed point to the new point to display.

Display Waveform Activity Diagram

Figure 5-29. Display Waveform Activity Diagram

The physician can select either of two waveform display styles. The first, called the erase bar style, advances a cursor with each new displayed data point and erases the area from the last data point to the cursor (as it is currently displaying old data there) and then draws the new data as a curve from the old data point to the new. The cursor advancement is done modulo the screen edge so that when the cursor advances past the right edge of the screen, the cursor snaps to the left edge of the screen. The other style is called scrolling waveforms and is often done with hardware support. While in the first form the position of new data changes constantly, with scrolling waveforms new data always appears at the right edge of the waveform window. When the next data is ready to be displayed, the old data is scrolled left (data at the left edge of the window being discarded) and the new data is drawn. The qualities of service required for this algorithm are provided in constraints in the figure.

Timing Diagrams

Similar in some ways to sequence diagrams, timing diagrams also represent scenarios. The essential difference between sequence and timing diagrams is that the latter emphasize change in value or state over time while the former emphasize sequences of message exchange. They are, approximately at least, isomorphic and able to represent the same information, but their purpose is different. Sequence diagrams used in requirements analysis focus primarily on the sequences of messages in operational scenarios. Timing diagrams focus on the qualities of service having to do with time, such as execution time, jitter, deadlines, periodicity, and so on, and how they affect the state of the system (or, more precisely, of the use case) or an important value held by the system.

Use cases, being classifiers, can have operations and attributes. The use case operations will be realized by services offered by the system to actors in its environment. Attributes will ultimately be realized by object (or attributes of objects) held within the system. Use case behavior can also be specified by statecharts and activity diagrams. In requirements analysis, timing diagrams are best applied to use cases when there are significant timeliness qualities of service of either some attribute or the state of the use case.

It is important to remember that timing diagrams show scenarios with an emphasis on their time properties. Scenarios represent very particular runs of the system, and different runs of the system may result in different timing. For example, suppose in one case an event comes in at t0+20ms[10]; the next time the scenario is run, the event might occur at t0+22ms. Is one of them wrong? No, but they may differ. To specify the timing requirement, you will use a constraint such as { t = t0 + 21 ms +/- 2 ms } . This can be done using the RT profile properties as well, if desired, as described in Chapter 4, but this requires a level of expertise that most customers may not possess.

The activity diagram from Figure 5-29 is used as the basis for the scenario, shown in Figure 5-30. The comment box in the upper right corner gives the preconditions for the particular scenario (waveform display speed is 25 mm/sec and the erase bar waveform style is used). The scenario then shows the change of state (activity state in this case) as processing progresses from the dataReady event until processing is complete. Since this is a scenario, the durations spent in the various activities are not specifications but examples. In several places, timing specifications are given using constraints.

Use Case Timing Diagram

Figure 5-30. Use Case Timing Diagram

Looking Ahead

One of the first things done on any project is to determine the detailed requirements of the system. These requirements may either be capabilities of the system or how well those capabilities are to be achieved. The UML provides use cases, scenarios, and statecharts to capture these requirements. Use cases identify the primary capabilities of a system. The details of how those capabilities are achieved—at least from an outside, black-box view—is captured in the scenarios or specifications associated with the use cases. A use case is normally detailed by a few up to several dozen scenarios, shown on sequence or timing diagrams. Alternatively, or in combination, a single statechart or activity diagram can provide the behavioral details of the entire use case.

This is crucial in order to understanding what system is to be built—its capabilities and required characteristics. None of this, however, has anything (directly) to do with how it's built. Use cases are realized by collaborations of objects working together for a common purpose (to implement the use case). It is, at best, less than obvious, to go from a set of requirements regardless of how they are modeled to a set of objects. Many objects may work together to realize a use case, but the same object may participate in multiple use cases as well.

The identification of objects and their classes is done in two phases. Object analysis identifies the key, essential set of objects necessary to realize the set of identified use cases. That is the subject of the next two chapters. Chapter 6 deals with how to open the box and identify the key concepts required to construct the essential logical object model of the system. Chapter 7 focuses on how to define the behavior of those logical elements, and map them back to the use case behavioral details.

Chapters 8 through 10 go on to discuss design. While object analysis identifies the set of objects required for any reasonably resolution of the requirements, design is all about optimization. Design selects one particular solution that optimizes total system quality with respect to all of its quality criteria.

Armed with that understanding, let's go open up the box and peer inside.

Exercises

1:

What are the three kinds of requirements defined in this chapter?

2:

Map each of the following requirements types (from the “UML for Systems Engineering” work-in-progress) into requirements types identified in question 1: operational, design constraint, functional, interface, performance, physical, storage, stakeholder need, and specialized. Be prepared to defend your mapping!

3:

Define the term use case.

4:

Compare and contrast use cases, specifications, and scenarios.

5:

What are the primary representational forms (in the UML) for specification? What are the pros and cons of each, and under what conditions might each be applied?

6:

What are the primary representational forms (in the UML) for scenario depiction? What are the pros and cons of each?

7:

What is an actor? What kinds of objects may be actors?

8:

How does the ROPES process map system requirements down to subsystems?

9:

Should use cases be independent or interdependent? Why?

10:

How are the use case relations generalization, «extends», and «includes»different in their usage?

11:

What is the realization of a use case in your systems design?

12:

How do you validate that your use case realization is good?

13:

Scenarios best capture what kind of requirements?

14:

In each of the diagrams used in requirements capture, where and how are QoS requirements captured?

15:

How do activity diagrams and statecharts differ semantically? How do they differ in usage?

References



[1] The currently ongoing work for UML for Systems Engineering identifies several more requirements: operational, design constraint, functional, interface, performance, physical, storage, stakeholder need, and specialized. These can easily be mapped to the taxonomy used here.

[2] In the UML, a subsystem is a component, which is in turn a kind of structured class; therefore a subsystem is a class that is composed of parts represented by object roles.

[3] As the multiplicity on the associations to the use cases can indicate when multiple actors of the same type are involved in a use case.

[4] The use of heavier lines for the association to external actors has no semantic meaning—they are just normal associations—but it does allow the interfaces that cross the system border to be easily identified.

[5] A hyperlink, as used here, is a reference either to a document managed by an external tool (an external hyperlink) or to some diagram or description somewhere else in the model (an internal hyperlink). Typical use of a hyperlink involves selection of the hyperlink to invoke the referenced document or model element in its native tool and format.

[6] That is, when the customer finally stops changing the requirements long enough for you to actually build the darn thing.

[7] Tidal volume is the amount of gas delivered per breath.

[8] At least not until after the product is delivered!

[9] Remember that the entire use case receives each event. When the use case has and-states, each and-state receives every event sent to the use case and may act on it or discard it as appropriate, independently from the other and-states.

[10] t0 here represents the time of the start of the scenario.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.174.239