The xUML Modeling Language

Here we explain the core models of Executable UML. Note the use of the term "model" instead of "diagram". A diagram is one, and often the primary, way of viewing a model. It is often helpful to distinguish these ideas. For example, the UML state machine diagram is usually an incomplete view of the state model since it emphasizes what to do when an anticipated event occurs that triggers a transition. It tends to ignore the handling of unanticipated events, or events that are ignored and do not trigger a transition. This is not to say that the diagram view of a state model isn't useful, it is. It helps clarify the lifecycle of the associated class. But a state table presents a complete view of how all events are handled while de-emphasizing the overall lifecycle. Either way, it is the model that we execute and later translate into code, not some particular view of the model.

Note: For now we have a brief overview of each topic. The plan is to add a "Learn More" button to each of the topics below to provide examples, tutorials and further explanation. Watch for those buttons in the near future!


The Domain Model

A domain represents a subject matter of relevance to a software project. The subject matter may be modeled in Executable UML, in some other modeling language or just hand coded or exist as legacy software. In all cases, once built, a domain is always specified at an executable level of detail. In other words, a completed domain can be run, just like a program.

A domain model (typically viewed as a domain chart) is a set of interdependent domains describing a complete software system. Each domain is understood to "required the services of" some other domain. This dependency mechanism serves to systematically filter details out of one domain so that they can be modeled in some other domain.

There are, of course, many ways to divide a complex software system into separate packages. (By task, by processor, by function, by project department, etc) What is so special about a domain separation? For one thing, platform independence. A domain model need not be changed to suit different implementation technology.

Consider the domain "linear algebra" for example. It is a distinct subject matter. This means that there are language elements (matrices, vectors, etc). There are distinct rules, constraints and policies defined on those elements (the algebraic definitions). There are behaviors (matrix multiplication). But most importantly, the subject matter can be defined independent of any particular implementation.

Imagine that you build an Executable UML model of linear algebra for some reason. You can implement that domain as a single math library. Or you can implement it as several libraries. Or you can implement it as one or more cloud services. And in all cases you have a choice of implementation languages. There is nothing about the subject matter "linear algebra" that requires an understanding of how some version of WIndows or Linux works. Similarly, every domain in a domain model is a distinct subject matter that can be modeled without regard to any particular implementation technology.

Class, State and Action Models

Each domain that we choose to model in xUML consists of these three core models. Each is a required facet of a fully executable package.

For any language to be executable, three components are required. There must be a way to define data (the things of interest in our subject matter), control (when activity can and cannot happen) and processing (computation and communication). In other words and in reverse order, "what you're doing", "when you're doing it" and "what you're doing it to". In a programming language you have data structures (data), threads, loops and tasks, etc (control) and functions, methods, assignments and operations (processing). In xUML we have the class model (data), the state model (control) and actions (processing). Unlike a conventional programming language, the three elements of executability are separated into three distinct models. Not only that, we build those models in a particular order. Class model first, state models second and finally we insert the actions. See the section on Development Process to see why these models are separated and built in that order.

CM K3.png

The Class Model

A class model defines the things of interest in a subject matter, their characteristics, their relationships and the rules and constraints that bind those things.

A common misconception is that the class model is just a "model of data" and therefore a thing of secondary interest. The state models and the actions are where the real work gets done, right? Wrong.

The class model establishes the vocabulary of a subject matter. Just as in natural language, complex problems are difficult to solve with an inadequate or imprecise vocabulary. Furthermore, the class model is where powerful logical expressions are defined which constrain what can and cannot happen in a domain. If you wanted to say, for example, that an Air Traffic Controller can log into a Station only if they are On Duty, you would say that in a class model.

It is best to think of a class model as nailing down precise concepts and constraints necessary to make true or false statements about what can and cannot happen in a domain. As a byproduct, you also end up with a model of the necessary data.

A poorly thought out class model will lead to unnecessarily complex state models and actions.

SM K1 resize.png

The State Model

The behavior of each class is defined with a state model. This is initially expressed using a UML state machine diagram to express the lifecycle of a class's instances. Since a class represents a set of things with the same behavior, it stands to reason that each class must be represented by at most one state model. (Not all classes exhibit behavior worth modeling. A read-only specification class, for example).

An instance of a class is, at any given time, in exactly one state of its state model.

An instance in one state model communicates with another (and to itself) by means of asynchronous signals. A class collaboration diagram is typically sketched out to organize communication across among multiple state models in the same domain. Delegation and control layering patterns are established with such a diagram.

A distinctive feature of xUML is that it defines a simple set of platform independent synchronization rules. These rules make it possible to verify correct synchronization of a model so that it can be maintained on multiple platforms. For example, if an elevator door class is constrained such that it cannot be in the OPEN state while its cabin is in the MOVING state, that coordination can be guaranteed across all concurrent or non-concurrent platforms. Implementations of this required synchronization will vary considerably across platforms, but the models need not be altered to accommodate some particular synchronization feature of a given platform technology.

The Action Model

Computations on data, decisions, communication among state models, and interactions with external domains are defined with actions. An action language establishes the primitive actions and means of combining them into useful expressions.

In UML, actions are expressed within activities. In xUML, activities can be in states, class methods, domain operations, external entity operations. A state activity, for example, is executed whenever an instance enters that state. The action language, and hence actions, written within that activity is then executed.

xUML actions are based on a data flow interpretation of processing. This data flow interpretation describes processes that input and output data and control flows. A process may execute whenever all of its input data flows have data and input control flows (guards) are enabled. Consequently, the actions written in an activity do not necessarily proceed sequentially as they would in a traditional programming language. The only action sequences specified explicitly in the model are those essential to the subject matter (platform independent).

Since the models do not specify unnecessary sequencing, the implementation can take full advantage of whatever concurrency mechanisms are available in the target language or platform.