Michael is an object-technology liaison, and Alan a vice president at Artisan Software Tools. They can be reached at http://www .artisansw.com/.
The Unified Modeling Language (UML) provides a common framework for modeling object-oriented systems. In fact, UML's utility as a common language for defining and designing software systems independent of a specific implementation language has increased the acceptance of object-orientation in many software development areas.
For real-time and embedded-systems developers, however, UML is insufficient in areas critical to the development of real-time embedded systems -- specifically, timing, concurrency, and hardware/software interfaces. In this article, we'll examine UML's deficiencies when it comes to modeling certain aspects of a system, and then present UML extensions that address these deficiencies.
Figure 1, for instance, is a typical process-control problem that contains a conveyor-belt transport subsystem that moves cans through a detector/scanner before moving them off-line for storage. Each can is identified by a barcode that is detected at the beginning of the transport process. The detector device is part of the transport system. The scanner unit (a self-contained microprocessor-controlled device that is coordinated by the transport subsystem) identifies defective cans as they travel on the conveyor. The scanner tells a robot router unit (another self-contained microprocessor-controlled device) the ID of a defective can. The robot then removes and disposes of the defective can. The system has local start/stop buttons that control all of the moving equipment. Operators can monitor and operate the system from a separate, remote computer terminal. The system needs to process on average 30 cans per minute. System startup/shutdown operations should not permit defective cans to go undetected.
UML combines graphical and textual notations to describe systems such as this. UML is primarily a set of notations and does not prescribe a specific development process.
Requirements Analysis:
Defining the System
One of the early activities in developing any system is to ensure that you understand the requested requirements, such as basic system functionality, timing constraints, and specific hardware constraints. There are two primary UML representations used to define the system requirements:
- Use Case Diagrams, which represent interactions between external "actors" (users or devices) and the functions of the system. These interactions combine to form functional capabilities of the system. Through Use Case Diagrams, you can establish a set of functional, testable uses of the system that satisfy the stated requirements. In Figure 2, the notation for a Use Case Diagram is simple. The primary functions of the system (Process Units, Remove Unit) as well as the external users (Operator, Container) are identified and connected. Each Use Case Diagram describes some important functional capability of the system that is further elaborated with one or more Sequence Diagrams.
- Sequence Diagrams, which capture a specific scenario or processing thread through the application using a pseudocode description (left side of the Sequence Diagram). The mapping of the Use Case functionality onto object actions is captured in the message sequence structure (right side of the Sequence Diagram). It is the communication (or collaboration) between the objects that collectively implement this Use Case. Figure 3 shows the structure of the pseudocode actions for this sequence and corresponding object messages and actions. For example, you can see the handling of a New Container Arrives message (from the Container actor to the Detector interface device) causes the Detector Identifies Container message (from the Detector interface device to the Controller object) to kick off the whole Dynamic Scan Cycle for the Process Units Use Case.
Technical Solution: Designing the System
UML supports a number of views to represent the design architecture that specifies how the solution will be implemented. This is done primarily through two architectural views -- Class and Collaboration Diagrams.
Class Diagrams form the basis for the logical object architecture of the system. Objects identified in earlier analysis steps are organized into basic class relationships of:
- Inheritance, which captures the levels of abstraction of the object architecture through a hierarchy of superclass and subclass relationships.
- Aggregation, which provides the basic mechanism for composition. An object can be made up of other objects, allowing for convenient problem decomposition and structural composition with clearly defined boundaries.
- Association, which provides another mechanism to define the connectivity between objects that need to communicate with each other or support some other aspect of the system requirements.
Figure 4 is one of the Class Diagrams for our sample system. In this view, the Controller contains (has) a Detector [aggregation] which identifies some Container [association] that has a condition attribute. The Scanner notifies the Router, which is a type of Robot [inheritance], and tells it which Container to remove. With the information in this diagram, you can almost read some of the requirements from these static class relationships.
The Collaboration Diagram, on the other hand, defines a communication structure between the objects. By analyzing several Sequence Diagrams together as a whole and representing the overall connectivity of the objects involved in those scenarios, it is possible to visualize the object-communication paths of the proposed design. This lets you create a more complete view of the overall communication architecture as opposed to any one specific scenario.
Focus your attention in Figure 5 on the Controller object. Through a review of several Sequence Diagrams, we have identified all object-to-object connections and represented them as single collaboration connections between the object instances. This simplified view makes it clear that the controller is a central object in our overall solution. You can also see from this level of detail that the Scanner and Router talk to each other directly. Additional details could be added to indicate the specific direction and content of the collaboration. For now, we are mainly concerned with the high-level view of who talks to who, rather than what they are saying (which is best shown in the Sequence Diagram).
Real-Time Considerations
The very nature of real-time embedded applications makes certain characteristics of their implementation (such as timing and implementation architecture) critical. Usually, the software in these applications is responsible for the control of other equipment, so designing a correct solution requires a systems view.
The issues of real-time support in UML are being addressed by the RTAD (Real-Time Analysis and Design) working group of the Object Management Group (OMG). This working group has representatives from several tool vendors (including Artisan Software Tools, http:// www.artisansw.com/, the company we work for) and other industry representatives. The approach we present here is Artisan's proposal. Although there are no standards yet, this approach embodies some of the fundamental concepts from the current thinking of RTAD.
Multitasking Systems
Most real-time embedded systems are, by nature, multitasking solutions to real-world problems. They typically deal with the interface and control of multiple external devices. The different parts of these systems usually run at different priorities and with different run-time characteristics. The notion of multiple tasks or threads being active in the system at the same time is common. Many of these real-time systems are deployed on a set of microprocessors in a distributed architecture. Designing a solution for this type of problem requires a system-level task design that captures these details.
Figure 6 shows tasks, standard communication primitives, and global data. The task symbol (the parallelogram) is frequently used and is suggested as the symbol for the "active object" in UML. This, and the channel symbol (see New Containers, for instance) are well known in real-time design through DARTS (see Software Design Methods for Concurrent and Real-time Systems, by H. Gomaa, Addison-Wesley, 1992, ISBN 0-201-52577-1). We have added a number of symbols that represent frequently used RTOS primitives, such as an Event Flag (Router Warm Start), Signal (Emergency Stop), Semaphore (Position Mutex), and Global Data or Pool (New Position).
We will look at one approach to representing a system-level task design that represents the architecture for the multiple threads of execution present in the application. The elements from the object design constructed using UML (Figures 4 and 5) map onto the task design (Figure 6). Collaboration Diagrams, like those in Figure 5, capture the interobject communication in a task-independent view. The primary information captured in a Collaboration Diagram is the message connectivity between objects. The characteristics of the concurrency are not easily captured in the Collaboration view.
There are three cases for the object-to-object communications in a multithreaded environment:
- Within the same task (intratask).
- Between two tasks on the same processor (intertask, intraprocessor).
- Between two tasks on different processors (intertask, interprocessor).
In the latter two cases, the interaction should also be modeled in the system task design because the actual messaging will not be through direct object method calls. A tasking view of the system helps to understand the complex implementations of intertask messaging, shared data access, throughput, and synchronization issues. Representing the details of a multitasking view of the solution is difficult in the standard UML.
Concurrency Diagram
Artisan's approach for dealing with the multitasking design for a system using a Concurrency Diagram can be thought of as an extension of the Collaboration Diagram. The Concurrency Diagram shows several useful aspects of the system using additional notation for tasks and the intertask connections. By focusing this specialized view on the multitasking issues, we can model the overall task structure of the solution as well as the communication mechanisms between tasks. By dealing primarily with the active objects, it is possible to then map the object architecture (Figures 4 and 5) into a multitasking solution. Nonactive objects can also be included in the Concurrency Diagram view for clarity of some interactions.
Through the Collaboration Diagram(s), we tackle the definition of object interaction, which feeds into our task design. Another approach to task design is to model the natural concurrency in the problem domain. In our sample process-control system, there are a number of tasks identified to handle the various interfaces in the system such as the Detector, Scanner, and Move Router. In Figure 6, we model the initial task structure to mimic the parallel operations performed by the system. In addition to the tasks (or active object threads), we are also modeling the interface devices and the specific communication channels between the tasks. This gives a clear picture of what concurrent threads (or tasks) will be running in our solution. For example, in Figure 6, the Scanner communicates with the Detector via the Controller task, which queues messages "New Containers" to a buffer. However, the Scanner talks directly to the Move Router task.
UML has no straightforward provision for specifying the implementation of the interobject communications when they occur across task boundaries. The intertask communications are usually handled by the run-time environment either by constructing application-specific communication objects in the application (semaphores and queues) or by using primitives in the underlying executive. In either case, by modeling the communication mechanisms (queue, signal, and so on), the subsequent elaboration of these artifacts in the source code is better understood.
Dealing with Time
Real-time systems are, by definition, constrained by some aspect of time. The requirements driving the development of these systems often state specific timing considerations. It is critical to capture this timing information while modeling the system to specify a reasonable system design and to support system test.
The two main categories of timing information that can be modeled in an object-oriented system are:
- Latency, which is the amount of time it takes for two objects to collaborate (that is, to communicate via messaging).
- Duration, which is the amount of time required for an object to perform its processing once it has received a message.
Through a combination of latency and duration specifications, we identify general timing constraints for a set of operations.
Sequence Diagram Revisited
Sequence Diagrams provide a logical place in the modeling view to capture this timing information. The timing requirements associated with a particular system function are modeled in the Use Cases and mapped through the Sequence Diagram(s) onto specific interactions between objects. Where UML defines the notation and diagram contents, modern modeling tools supporting UML usually have some form of underlying repository for storing additional information and relationships. UML allows general notes to be added to any diagram. The definition of specific properties is not called out nor precluded by the UML definition. Modeling tools can support diagram annotation as well as diagram artifact attributes or properties. By making timing information an explicit attribute of the representations on the Sequence Diagram, the timing requirements are mapped directly onto the appropriate events and operations for each object and stored in the tool's repository. The timing information is then usable in other views of the system (class design). Artisan's Real-time Studio is one such tool that manages the timing information through explicit message properties.
Figure 3 illustrates specific timing attributes associated with the messages (horizontal lines) and the operations themselves (vertical blocks). For example, our process-control system has a 75 ms latency on the "Arrives" message that takes 100 ms to process the action. In addition to the individual timing attributes, it is also useful to specify overall timing constraints on a set of operations as on the far right side of Figure 3. Here, the total for the Dynamic Scan Cycle must be less than 2 seconds, thus making sure we can meet the 30 containers per minute requirement on the "Process Units" Use Case.
Architecture Representation
Real-time embedded systems contain both hardware and software elements as part of the solution. A thorough understanding and representation of the physical structure, software/hardware interfaces, and system boundary is important for construction of an application that not only meets functional requirements but can be deployed into the proper environment.
UML provides a Deployment Diagram (Figure 7) for capturing some of this information. The Deployment Diagram shows various nodes in our system with packages and processes (tasks) enclosed in these nodes and connections between the nodes and items on the nodes. However, in real-time embedded systems, the physical architecture has implications beyond simple placement of software on connected nodes. The types of connections (point-to-point, multidrop bus, or whatever) between the nodes, as well as the connectors (PCI, serial, ISDN, and so on) can play an important role in defining the proper architecture for the system. More importantly, the node characteristics themselves (processor configuration and memory maps) are vital to deployment and debugging of the target system.
To examine the software/hardware mapping more closely, Artisan defines three separate layers of the system called the "Solution Architecture." These layers are modeled as Object, Software, and System Architectures. Figure 8 shows a conceptual view of these three layers along with the logical mappings of information between them. This multilayer view will help us put the other views in perspective. One of the strengths of using a modeling tool for capturing the various views of the system is that it also allows you to relate information between the views. This capability is not readily available in simple drawing tools and not very extensive in some modeling tools.
Object Architecture
The Object Architecture defines the logical object-oriented solution to the problem. It consists mainly of Class, Collaboration, and Sequence Diagrams. UML is well suited to this level of the solution design. The Object Architecture does not rely on any implementation-specific mechanisms until well into detailed design. In Figure 8, the objects (interface, control, entity, and so on) can be further organized based on their role or responsibility in the design. With this partitioning, it is easier to identify the active objects and concurrency requirements that are handled in the next layer.
UML defines the notion of a Package Diagram, a simple addition to the class architecture we have defined so far. Packages are useful for organizing classes into collections based on some criteria (for example, common functionality, access boundaries, directories, build packages, and so on). The Package construct can be used on existing Class Diagrams or separate views can be constructed to represent this information. By organizing the system components this way, packages provide an excellent mechanism for dealing with scalability and reuse. Packages are also the implementation artifact that will map into the physical model. You can see two Packages in Figure 4: The Transport Equipment has been grouped together, and so has the Robotics software.
Software Architecture
The Software Architecture defines the overall partitioning of the application into executable tasks and persistent data stores. The Concurrency Diagram in Figure 6 represents the multitasking model of the solution. The mapping binds active objects from the Object Architecture to their corresponding task representations in the Software Architecture. It is also possible to bind object communication mechanisms between the logical Object layer and the Software layer.
It is through these relationships between the two layers that a final system design can be evaluated. In Figure 8, objects (or classes) in the logical model are mapped to an active task in the Concurrency Diagram. Each task (the active thread) is associated with only one object/class between these two diagram views. These associations are not shown here, but captured in the relationships managed by the modeling tool.
System Architecture
The third layer represents the physical structure of the system. In essence, it replaces the UML Deployment Diagram. It is defined using a notation that represents a simple set of hardware building blocks. These building blocks support the software, system, and hardware engineer's view of the physical deployment environment. Artisan calls this a System Architecture Diagram. This view is made up of processing nodes (or boards), storage nodes (or disks), interface devices, connections (both point-to-point and multidrop), and subsystem collections of these items.
In Figure 9, a preliminary System Architecture view of our system, you can see the specification of separate processors for the Scanner and Robot Router parts as well as a central control unit for the rest of the transport application. They are linked together on a common bus to complete the physical connection of the system. You also see various configuration details about the processor nodes in this solution (analog interface ports on the Scanner) that are part of the modeling view. The attributes or properties of these physical architecture elements (memory location, IRQ, quantity, and so forth) are maintained as properties in the underlying repository.
Although they are not visible on the diagram, the specific implementation characteristics of these components such as memory size, location, speed, bandwidth, and quantity are modeled in the System Architecture view. Recording this information in the model and sharing it between system, hardware, and software engineers improves the interproject communication and lessens the chances for software/hardware integration errors later on in the project.
Another important difference with this approach lies in the handling of the relationships between object components, software tasks, and physical nodes. Instead of trying to represent all of this information on a Deployment Diagram as is done with UML, Artisan believes that it is better managed through underlying modeling relationships between separate, distinct and more detailed views. Mapping the packages from the Object Architecture and the tasks' Software Architecture representations onto the System Architecture and viewing these relationships through a repository metamodel browser allows for a more complete perspective of how the system is specified. This facilitates analysis of correct design and implementation decisions.
System Boundary
One often overlooked consideration when modeling the solution is the external interface boundary. There is no simple consolidated view in the UML. Artisan recommends capturing the actors defined for the Use Cases as well as the interface devices from the Concurrency Diagram and System Architecture Diagrams on a single view called the System Scope Diagram. The System Scope Diagram uses the same notation as the other views in the model to define the external actors, interface devices, and system software boundary in a single view. This view is useful in determining the system boundary; in other words, what is inside the solution and what is outside this context.
The System Scope Diagram (Figure 10) can be used early in the problem analysis to help isolate the boundary of the analysis activity. The System Scope Diagram provides a simple graphical checklist of all of the external and interface boundaries in the solution. It is an easy way to make sure that the complete problem is being addressed.
Conclusion
UML provides a usable framework for object-oriented solutions. In its current version, it covers most of the views necessary to construct a reasonable solution to a given problem. Use Case and Sequence Diagrams allow for the definition of system functionality and processing required for typical scenarios. Class Diagrams give you tools for showing the static structure and relationships of the pieces (classes) of the solution. Collaboration Diagrams document the overall structure of the communication of the objects in the application.
However, several aspects of real-time systems development require additional support. By adding complementary views and notation, UML can be naturally extended to better define and design real-time systems. By applying these combined modeling techniques, the resulting system definition is more complete, the solution design is more accurate, and the system development (programming) is more straightforward. A correct solution is more likely if the software, hardware, and system engineers have a common and agreed upon view of the functionality and implementation of the application. The extensions presented here provide this common foundation.
References
Cooling, J.E. Software Design for Real-time Systems. International Thomson Computer Press, 1991, ISBN 1-85032-279-1.
Douglas, B.P. Real-time UML: Developing Efficient Objects for Embedded Systems. Addison Wesley, 1998, ISBN 0-201-32579-9.
Fowler, M. UML Distilled: Applying the Standard Object Modeling Language. Addison-Wesley, 1997, ISBN 0-201-32563-2.
Gomma, H. Software Design Methods for Concurrent and Real-time Systems. Addison-Wesley, 1993, ISBN 0-201-52577-1.
Moore, A. and N. Cooling. "Real-time Perspective -- Foundation." Artisan White Paper, 1997.
---. "Real-time Perspective -- Overview." Artisan White Paper, 1997.
Rumbaugh, J., M. Blaha, W. Premerlani, F. Eddy, W. Lorenson. Object-Oriented Modeling and Design. Prentice Hall, 1991, ISBN 0-13-629841-9.
UML Version 1.0 Notation Guide, 13 January 1997.
DDJ
Copyright © 1998, Dr. Dobb's Journal