Unified Modeling Language is about communication. But in order for communication to work, it must be useful. How do you make sure that you don't sweat over a set of UML diagrams only to discover that no one else can understand them? Fortunately, there are guidelines, discussed in this article, to help prevent this catastrophe. This article is excerpted from chapter three of the book UML Applied: A .NET Perspective, written by Martin L. Shoemaker (Apress, 2004; ISBN: 1590590872).
IN THE LAST CHAPTER, we spent a long time working through the process of Five-Step UML, and looking at all of the new UML notation which that entailed. But in this chapter, we’re going to take a quick break from learning all the formal rules and all the step-by-step instructions on how to use UML as part of a modeling process. Instead, I’m going to present a set of pragmatic guidelines that will help you stay on the right track during your development work.
By this point, you may already be tired of hearing me say that UML is about communication. But that’s easy to say, and much harder to do. Listen to any political speech, and you can hear lots of words with no real meaning communicated. Read the telephone book from cover to cover, and you’ll find lots of factually accurate information that’s too voluminous and too complex to be useful.
The same sorts of things can happen with UML diagrams: you can make a set of diagrams that seem to say something, but that actually fail to communicate. You can pour time and sweat into getting the lines just right and all of the right icons in the right places, only to find that no one else can understand what you drew. You are, quite literally, back to the drawing board.
This frustrating event is going to happen to you. Nothing can prevent it, and it’s part of the normal, healthy design process: the missteps are merely steps to a better design. The only designers who never design anything poorly are those who never design anything. But there are some common mistakes that you’ll see in your own work and in that of others.
The following guidelines are my attempt to warn you away from some of these mistakes. And despite some of the names, they are guidelines, not rules. You can break them, and still communicate. Sometimes you must break them in order to communicate. But when you find that one of your diagrams is failing as a communication tool, check these guidelines: chances are, the bridge for your communication gap is here somewhere.
Do What Works
The number one guideline is that simple: Do What Works. Not what’s right. Not what’s “supposed to be done.” Not even what I tell you to do. Just what works. At the end of the day, if you don’t communicate, if you don’t solve a problem, you haven’t succeeded. Don’t let me or anyone else sell you on “the one true way to produce software.” We may be very bright (or think we are), and we may have really good reasons for what we’re saying; but maybe those reasons depend on factors that don’t apply in your situation.
And this is (unfortunately) a slippery rule: “what works” changes for different purposes, different problems, different audiences, and a range of other variables. I’ll look at that in a bit more detail in the next three sections.
If your purpose is to document an existing system, you’ll probably start with Class and Component Diagrams that reflect its structure, and then add Interaction Diagrams to show how that structure works, and then add Use Case Diagrams to show the externally visible behavior embodied by those interactions. Then, as you extend and maintain the system, you’ll update and add to those diagrams. But if your purpose is to design a new system, on the other hand, you’ll start with Use Case Diagrams to depict requirements in context, and then work in. If your purpose is to understand a strange bug, you might start with Interaction Diagrams. Your purpose will also determine the level of detail you apply: if you’re just trying to understand some existing code, you might apply much less detail than you would in designing new code.
For a small problem, too much modeling can bury you in paperwork, and you’ll suffocate. For a large problem, not enough modeling can mean that your vision isn’t abstract enough to encompass the system at varying levels of detail. For a familiar problem, a single stereotype icon on a diagram can convey pages of meaning to the team; and too much detail really doesn’t communicate anything new, because “We’ve seen all this before.” For a new problem, you’ll need much more detail, because people need lots of help learning the new domain.
For your fellow developers and designers, you’ll add lots of detail. These people are basically pre-reviewing your code by reviewing your design; but if you don’t include enough detail to demonstrate that you know what you’re doing, trust them to call you on that. (And if you can’t trust them for that, what good are they?) But for business analysts, customers, and other nontechnical stakeholders, this detail is just clutter: they don’t know what it means, they don’t want to know what it means, and they’ll get it wrong if they try to know what it means. For them, you draw less-detailed diagrams, but perhaps try to fit a broader scope into each diagram.
A .NET Perspective
In particular, what works well for me in .NET modeling is reverse engineering. My UML tool of choice, Rational XDE, is one of many that will generate the elements of a model from your source code. So often, after I have gathered requirements and started on a shell of architectural design, I’ll use the powerful tools in Visual Studio .NET to generate the basic components of my architecture; and then I’ll reverse engineer those components into my models and incorporate the reverse-engineered elements into my UML diagrams and designs. So I’m not a modeling purist: sometimes I start with a model and lead to code, and sometimes I start with code and work towards a model. But either way, my real approach is circular: code leads to models leads to code leads to models leads to . . .
Using a Tool
So though I describe some useful steps for applying UML, my real technique is to do whichever step makes most sense next. That’s one advantage of a good modeling tool like Rational XDE: no matter what I discover or envision, there’s a place for it in the model, and I can put it there quickly, explore it as much as I need to right now, and go back to what I was doing when the topic came up, with only minimal interruption. Then later I can go back through the model and find all these proto-ideas and work on fleshing them out. The model evolves very naturally this way. And that leads us to . . .