UML Best Practice: There are no Activities on an Activity Diagram

Short

Don’t use Activities on an Activity Diagram

Purpose

Model useful and UML compliant Activity Diagrams

Detail

UML Activity Diagrams are often used to depict a certain flow of events. One of the reasons Activity Diagrams are so popular is because they are very similar to flow charts, something all of us know from long before UML even existed.

So lots of people start out enthusiastically to draw Activity Diagrams.

Lets say that we are modelling the checkout at a cash register of a store.

We start out with an InitialNode called Start and then we draw a ControlFlow to the Activity Scan Items. We then continue with the Activity Process Payment and end up in the FinalNode Finished.

Checkout_simple_hor

So far so good, but now we want to deal with customers who need an invoice. In order to be able to print an invoice we need to ask the customer for its details such as name, address, VAT-number etc… After getting the company details we can process the Payment, and when the payment is finished we print the invoice.

When using Activities there are two possible solutions to model this workflow.

Checkout_DuplicatePayment

The first solution is to split up the flow into a Company flow and an Individual flow, but as you can see this would force us to duplicate the Process Payment activity; which is not acceptable of course. Duplicate elements very quickly turn your model into a maintenance nightmare.

Another solution would be to come back to the single Process Payment activity after registering the Company details.

Checkout_DuplicateDecision

But then we would need to split up the flow again after the Process Payment. This time we are not duplicating an activity but a decision, which is almost as bad. Another drawback is that this makes our activity diagram less readable because we can’t easily distinguish the two flows.

No the only real solution is to use Actions on the diagram instead of Activities.

Checkout_Actions

Now all Activities have been replaced by Actions, and the Process Payment actions now both invoke the same Process Payment Activity.

To conclude:

  • Activity: used to contain an Activity Diagram
  • Action: used put on Activity Diagrams

More UML best practices

UML Best Practice: 5 rules for better UML diagrams

Following these 5 rules will make your UML diagrams easier to understand, cleaner, and more consistent.

Although that has no effect on the actual model, it will improve the communication with the stakeholders.

Rule 1: Less is more

Large diagrams containing heaps of elements actually convey less information then small focussed diagrams.
When reading such a large diagram your audience will not know what to focus on, and since there’s too much on there to actually pay attention to all elements, they will quickly give up trying altogether.

Show up with a diagram like this at your stakeholder, and you will have already lost his/her attention even before you start talking.

The diagram above is a good indication of how much, or how little, you should put on a diagram. My rule of thumb is that you need to be able to print the diagram on a single A4 sheet while keeping things readable.

Rule 2: No Crossings

This is a fairly common and well known rule. Try to avoid any two lines in your diagram to cross each other.

Uncrossing lines in your diagram sure make it more readable and understandable, but there’s more to it then that.  If you are unable to uncross the lines on your diagram then that is a sign that

  • a) there’s too much on the diagram (see rule 1 Less is more)
    It might be that you are showing two different aspects of the model in one diagram. In that case it might be better to create two different diagrams, each focused on one aspect.
  • b) there is some kind of design flaw in your model
    For some reason well designed models don’t have the crossing lines problem. I have no idea why or what it is exactly, I just noticed that a lot of the times, when I’m unable to “uncross” all the lines in a diagram, I discover a design flaw that, when fixed results in a diagram without crossing lines.
The following diagram contains exactly the same information, but has just been ordered differently as to make sure there are no crossing lines.

Rule 3: Orthogonality

It seems like a small thing, but making the lines in a diagram go only horizontal or vertical, and having all only right angles makes a diagram look better instantly.

The diagram below is uses a direct style for its connectors. they all go directly from one element to the other with a straight line.

The mere fact that the lines have all kinds of angles makes the diagram look a lot messier, and less understandable.

Below here again the same diagram, but now with all connectors styles set to orthogonal.

Exceptions to this rule are (for me) note links and all relations with use cases. For some reason they look better with a direct style.

Rule 4: Parents Up

When drawing generalization or realization hierarchies on a diagram always make sure the parent elements are higher then the child elements so the arrows always point upwards.

This rule is pretty intuitive for most UML modelers. Only now and then I encounter diagrams that don’t follow this rule and have their hierarchies upside down.

Diagrams like this, where the generalization arrows point downwards are harder to read. For some reason it takes a greater mental effort to understand this then when the arrows all point upwards.

In case you have multiple elements all descending from the same parent, it is recommendable to show the hierarchy in a vertical tree style.

Rule 5: Tidy Up

I realize this sound like a nagging mom, but for crying out loud: Tidy Up!

If you want to convey the message that your analysis is a well thought trough construction that will solve your stakeholders problems then you better show up with a nice and clean diagram.

When tidying up think about

  • Aligning elements, either by one of their sides (e.g Top) or by their centers. The latter works best when aligning vertically
  • Make elements the same size where possible

After tidying up the diagram looks a loot better

Now remember, following these diagramming rules will not make you a better analyst, nor will it result in better UML models.

But it will allow you to make a better impression when trying explain the fruits of your hard labor to your stakeholders. You will need less time explaining diagrams, and you will be able to spend more time focusing on the actual content.

More UML best practices

UML Best Practice: Attribute or Association

Short

Use Associations for Classes and Attributes for DataTypes

