Relationships in Executable UML Diagrams
March 17, 2009
In order to specify the behavior of an operation in a UML model so that it can be executed, we have to have a syntax for refering to classes that relate to one another. Lets say I have a class A that uses another class B via an aggregate relation. Some operations in class A, will need to refer to instances of class B via the relation, One problem that I have encountered, is how to refer to the instance of class B used by class A.
Normally in an object-oriented programming language we just use an object field, and that is that. However, in UML people may use a relation that is named or unnamed, that may or may not have role names, that has optional directionality, and may include multiplicity.
In the literature on executable UML the recommendation is to name every connector: R1, R2, and so-on, and to use that to refer to the related object. One syntax used is the following:
instanceB = select one B related by instanceA->B[R1];
This is too awkward for me. One alterantive solution that I investigated to use was to use role-names.
instanceB = instanceA.roleName
This is more object-oriented, but the reality is that role-names are not present in most diagrams. It is a lot of work to require modelers to add role-names to all diagrams.The other possibility I investigated was to restrict all relations to aggregations and compositions which have an implicit directionality. This way we could use the relation name itself.
instanceB = instance.R1
I was pleased with this solution for a bit until I started to have multiple class diagrams sharing the same model.
One important advantage of UML is that you can have multiple diagrams, which act as different views of the same class model. A problem occurs when we have a class diagrams (call it View2) that use class A, but not class B, in which the connector is omitted. It is hard to write operation on class A from within View2 when there are implicit dependencies on class B not present in the diagram. This would become a huge problem if class A exists in multiple diagrams. You would have to keep in mind all the relations from all the diagrams at once in order to write the operations. It just doesn't scale.
This led me to make the design choice that all relations are required to be modeled as attributes. All relationships in a diagram, including the relation name, role name, and multiplicity is provided purely for informative purposes. This way all relations between classes needed to write and read operations would be present. The formal semantics are then restricted to the classes, attributes, operations, and a few other key elements.
This makes the UML diagram become a kind of persistent visual commenting system, while the formal/executable portions are contained primarily in the operations and attributes. A disadvantage of this approach is that it introduces a degree of redundancy (all named relations will also have corresponding attributes). However, given a model with named relations we could easily write a tool that generates the necessary attributes.
So in the end my approach to executing UML models is veering away somewhat from the approach used by other executable UML tools, but luckily these tools and the current approach to executable UML doesn't have a ton of traction. There are currently only a couple of tools on the market that I am aware of (Bridgepoint from Mentor Graphics and iUML from Kennedy Carter), and they are extremely expensive.
I hope this post isn't too esoteric for my readers. Let me know if you would like to know more about what I am doing, or have any questions.