Blog-Archiv

Sonntag, 13. Oktober 2019

UML Diagrams with PlantUML

There is a free Java tool called PlantUML that offers to create UML diagrams through programming in a domain-specific-language, instead of graphically drawing boxes and lines.

I used PlantUML for some months, and had ups and downs with it. The ups took place when drawing sequence diagrams. Downs I had with all other kinds of diagrams when trying to give them good layout.

Simple Example

This is a small class-diagram example, suitable to quickly show how things are done using PlantUML.

@startuml

legend
  An airport can have several terminals.
  A terminal can have several gates.
endlegend

Airport *-{ Terminal
Terminal *-{ Gate

@enduml

Store this text into a file named airport.puml. Then download plantuml.jar, place it into the folder where the file is, and launch following commandline:

java -jar plantuml.jar airport.puml

An image file named airport.png will be generated, and you can view it through any image viewer.

A more convenient way to work with plantuml.jar is following command:

java -jar plantuml.jar -gui

This starts a graphical user interface that will list all .puml files in directory. Moreover it will immediately generate an image for every newly created file. Double-clicking onto an list item will open a built-in image viewer that displays the diagram in a new window.

This is how the class-diagram above looks like:

Try it out by yourself at the online-server.

Vertical Variant

If you want the boxes to be vertically arranged, you must increase the edge lengths (!) by adding a "-":

@startuml

Airport *--{ Terminal
Terminal *--{ Gate

@enduml

Result:

Styling

Of course you can customize colors and lines using PlantUML skinparams. Names of skinparams can be listed using following command:

java -jar plantuml.jar -language

Comments

Commenting out lines can be done via quotes:

@startuml

' single line comment

/' multiline
  comment '/

@enduml

More Complex Example

Following is a component-diagram that describes how to use an airport for departure.

@startuml

legend
  Check-in starts about 3 hours before take-off.
  Mind that automated check-in will not accept your non-cabin baggage,
  and you may want to get rid of that because it contains your camping knife!
  Airports differ in where and when they check passports, boarding card
    and cabin baggage.
  Boarding (at the gate) starts about 60 - 30 minutes before and normally
    includes an accurate cabin baggage check (knives will be confiscated).
  Boarding closes 20 minutes before flight.
  State officials that check passports will **not** help you find your gate!
  
  **Unchecked (cabin) baggage**: what you take into the aircraft and put into
    the rack, 7 kg, must not contain a knife or liquids, can contain a laptop.
  **Checked (hold) baggage**: what you give to the airline on check-in, 23 kg,
    may contain a knife, don't put laptop into it.
  Baggage must not exceed 55 x 38 x 20 cm.
  Damaged baggage must be reported (written) within 7 days, delayed baggage
    within 21 days.
endlegend

skinparam rectangle {
 roundCorner 30
 borderColor gray
}

package "Airport A" {

  package "Terminal 1" {
  
    rectangle "Public Access / Departure" as publiczone {
      "**Check-in**:\nShow passport and ticket,\nassign seat,\nleave hold baggage,\nget boarding card" as check_in

      check_in -> [Airline C]
      [Airline B]
      [Airline A]
    }
   
    rectangle "Transit Zone (passengers only)" as transitzone {
      stack "Duty-free shopping"
      
      package "Gate A1" as gate {
        "Cabin baggage check,\nshow boarding card\nand passport" as board
      }
    }
    
    publiczone ==|> transitzone: Say Goodbye, you're leaving the country.\nShow boarding card and passport.
    
    queue "Aircraft for Flight ABC-123" as flight
    board ==|> flight: Show boarding card, passport.
    
  }
}

@enduml

Here is how the departure diagram looks like:

You see that I used some tricks like inline text formatting (bold font, newlines) and skin-parameters (to style the inner boxes).

Now this is quite acceptable I think, although the red edges are much too long, and they touch the text. And - why is the legend on bottom when I wrote it on top?

Anyway, let's create another diagram for arrival:

@startuml

legend
  In case an immigration form is required, make sure you filled one
  before standing in long lines at arrival passport checks,
  because you may be sent back to fill one and then again stand in line!
endlegend

skinparam rectangle {
 roundCorner 30
 borderColor gray
}

package "Airport B" {

  package "Terminal 2" {
  
    queue "Aircraft for Flight ABC-123" as flight

    rectangle "Transit Zone" as transitzone {
      "With cabin baggage" as unboard
    }
   
    flight -> unboard
   
    rectangle "Arrival" as arrival {
      "Get hold baggage" as passenger
    
      passenger <- [Hold luggage conveyor for Flight ABC-123]
    }
   
    transitzone ==|> arrival: Show boarding card, passport,\nmaybe immigration form.\nYou are entering the country.

    rectangle "Public Access / Arrival" as publiczone {
      "City Train"
      "Taxi"
    }
   
    arrival ==|> publiczone: Customs, then say Hello!
  }
}

@enduml

Here is how the arrival looks like:

This is not acceptable. Look at the edges. Why do they bend so ugly? Why don't they go straight down?

Here the PlantUML weakness shows up. It is the automatic layout done by GraphViz, which is a native library, not Java. The way how PlantUML and GraphViz work together is not the best one.

Now you may say "It is the edges that are too long!". So let's make them shorter by taking away a "=":

@startuml
....

    transitzone =|> arrival: Show boarding card, passport,\nmaybe immigration form.\nYou are entering the country.

    ....
   
    arrival =|> publiczone: Customs, then say Hello!

....
@enduml

I don't want to show the result. The diagram now expands horizontally, the edges are cluttered, obscuring the text. You can try it out by yourself. It is not acceptable.

The only way I could improve this is by adding following instruction:

@startuml

skinparam linetype ortho

....

@enduml

Then it looked like this:

Still the red edges are much too long and unnecessarily crooked. The first one looks like it is not related at all to its text, the second one obscures it.

Layout with PlantUML is really time-consuming. You have to find out the techniques that PlantUML built in to manipulate GraphViz. Moreover I uncovered platform differences, the diagram looked differently when rendered on WINDOWS, LINUX or at the online-server, or when rendered with different versions of GraphViz and PlantUML.

Conclusion

Use PlantUML for sequence diagrams, here it shines. This is because PlantUML doesn't use GraphViz for it. Don't use PlantUML for anything complex unless you want your readers shake their heads and skip your diagram.




Keine Kommentare: