UML style – an example

Last autumn I posted a personal UML style guide, followed soon afterwards by a detailed explanation of my reasoning for not including associations. Those articles had quite a positive reception (thanks), but patterns and heuristics can only go so far. So this article presents a (long) worked example to show my UML style in action. I make no claims for the resulting model – except that it works for me, and seems to satisfy those who are able to persuade me to create UML models. I should also point out that I usually – ie. when I have the opportunity – jump right to the last page; what you see here is one conceptual route to that end point…

Fade to an imaginary office somewhere in the north of England. It’s the end of an imaginary project in which we’ve developed an XP planning game tool in Java (this example is based on the Planning Game Simulator exercise in Bill Wake’s excellent Refactoring Workbook). The customer has scheduled a story to document any “interesting” parts of the design, as a roadmap for the code’s future developers and maintainers. We select the tool’s status bar, and we decide to draw a UML model to convey the following information:

The status bar always displays a summary of the plan (number of cards, their total cost, current velocity, and number of iterations required to complete the backlog). Whenever a card is added to or removed from the backlog, or when a card’s cost changes, or when a card is split, the Plan re-calculates everything and the status bar updates itself to show the new information. The status bar does this by listening for change events thrown by the Backlog; when one occurs it requests the latest information from the Plan and displays it.

We begin by drawing a static model showing the classes involved, with their relationships, methods and packages. This is the kind of model created by one of those reverse engineering tools that reads our code and constructs a thorough model of it all:

uml1

Note that I have not shown attributes; nor have I shown every method. They aren’t relevant (and I got bored typing). Note also that it is a big stretch from this model to the above outline description. In my opinion this kind of model tells us loads of unimportant stuff and very little that’s genuinely useful. Let’s see what we can do about that. First let’s correct those associations so they show the correct navigability:

uml2

That already helps, because it removes some implied, and incorrect, information from the diagram.

Now, the inheritance relationship between PlanSummary and JLabel is an implementation detail. All we really need to know is that the View package makes use of Swing. We can say something similar about the use of Observer and Observable: what’s important is the application of the Observer design pattern, wherease the use of those two specific classes is an implementation detail. Where a dependency follows a well-known pattern, I’ll tend to use a stereotype to indicate the fact.

uml3

That already seems much clearer to me (and note that I was also able to get rid of that update() method on PlanSummary – again, it’s part of the implementation of the Observer-Observable relationship, which is already completely described by that stereotype.

Next, I notice that the list of methods on Card and Backlog add nothing to the story told by the diagram:

uml4

I’ve also replaced the methods on Plan, instead listing attributes as a way of showing the Plan’s responsibility to know these things. It feels dirty to do so, and runs counter to my principles; but right now they do convey the information that the Plan has a velocity distinct from the Backlog.

Note that I also removed the spurious multiplicities on the non-navigable ends of those associations. I wouldn’t want my reader to infer that a Card can belong to only one Backlog, for example. The code doesn’t implement that restriction, so the original model was incorrect to include these.

At this point it could be argued that the Product-Backlog and Backlog-Card associations should be depicted using one of the containment or ownership adornments. But I find that too to be an implementation detail. True, the Plan’s constructor creates a Backlog instance, but that’s surely a detail of the code. In domain terms, it is perfectly reasonable to “construct” a plan around an existing backlog, and a different sequence of refactorings might have brought this code to such a structure. The adornment would only serve to constrain the model, and thereby to increase the probability that it might need to change if the code were refactored in the future.

And now I’m going to remove the remaining multiplicities too! This is a static model; the entities shown are all classifiers. But those multiplicities count instances, which I find to be incongruent. More importantly, I don’t believe they add anything to the story told by the picture. And so we are left with dependencies, pure and simple.

uml5

And so, at last, we come to BacklogEvent. Clearly there is no such concept in the domain (Ken Schwaber’s books don’t mention BacklogEvents, for example). It was included in the model simply because it exists in the (current) implementation: Every time the Backlog is changed it creates a new BacklogEvent instance to convey both the event type and the affected Card (via the Observer-Observable mechanism) to anyone who’s listening. The only reason we require a BacklogEvent class is because the Java implementation of the observer pattern passes only a single argument back to the listener via the notification method. Some part of the planning game’s code needs to get both the action and the affected Card, hence the need for this little bundle.

Does the diagram convey all of that last paragraph? Or indeed any of it? No. Does it need to? Again, I would argue that it doesn’t. We can’t come close to describing all of that in the diagram, and anyway it is all in the code. So my final static model would be the following:

uml6

If pressed, I might concede that BacklogEvent is an interesting concept at some level of detail. But how to convey everything we said above? My preferred approach, to which I will only resort under duress, is to show the BacklogEvent as a kind of association class. The class is the “message type” within that dependency, and at the same time acts as the medium for those messages. Marshall McLuhan would be proud…

uml7

I’ve also taken this opportunity to move the classes around so that the dependencies all flow rightwards or downwards, following the reader’s eye. Its only a convention, but I now find it easier to follow the flow of delegation among the classes.

So, we now have a static model that, in my opinion, conveys only what’s important and nothing else. But is that all we can do? It still isn’t easy to read the original story from this model – because the story was dynamic and this model is static. And so I offer the following instead:

uml8

I could argue that either the static model or this collaboration model is sufficient to depict the original story. But I also note that the text version took significantly less time to create…

Advertisements

One thought on “UML style – an example

  1. Pingback: a personal UML style guide « silk and spinach

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s