Designing ColdFusion Applications With UML

Have you ever watched actors improvise? It's quite fun; you never know what's going to happen. But imagine if a movie director decided a script wasn't necessary at all.

After all, the actors know the plot and know the most about their characters, so why not let them improvise. Wouldn't this lead to a more creative and realistic movie? I think we can all see that this would simply lead to a confusing story with no consistency. The actors are expected to impose their own talents on their roles, but they need a script to guide them along.

Developers are no different, yet I see "improv developing" all the time. A project manager will just describe what's needed - the outlines of a plot - and let the developers work it out. The results are often what you'd see with a movie. However, designing an application with UML can act as a script for developers. They're still free to use their own creativity and experience when implementing the design, but the UML documents provide them with a map of what the final product should be.

So it's no surprise that UML is quite popular in many software development communities, and you even see it used occasionally for ColdFusion. Yet how can ColdFusion developers really leverage UML to avoid improv development?

I'd like to show you some ways I've used UML to help me design ColdFusion applications. In this article I'll first explain what UML is, then how to read it, and finally how to create it.

What Is UML?
UML or Unified Modeling Language isn't a markup language like HTML or XML, and it's not a programming language like CFML. It's a unified method for modeling systems. This is usually used for software, but it can model any system. There are a number of benefits to designing an application. Like better team coordination, faster development cycles, and more scalable application designs.

Whether you're a freelance, corporate, or Open Source developer most of us need to work on a team. By designing an application upfront project managers can get a bird's eye view of a system before development starts. This lets them divide the work among multiple developers or groups. It also lets those developers know what to expect from the other part of the system without having to open the code.

Designing a system first also forces the designer to consider how the system will work before coding begins. Instead of putting those decisions off until later, they're made earlier. It's easier and faster to move a few blocks around a diagram then it is to refactor code. UML will help uncover faulty design decisions and reveal potential problem areas.

Lastly, most well-designed applications will pay close attention to the separation of concerns (SoC). MVC (Model-View-Controller) is one common way to achieve SoC. In fact, most ColdFusion frameworks are designed to enforce MVC (they often take the role of the controller). UML also helps enforce better application designs, like MVC. This creates more scalable, stable, and bug-free applications.

Reading UML
Most UML diagrams are fairly intuitive; you can glean most of what you need simply by studying them. But to write good UML you need to have a basic understanding of the notations used and what the different symbols mean. So before I show you how to use UML to create a ColdFusion application I'll explain a few of the elements you'll see in this article and how they relate to ColdFusion.

Class Symbol
At the heart of any OO application are "classes." In ColdFusion these are most directly related to components (CFC). The most basic symbol of a class in UML is just a box with the class's name in it like:

You might notice that there's a colon before the class name. Anything to the right of the colon is the class's name; anything to the left is the name of the specific object like:

This comes in handy when documenting an interaction between specific objects of a class, especially when two objects belong to the same class and you have to distinguish between them. But most of the time when designing an application you only see a class name.

If more details are needed about the class, this symbol can be expanded on. One or two more boxes can be added, the first containing the class's properties and the second its methods like:

There's a special notation used to list properties and methods in these blocks.

Here's the notation for properties:

-propertyname: datatype

The first character is a plus or minus sign, which stand for a private (-), or public (+) property. In a CFC, this means that you'll either scope the properties with "VARIABLES" (private) or "THIS" (public). You'll almost always have private properties, so you'll almost always use the minus sign to prefix your properties. The property name is whatever name you intend to give this variable inside the code. The name is followed by a colon and the data type of the property. For example:

If I were to open the "MyClass.cfc" file, I'd expect to see these lines of code:

<cfpoperty name="name" type="string" />
<cfpoperty name="age" type="numeric" />

And I'd expect to see these variables referred to as VARIABLES.name, and VARIABLES.age.

The notation for methods (known as functions in ColdFusion) isn't all that different:

+methodname(argument: datatype, argument: datatype): datatype

As you can see, the methods start off the same way as properties, with a plus or minus to indicate public or private. Then the name of the method itself is listed. The real difference is what follows the method name: a set of parentheses containing a list of the method's arguments. Each argument follows the same format as the properties - name:type. After the arguments is whatever data type, if any, the method itself returns. Let's expand our previous example:

Now if I open the MyClass.cfc file I'd expect to see this code:

<cffunction name="getString" access="public" returntype="string">
    ... code ...
</cffunction>
<cffunction name="setAge" access="private" returntype="void">
    <cfargument name="age" type="numeric" required="true" />
    <cfargument name="x" type="boolean" required="true" />
    ... code ...
