Cloudfier applications are fully defined UML models that comprise structure, dynamics and behavior and, as such, can be executed as regular programs.

But how do you specify behavior in UML?

Behavior in UML

Since version 1.5, issued in 2003, UML models can specify behavior, via what is often referred to as action semantics. That initial support was much expanded in the 2.x versions of the language. In essence, action semantics introduce:

  • detailed behavior can be described in the form of activities
  • activities can be used to define the behavior of operations, objects, states, transitions, constraints etc, wherever behaviors are supported (think of activities as procedures)
  • an activity is a hierarchy of activity nodes
  • activity nodes can be control nodes, object nodes, and executable nodes/actions
  • control nodes are things like InitialNode, ForkNode, MergeNode etc, that you will typically find in activity diagrams
  • object nodes are data sources/sinks, connected by edges where data flows through, called object flows
  • executable nodes, or more specifically, actions, which are atoms of behavior in UML models. You can think of them as the instruction set of the UML machine.
  • actions can take inputs and produce outputs via (respectively) input and output pins, which are object nodes
  • data travels between actions via object flows, which connect an action’s output pin to another action’s input pin

Predefined actions

UML has predefined actions for everything you need in an object-oriented, event oriented program, and then some more:

action-hierarchy
I challenge you to find a more comprehensive set of primitives, be it as instructions in an instruction set or system calls. The primitive actions unlock functionality for manipulating all the UML elements that would be useful when building software, such as classes, instances, operations, attributes, relationships, signals, etc. Yet, as rich as this set of actions is, you won’t find anything related to low-level concerns, such as memory allocation, I/O handles, etc, and that makes sense, as those things belong to the computer domain and are not relevant in application domains.

Also, note there is no representation for these primitive actions in the UML notation, so if all you do with UML is limited to diagrams, you probably have never used them.

Notation, notation, notation

But how do Cloudfier applications use those primitives? As I mentioned before, you won’t be drawing any diagrams in Cloudfier. Instead, you use TextUML, a textual notation for UML that gives you access to most (not all for the time being) of the primitive actions above.

Here is an example:

 
operation rent(car : Car)
    precondition CarMustBeAvailable(car) { car.available }
    precondition OneRentalPerCustomer { self.currentRental == null };
begin
    var rental;
    rental := new Rental;
    link RentalsCustomer(customer := self, rentals := rental);
    link RentalsCar(car := car, rentals := rental);
    send CarRented() to car;
end;

which if you are wondering, makes use of several primitive actions:

  • CreateObjectAction (new Rental)
  • AddVariableValueAction (rental := ...)
  • CreateLinkAction (link RentalsCustomer(customer := ..., rentals := ...))
  • ReadVariableValueAction (rental)
  • SendSignalAction (send CarRented() to ...)
  • ReadSelfAction (self)
  • ReadStructuralFeatureValueAction (car.available)
  • ReadLinkObjectEndAction (self.currentRental)
  • StructuredActivityNode (begin ... end)

Also, notice how a textual notation naturally allows describing the data flows via parameter passing, assignment and symbol references. Behind the scenes, each data flow is an edge connecting the producer action’s output pin to the consumer action’s input pin.

You can learn more about the support in TextUML for UML actions under TextUML Behavioral Notation in the TextUML documentation. Also, head to the Cloudfier documentation to learn how to create Cloudfier applications.

What about fUML?

fUML is a OMG specification that that builds on the existing support for executable models in UML, selecting a subset of elements that are required to support executability (ignoring the others), and adding a layer of precise semantics where required to eliminate vagueness or ambiguity in the base specification.

The support for executable UML models in Cloudfier is not based on fUML, as it predates it. Instead, Cloudfier implements executability on top of the basic UML standard. There are a lot of similarities between them though (which is not surprising, since fUML is strongly tied to UML).

So, if fUML was created to eliminate imprecision in UML, and Cloudfier is not built on fUML but on the base UML, doesn’t that mean that Cloudfier builds on top of an imprecise specification? Yes, in some areas the base UML specification can be quite vague or ĺacking, and leave a lot of room to interpretation to implementers. Wherever that was the case, the compiler, interpreter and code generators in Cloudfier all share a common interpretation of UML, eliminating the ambiguity (an exercise similar to what had to be done in the definition of fUML). Whenever a choice had to be made, the driving force has been the target audience of Cloudfier: business applications. A consequence of this is that it suggests Cloudfier is not the best tool for other kinds of applications that typically make use of executable UML models, such as embedded/real-time applications – and that is fine, as those kinds of applications are already well served by existing tools, which has not been true for business applications.

What about Alf?

Alf is a surface notation for fUML, and is also a OMG standard. TextUML, the surface notation used in Cloudfier, is not related to Alf, other by the fact that they both are notations for executable models in UML, with TextUML mapping to the base UML, and Alf mapping to fUML’s view of UML. But, in terms of level of abstraction, abstract syntax and semantics, they are quite similar.

You can learn more about both fUML and Alf in a previous post by Ed Seidewitz, who was heavily involved in both specifications.

Great, now what?

Here you learned about how UML models represent behavior. In future posts we will see how Cloudfier can run executable UML models and how to take advantage of that by executing models directly (for rendering prototypes, or running tests).

Want to build better software faster?

Want to build better software faster?

Read about the latest trends on software modeling and low-code development

You have Successfully Subscribed!

Pin It on Pinterest

Share This