What's the second biggest news in the object-oriented development world at the moment? It's the Unified Modeling Language (UML), which will replace all of those analysis and design methods (Booch, Coad, Jacobson, Odell, Rumbaugh, Wirfs-Brock, and so forth) with a single new notation endorsed by the Object Management Group (OMG). This will finally eliminate a tedious range of arguments about which method software developers will use. We will enter a new period of harmony, brotherly love, and increased productivity (and have a good snicker at those old structured methods which, despite their greater maturity, never achieved such a standard).
If you were a keen user of one of these B.S. (before standardization) methods, you'll bite the bullet and switch over to the UML, muttering darkly about how it missed feature x from your favorite method and how you don't like features y and z cluttering it all up. But have you really stopped to think about why a modeling notation such as the UML is useful?
Ask a methodologist (in our industry that's someone who invents a methodology) and you'll get a stern lecture on software quality. Methodologists will talk about how our industry suffers from the software crises, problems of poor software quality, the importance of good design, and so on. This is all well and good (although I think the software industry has done pretty well over the last decade), but how exactly does the UML help? Ask a CASE tool vendor and you'll get a lecture on improved quality, automatic documentation, and the productivity value of code generation. But we all know what CASE tool vendors are after.
If you're a developer who is suspicious of all this methods stuff as yet another management fad, and you shudder at the thought of all the useless paper that gets generated, then the UML is just another notation to pretend to care about. At least there's only one now. Still, you know that the next time you have to modify a system, these UML diagrams that are supposed to be so helpful will be several generations behind the code you have to fix.
I got into methods early in my software career. Since I have an engineering background, they seemed to be a natural field of interest for me. Most branches of engineering have drawings that describe how things should be built, and you take great care that things are done according to the drawing. I saw methodology diagrams in the same way. In time, I learned the lie of that analogy, but I still find methods useful. This despite the fact that I have a lot of sympathy for developers who dislike methods.
To describe why I find the UML useful, I first must start with a quick reminder on the scope of the UML: it's a modeling language, not a method (or methodology). The UML defines a number of diagrams and the meaning of those diagrams. A method goes further and describes the steps in which you develop the software, what diagrams are produced in what order, who does what tasks, and so on. The idea behind the UML is that it is method-independent. Over the next year or two, we will see various people come up with methods that use the UML notation. But you don't have to use a method to make use of the UML. In this article, I'm not going to assume any fixed method of development.
So if we strip away all the method trappings, what are we left with besides a handful of types of diagrams that you can draw? The question, "What use is the UML?" becomes "What use are these diagrams?"
The answer boils down to one word: communication. This is an important word. The main reason software is deceptively hard to develop is communication. We know how easy things would be if we could only sneak off for a weekend and code away. The difficulty arises because we must communicate with multiple developers. The UML is important because it can help software developers communicate. We have to use it in a way that helps communication and does not hinder it.
Figure 1. A UML Container of Java's AWT Container Classes |
You might prefer the diagram or you might prefer what I said in the previous paragraph. This depends on whether you are familiar with the UML and whether you prefer a visual or narrative statement. For this situation, I prefer a visual, but there are those who prefer the text, even if they understand the diagrams. You could give them the text or (perhaps better) a selection of code (as shown in Listing 1). Which would you prefer? Which do your colleagues prefer? These questions are the crux of the role of the UML and similar languages. I've found that some prefer text, others prefer the diagram, some prefer the diagram for some things and the text for others. In the end, the diagram is only worthwhile if it enhances communication.
In addition to what the diagram shows, you should also note what the diagram does not show. All of the classes mentioned have much larger interfaces than either Figure 1 or Listing 1 indicate. I've also failed to mention that Layout Manager is an interface, or that Component implements a number of interfaces. Many would thus criticize Figure 1 for being incomplete. Incomplete it is, but is that a failing? In the diagram, I made a decision about which features of the depicted classes to show and deliberately did not show others. The fact that I show only some of these features highlights the features that I've shown.
Selecting information to give it emphasis is an important part of communication. In any group of classes, there are some aspects that are more important to understand to gain an initial comprehension of the classes. If you show everything, you fail to make that distinction, and your reader has no idea what is important to understand first and what is detail to be absorbed later. When I use class diagrams, I use them for this initial comprehension, to understand the key aspects of the classes about which I'm talking. I know that the reader can always go to the javadoc files to get a complete statement of the interface.
I encourage you to use class diagrams in this selective manner. Not only does this improve the communication value of the diagrams, it also makes them easier to keep up to date. You don't have to change the diagram for every little change in the class. Since one of the biggest problems with these kinds of diagrams is the difficulty of keeping them up to date, this is an important advantage.
As well as encouraging selectivity, I also encourage an emphasis on interface rather than implementation. I've shown an attribute of isEnabled on Component. This doesn't say that the Component class has a field called isEnabled (I actually didn't look, because it doesn't matter). It says that from the outside, you can assume the class has such an attribute, which you would access through the appropriate operations. Ideally, there will be a naming convention for these operations (in the Java library these days, this is isBooleanAttribute and setBooleanAttribute). I don't show the operations on the class because I find the attribute notation communicates the intention of the code better. This attitude extends to associations too. I have no idea what data structure exists between Container and Component, the operations suggest the association.
Many people draw class diagrams from an implementation perspective: the attributes and associations to reflect the data structure. This is valuable if the data structure is what you wish to communicate. Often, however, the interface is what's most important. You should decide what it is that you wish to communicate and follow that perspective.
I find diagrams are also useful when discussing a design and how you might change it. If you have a group of designers working on a design, try sketching the designs on a whiteboard. Draw a few alternatives. I find it's a valuable way to visualize what we're talking about. (CRC cards are another good technique for this.)
A particularly important variant of this technique is when I am working with a domain expert to try to understand the domain for which we are building a system. In this situation, I use minimal notation and concentrate on the concepts in the domain expert's head rather than any particular software situation. I've found it easy to teach this conceptual modeling style to people without a software background. Then, using the diagram, we can jointly develop a well-defined vocabulary to talk about the domain and can come up with abstractions that are useful both in discussions and in the final software. This was a great boon to me when I worked with complex domains such as healthcare and financial trading.
Standardization is valuable here because it enhances communication. It's difficult to communicate with people when they use a variety of diagramming styles. By having a single standard, we can be sure that if people know any diagraming styles, they will know this one. But don't let this go too far. The UML contains a lot of notation, and there's no rule that says you must use all of it. Try to use a fairly minimal part of the notation, and don't use the advanced concepts unless they're really necessary. Although you should stick to the standard as much as you can, I'll admit I'm not afraid of bending the notation if need be. I don't do it often because each bend has to be explained and is going to be unfamiliar to the reader-but if it enhances communication, I do it.
So if you're new to the UML, try it out as you need to communicate ideas. Experiment to see what works and what doesn't. Learn the notation by using it, and learn it gradually. If you're more experienced with modeling notations, you should have no difficulty adapting to the UML-but beware of taking it too far. Remember its primary purpose. Be aware of how well your diagrams are communicating. Don't leap into more complex use of the UML than your readers can handle. And remember to be selective and to highlight important information. n
Listing 1. Java Interfaces for Figure 1public abstract class Component { public Container getParent(); public boolean isEnabled(); public boolean isVisible(); public void setEnabled (boolean b); public void setVisible (boolean b); ... } public class Button extends Component {...} public class Label extends Component {...} // other component subclasses public abstract class Container extends Component { public Component add (Component comp); public void remove (Component comp); public Component[] getComponents(); public LayoutManager get Layout(); public void setLayout(LayoutManager mgr); ... } public class Panel extends Container {...} public class Window extends Container { public void show(); public void dispose(); ... } public class Frame extends Window { public String getTitle(); public void setTitle(String title); public boolean isResizable(); public void setResizable (boolean b); ... } public class Dialog extends Window { public String getTitle(); public void setTitle(String title); public boolean isResizable(); public void setResizable (boolean b); public boolean isModal(); public void setModal(); ¡ } |