</cffunction>


Relationships
Classes don't live in a bubble; they interact with one another. Any sort of interaction between classes is a type of relationship. A relationship is illustrated with a line or arrow between the two classes. There are many kinds of relationships in UML, but we'll focus on just three in this article, associations, generalizations, and messages.

An association means that one class uses another in some way. That could mean the first class utilizes a method of the second. Or it could mean that the first class contains the second as one of its properties. For example:

In this example, the Person class has an "addr" property that has a type of "Address." So there's an association between the two classes. The association line also has its own notation. At each end of the line is a "multiplicity" and in the middle is a "descriptor":

The descriptor in the middle simply describes the type of relationship. The multiplicities at each end of the line indicate how many of these classes are involved in the relationship. If you've ever worked with database schemas these may look somewhat familiar to you. Values can be a comma delimited or two dots (..) that indicate a range of values. An asterisk indicates an unknown number. For example:

0..      Zero or 1
*      Any amount (zero or more)
1..*      Any amount greater then one
1,3,4      1, 3, or 4
1..6,10      1 through 6, or 10

These association lines should actually be readable top-down, left-to-right. So in the example above, one person has zero or one address.

The second type of relationship is a "generalization." This is when one class inherits another; in ColdFusion this is called extending. The rule of thumb is if you can say that "A is a type of B", then "A is a generalization of B". Or you could say B extends A. A generalization is noted in UML with a solid line with an open arrow at one end. For example:

This says that a Geek is a kind of Person (they really are you know). In the Geek.cfc I'd expect to see this code:

<cfcomponent extends="Person">
     ...code...
</cfcomponent>

The last type of relationship you'll see in this article is messages, which are used in collaboration and sequence diagrams. Messages are when one class calls the method of another class. An arrow between the two classes is how we illustrate a message, usually with a description or method name just above or beside it. You'll see more on how messages are used in UML when we cover collaboration and sequence diagrams.

MVC symbols
As we said, UML can help enforce better MVC design. There are actually three special symbols used to indicate those kinds of elements:

What does Model-View-Controller mean?

For a great example of using MVC in ColdFusion take a look at "ColdFusion Best Practices" at www.benorama.com/coldfusion.

These symbols can be put inside the class icon to indicate the type of class:

This isn't official UML - to my knowledge - but I've found it to be very useful.

Creating UML
There are a few basic UML diagrams I use to design a ColdFusion application. A UML diagram can't be created in a single pass. Like writing a story it takes a number of iterations to refine and complete. The process we'll follow here will help us gradually explore and define each diagram, using one diagram to help explore the next. The point of this process will be to generate a suite of diagrams that will tell you almost anything you need to know about how your application will work. The basic suite I use consists of three diagrams: a Class Diagram, a Collaboration Diagram, and a Sequence Diagram. This is only a subset of the UML diagrams available, and complex applications may require other more specialized diagrams to complete the suite. But in this article we'll only look at creating that core set of diagrams.

The Class Diagram
The first thing I do when designing a system is to create a class diagram. What's the point of a class diagram? It's a view of all the system's elements and how they'll interact with one another.

To get started we'll need to identify our classes. There's an old trick in the OO world that will work well here. Take the Use Case, or whatever document you used to gather the system's requirements, and highlight all the nouns. Take those nouns and put them into an Excel spreadsheet. Only put each noun in once, ignore duplicates, and ignore pronouns. This is the initial list of classes.

Next, in the column following the nouns, enter what type of class or element the noun is. Common possibilities are Model, View, Control, Property, or Other:

Don't stress the class identification too much; it's really just to help get the class diagram started so it does not have to be perfect. Just take your best guess; you can always change it later. We can now start the class diagram. Put all the classes from the spreadsheet into the diagram and note what kind of class they are (Model, View, Control) using the three symbols. Also add any properties you identified. Now add any relationships, methods, or properties that are obviously going to be needed. You're still drafting the class diagram so just put in what you know will be needed, and don't worry about how it looks, we can clean it up later.

Let's say I'd like to create a very basic to-do list application. In this application the user goes to a task list page and all his uncompleted tasks are listed. He can mark a task as completed or add a new task by naming it and clicking an "add" button. To start my class diagram I'll take whatever requirements document I have, even if it's just a description like what I just gave, and identify the nouns. I use that to draft a class diagram, and add a few of the obvious relationships, methods, and properties. This is what I end up with:

It's far from complete; most of my classes don't even have any details. I just fill in what I know so far.