Purpose

Make an informed choice between Attributes and Associations when modeling a relation between two Classifiers.

Details

When modeling the structure of your system there are basically two ways to express a structural relationship between two Classifiers. You could use an Association between the two Classifiers, or you could create an Attribute owned by one Classifier with it’s type set to the other Classifier.

Both ways, Association or Attribute are pretty much equivalent. There’s not really a big difference between the two except for personal preferences.

The problem with modeling teams working on the same model is of course that you can’t allow personal preferences, you have to make a clear choice what to use in which circumstances.

To explore the details of the two approaches it is best to have a look at the UML meta model.

In this meta diagram we see that both the Attribute as the Association use the same Property object to link to a type.

The association has two or more Properties as MemberEnd. Each of these Properties has a Type, so that is the way the association links two or more Classes. The derived link from Association to EndType is derived from the type of the Properties in the memberEnds.

The Attribute of a class is in fact a Property in the ownedAttributes of a class.  Again through the fact that a Property is a TypedElement an thus has a Type as “type” we get the relation to another Classifier.

In the years I’ve been working with different modelling teams I’ve found that the rule that works best is to use Associations for Classes and Attributes for DataTypes.

Now whats the difference between a Datatype and a Class? Well, they are actually pretty similar. The UML specification states:

A data type is a special kind of classifier, similar to a class. It differs from a class in that instances of a data type are identified only by their value.

So that means that DataTypes are much like the primitive types and enumerations we know in the programming world. This concept is generally referred to as being immutable. So you can think of things like Integer, Date, MoneyAmount, but also enumerations such as Color, DayOfTheWeek etc..

If we add Datatype and Enumeration to the meta diagram we get following

You can see that DataType is a subtype of Classifier, and that Enumeration is a subtype of Datatype.

Following example shows how to use Classes and Datatypes when following this best practice.

In this diagram we see two Enumerations: Currency and ProductCategory. ProductCategory is being used as the type of the attribute Product.Category while Currency is being used by the Datatype MoneyAmount.

I’ve added dependencies to visually express which Datatype is being used by which Classifier, but those dependencies are usually not there in a production model.

More UML best practices

UML Best Practice: One Operation => One Sequence Diagram

Purpose

Model the implementation of your operations with a single sequence diagram for each operation.

Details

Most UML models I’ve seen in my career contain classes with attributes and operations. An Operation is a specification of a behavioral feature. Adding an operation to a class means that you are specifying that your class will respond to a specific request by executing a certain behavior.

So the operation defines the details of the request to be sent to the class (such as name, parameters…), but it doesn’t specify the details of what needs to happen when the operation is called. Those details are stored in a Behavior, and the operation specifies which behavior needs to be executed when it is called.

In the UML metamodel that looks as follows

The abstract Behavior is linked to the abstract BehavioralFeature where Behavior has the role of method and the BehavioralFeature has the role of specification.

So please never again mix up the terms Operation and Method, these are two different things!

From this diagram we also learn that Behavior is actually an abstract metaclass, and that there are four concrete subclasses of behavior that can be used to be the method of the Operation.

  • OpaqueBehavior
    A simple textual definition of the behavior one or more languages (such as English, Java, C#…)
  • Activity
    The natural owner of an Activity Diagram
  • StateMachine
    The natural owner of a State Machine Diagram
  • Interaction
    The natural owner of a Sequence Diagram

From these four choices I’ve had the best experience using Interactions containing a Sequence Diagram to express the method of my operations.

Enterprise Architect Example

I created a small example in Sparx Enterprise Architect to illustrate this:

This view of the project browser shows the class MyClass, containing the operation MyOperation. Then there is the MyOperation Interaction which contains the MyOperation Sequence diagram.

In order to specify that the MyOperation interaction is the method of MyOperation operation you need to link them in the Behavior tab of the operation. Clicking the Element button will allow you to select the Interaction to use.

This interaction owns a single sequence diagram which contains the actual details of the implementation.

For the sequence diagram itself I have the following rules or habits:

  • First Message
    The first message, calling MyOperation on MyClass is not strictly necessary, but it helps the reader to quickly identify for which operation this is the implementation, without having to search for the operation in the model.
  • caller
    The gate “caller” is the representation of any other object calling the MyOperation operation on MyClass. It is important to keep this “caller” anonymous, even if there is only one class that effectively calls MyOperation. In the future other classes may start using MyOperation as well, and we don’t want to start duplicating the sequence diagram to include all the callers of this operation.
  • Only messages from MyClass
    Since this sequence diagram represents the implementation of the operation MyOperation I only want to show what happens in that operation. So the sequence diagram will only have messages starting from MyClass and it will not show any details of the implementation of operations on SomeOtherClass or YetAnotherClass. These operations will all have their own Interaction and sequence diagram to specify their behavior.
  • Objects for “non-static” operations, classes for static operations.
    Non-static operations are always called on instances of a class.  Static operations are called on the class itself. Notice the difference between the object “:SomeOtherClass” and the class “YetAnotherClass”.

To quickly navigate between operations and sequence diagrams I of course use the free and open source EA Navigator add in.

More UML best practices

update 29/05/2011: Changed the “Caller” lifeline into a gate as suggested by Davide. Thanks Davide!