At some level, it is fair to say that any language that can be executed is necessarily a programming language; it's just a matter of the level of abstraction. So, is executable UML yet another (graphical) programming language?
An executable UML model completely specifies the semantics of a single subject matter, and in that sense, it is indeed a "program" for that subject matter. There is no magic. Yet an executable UML model does not specify many of the elements we normally associate with programming today. For example, an executable UML model does not specify distribution; it does not specify the number and allocation of separate threads; it does not specify the organization of data; it does not even require implementation as classes and objects. All of these matters are considered decisions that relate to hardware and software organization, and they have no place in a model concerned with, say, the purchase of books online.
Decisions about the organization of the hardware and software are abstracted away in an executable UML model, just as decisions about register allocation and stack/heap organization are abstracted away in the typical compiler. And, just as a typical language compiler makes decisions about register allocation and the like for a specific machine environment, so does an executable UML model compiler make decisions about a particular hardware and software environment, deciding, for example, to use a distributed Internet model with separate threads for each user window, HTML for the user interface displays, and so on.
An executable UML model compiler turns an executable UML model into an implementation using a set of decisions about the target hardware and software environment.
There are many possible executable UML model compilers for different system architectures. Each architecture makes its own decisions about the organization of hardware and software, including even the programming language. Each model compiler can compile any executable UML model into an implementation.
The notion of so many different model compilers for such different software architecture designs is a far cry from the one-size-fits-all visual modeling tools of the past.
Here are some examples of possible model compilers:
Multi-tasking C++ optimized for embedded systems, targeting Windows, Solaris, and various real-time operating systems.3
Multi-processing C++ with transaction safety and rollback.2
Fault-tolerant, multi-processing C++ with persistence supporting three processor types and two operating systems.
C straight on to an embedded system, with no operating system. 3
C++, widely distributed discrete-event simulation, Windows, and UNIX.
Java byte code for single-tasking Java with EJB session beans and XML interfaces.
Handel-C and C++ for system-level hardware/software development.
A directly executing executable UML virtual machine.
A single model compiler may employ several languages or approaches to problems such as persistence and multi-tasking. Then, however, the several approaches must be shown to fit together into a single, coherent whole.
Of these, some are commercially available, as indicated by the references provided above, and some are proprietary, built specifically to optimize a property found in related systems produced by a company, such as the fault-tolerant multi-processing model compiler. Some are still just prototypes or twinkles in our eyes, such as the last three.
As a developer, you will build an executable UML model that captures your solution for the subject matter under study, purchase a model compiler that meets the performance properties and system characteristics you require, and give directives to the compiler for the particular application. Hence, a system that must control a small robot would select the small footprint C model compiler or one like it, and a system executing financial transactions would prefer one with transaction safety and rollback.
The performance of the model compiler may depend on the allocations of application model elements, and a model compiler may not know enough to be able to allocate a particular class to that task or processor for the best performance. Similarly, a model compiler that provides persistence may not know enough about your subject matter to determine what to make persistent. Consequently, you will also need to provide model compilerspecific configuration information. Each feature provided by the modelcompiler that does not have a direct analog in executable UML will require directives to determine which feature to use.
These choices will affect performance of the model compiler. One particularly performance-sensitive feature is static allocation to tasks and processors. Allocating two classes that communicate heavily with different processors could cause significant degradation of network performance and of your system. If this is so, of course, it's a simple matter to re-allocate the elements of the model and recompile. This is why executable UML is so powerfulby separating the model of the subject matter from its software structure, the two aspects can be changed independently, making it easier to modify one without adversely affecting the other. This extends the Java notion of the "write once, run anywhere" concept; as we raise the level of abstraction, we also make our programs more portable. It also enables a number of interesting possibilities for hardware-software co-design.