The Collaboration Diagram
The first draft of the class diagram is now complete. Now we'll use the class diagram and make our collaboration diagrams. Start by copying the class icons from your class diagram to a blank diagram. Draw lines between the elements you think will interact with one another. Add a stick figure to represent the user and draw an arrow from the user to the first element in the diagram the user will interact with. Put a number "1" next to this arrow followed by a description of the interaction. Let's use the task list application from our previous example:

Then determine what the next interaction will be. In our example the TaskList view would have to get the list of tasks; let's assume it would get that from the User class:

Keep doing this, step-by-step, mapping the interactions of the application. This is another area that a Use Case, if available, can help. Again, don't worry about it being perfect just do your best. Here's what I ended up with after walking through my description of the task list application:

You might notice a few things. First, I used fractions for numbering some of the step (like 1.1, 1.2, 1.3...). This is a common technique to keep a series of step clear and it also makes it easier to add more steps later. The important thing is to keep the diagram clear and easy to read. I could even create three separate diagrams for each of these sequences if I felt that would be easier to read.

Second, you might notice that the TaskList page goes to the ManageTasks controller to update or add a task. Why do I do this instead of just updating the Task element? Well, as mentioned before when talking about MVC a view element can't modify a model element, it mostly goes through a controller. This is simply how I've chosen to architect my application. If you have a different standard, or use a framework, the collaboration diagram is still completely applicable; you simply diagram the interactions according to your own standards.

The Sequence Diagram
Now we have the first draft of the collaboration diagram. We've already revealed some relationships that were missed in the class diagram. But let's not revise the class diagram just yet; let's create a sequence diagram first to clarify these details even more. We'll use the collaboration diagram to create the sequence diagram. Once again start with a blank diagram and copy all our classes over to it, but line them along the top side-by-side. Put the views on the left, the controllers in the middle, and the models on the right. Then add another user stick figure on the far left. Below each of these draw dashed lines; these are the "lifelines" of the elements:

Now we'll map the same sequence of events from the collaboration diagram in more detail. Start with the first interaction on the collaboration diagram and draw a line from the user to the TaskList:

Notice I gave this arrow a short name that describes the interaction and put blocks on the two element's lifelines. These blocks represent activity. This first interaction is nothing existing, so let's move on to the next step in the sequence, step 1.1 from the collaboration:

Ah, now things are more interesting. This time we have an interaction between the system elements, so instead of a description of the interaction, we actually gave it a method name. Now we not only know that these two elements interact with one another we're actually defining what methods will be used during the interaction. You might also notice the dotted line arrow going from the User back to the TaskList; this is a return message, and I've noted that an array is being returned. Now we've even defined what kind of information the method will return. Let's move on to the third step, 1.2:

Notice how I've taken "Get each task's information" and expanded that out into two methods, getName() and isCompleted(). Also notice the box around those methods with the funny looking upper-left corner titled "loop." This is how UML frame's special logic flows. This obviously indicated a loop. The note in the lower corner states "[each task]" meaning we'll loop the framed content once for each task. In other words, we're going to get the name and completion status of each task. Right after the loop we simply return the page to the user.

Keep walking through each interaction on the collaboration diagram adding them to the sequence diagram, giving system interactions actual method names. Here's what I came up with for our task list application:

There are two things worth noting in this diagram. First, there are arguments for some of the new methods I added. I noted those by simply adding them in the parenthesis of the method.

The second thing I'd like you to notice is that the diagram doesn't specify how the TaskList calls the completeTaks() or addTask() method. This could be done with AJAX, a normal page refresh, or by posting to the CFC as described on www.benorama.com. The sequence diagram is very flexible this way; it helps clarify how elements will interact and communicate, but can apply to many different technologies or techniques. The previous sequence diagram could apply to Java or PHP just as easily as ColdFusion.

Rinse and Repeat
We now know a great deal more about how our application will work than we did when we first created the class diagram. Now it's time to revise the class diagram based on what we discovered in the collaboration and sequence diagrams:

This revision might have resulted in new classes, or classes being dramatically changed. Don't shy away from making drastic changes, that's what this process is all about.

Are we done? Not quite yet. We now repeat these steps, returning to the collaboration diagram to refine it further, and adding anything we might have missed the first time. Then revise the sequence diagram and go back to the class diagram. We'll repeat this process until we feel confident that the diagrams are complete and accurate.

Summary
This article covered some very basic UML. No single article can cover UML in its entirety; that would be like trying to explain everything about ColdFusion in a single article. But in the end the suite of diagrams I've showed you here will describe an application in great detail, and give you a starting point from which to explore UML further. One could hand these diagrams over to a developer - just like someone would hand a script to an actor - and improv development would be avoided.

© 2008 SYS-CON Media