UML Diagrams with PlantUML and SwiftPlantUML

PlantUML is an open-source tool used to produce an assortment of diagrams using text. With other diagramming tools, the paradigm is typically a GUI and some dragging and dropping of various objects to build up your diagram. PlantUML allows you to forgo the dragging and dropping element and write your diagram in PlantUML’s own markup language.

As an example, if you’re looking to model out a data structure for a Book in your app, you might come up with the following information your app needs to know about:

  • Book
    • ISBN (a UUID for books)
    • Title
    • Author
      • UUID
      • Name
    • Publisher
      • UUID
      • Name
    • Number of pages
    • Release date
    • Cover Image
    • Category
      • Description

What PlantUML allows you to do, is to pass in syntax that resembles plain English to model out this data structure. The above structure looks like the below in the PlantUML syntax:

@startuml

// Defines our data objects.

struct "Book" { 
  ~isbn : String
  ~title : String
  ~author : Author
  ~publisher : Publisher
  ~numberOfPages : Int
  ~releaseDate : Date
  ~coverImage : String 
}

struct "Publisher" { 
  ~id : String
  ~name : String 
}

struct "Author" { 
  ~id : String
  ~name : String 
}

struct "Category" { 
  ~description : String 
}

// Defines the relationship between them.

Book ..|> Publisher
Book ..|> Author
Book ..|> Category

@enduml

And when the above syntax is plugged into PlantUML, you get something that looks like the below:

A UML diagram showing the above syntax when put into PlantUML

Whilst this example is perhaps simplistic, having a tool thats able to document your architecture is great to make sure everyone is on the same page when building out your project, and is helpful to have around for historical context in how the system structured (perhaps documented in something like an ADR or RFC). Having this information in a open-sourced standardized text form, rather than being stored in some proprietary file format, is also very appealing (albeit, not entirely without flaws).

It also democratizes UML diagrams, in the sense it makes them more accessible by having the markdown readable by screen readers.

A deep-dive into PlantUML’s syntax can be found here.

SwiftPlantUML

SwiftPlantUML aims to take PlantUML and make it more convenient to Swift developers.

By using either the command line tool or the Xcode extension, you’re able produce diagrams from preexisting code.

Installing SwiftPlantUML

Installing SwiftPlantUML is straight forward via Homebrew:

brew install swiftplantuml

Command Line Usage

Borrowing from the Book example above, you might have something that looks like this in your codebase:

struct Book {
    let isbn: String
    let title: String
    let author: Author
    let publisher: Publisher
    let numberOfPages: Int
    let releaseDate: Date
    let coverImage: String
}

struct Publisher {
    let id: String
    let name: String
}

struct Author {
    let id: String
    let name: String
}

struct Category {
    let description: String
}

And once SwiftPlantUML is installed, generating a diagram for the above becomes as simple as running this command in the directory where the files are stored:

swiftplantuml

(Note: By default, directories will be searched recursively)

This command then links to PlantText where the diagram is passed as encoded data in the URL. Here is a direct link to the above:

https://www.planttext.com/?text=bP4z3i8m38NtdCBY03q00oe_IoSgSOAqDMr4crIEWuJuEJinq9OE34onFkSzlpYfPqqSkbOfpnHAXiN6kTC2hg007iON5fPmO3As5i26MvmH7RXn5D7wLGZgGz4Qtw3GVAYbOKDN8EsFkQxHnsPcMJ1XYzhZJhDOoo6qT6Uah8jNntcWxbFEqNaCMys2MTtzKBwJ_YtRnc2reyiWhD2NP7espiu5ia58ajlgw_KJ--nf0eElKYdQAlx54m00

Thats pretty cool as it means PlantText doesn’t need to save any images on its server, it just needs to be able to decode the URL.

Running PlantUML locally for larger diagrams

By default, SwiftPlantUML uses PlantText as the renderer for its output, but this has some disadvantages:

  • Privacy
    • You could end up passing large chunks of information about your system to a third party. Perhaps thats fine for small projects, but possibly a concern for bigger companies.
  • Large Diagrams
    • Online renderers often limit the size of the images they’re able to produce. With PlantText, that limit is 4096x4096 pixels. You may find that if you have a large diagram, then PlantText may render an incomplete version of it.

To mitigate this you can run PlantUML locally.

To do this, you can download the latest version of PlantUML here and place it along side the code you want to build a diagram of.

Run the below command, which outputs your diagram in PlantUML syntax to sources.txt in the same directory, and removes the default PlantUML image size restrictions with -DPLANTUML_LIMIT_SIZE=8192:

swiftplantuml ./ --output consoleOnly > sources.txt | java -DPLANTUML_LIMIT_SIZE=8192 -jar plantuml.jar $1

And you’ll be presented with your image in PlantUML, which should look a bit like the below:

A screenshot showing a module loaded up in PlantUML, with PlantUML displaying a UML diagram of the project.

A few notes

  • I’ve found dependencies are not always correctly marked on the diagrams produced by SwiftPlantUML, so a level of proof reading is required to check everything is in order.
  • When first trying this out, I received the error below:
    java.io.IOException: Cannot run program "/opt/local/bin/dot": error=2, No such file or directory

    To get past this error, you’ll want to install GraphViz, which is the software PlantUML uses to render the diagram. This can be installed with Homebrew using:

brew install graphviz
  • The Double Edged Sword: Apple Music and Dolby Atmos

    A month or so back I bought “Dark Side of The Moon” on Blu-Ray to finally listen to the Atmos remix and – not to mince words her – it was revelatory. Maybe the most…

  • ImageSequencer – Build a video from a collection of images in iOS/macOS/tvOS

    I’ve been working on Lapsey – an app to make beautiful timelapse’s with – and whilst I won’t be open-sourcing the entire project, I am trying to open-source various components in the app that feel…

  • Get all available cameras in iOS using AVCaptureDevice.DiscoverySession

    I’m working on an iOS project that required finding all of the users available cameras on their device. This used to be simple enough prior to iOS 10, as you could just call: This would…

  • Examples of Use Cases in Swift

    In the last post we went over what use cases are in software development and how they can be used in iOS development. We also went over their origin as a requirements gathering technique for…

  • Use Cases in iOS Development

    Use cases have historically been a somewhat confusing topic to venture into for me personally, and I’m now of the believe that is because they typically have a couple of definitions, depending on who you’re…

  • UML Diagrams with PlantUML and SwiftPlantUML

    PlantUML is an open-source tool used to produce an assortment of diagrams using text. With other diagramming tools, the paradigm is typically a GUI and some dragging and dropping of various objects to build up…

  • Camera for iOS – A Swift Package

    Currently preparing a large post going over Clean Architecture in iOS and how that relates to modularization, but whilst that is in the making, I figured I’d post about my newly released Camera framework, and…

  • Feature Modularization in iOS

    So you’ve decided a loosely coupled, highly cohesive, modular architecture with well defined boundaries, is the approach you want to take with your project. Now its time to go over how to deal with separating…

  • Module Boundaries in iOS

    We’ve talked about what modularization is, and what its advantages are when used in a decoupled, cohesive way. It feels only reasonable that we should dig into the meat of what a modular architecture could…

  • Advantages to modularization in iOS

    We’ve already talked about what modularization is, and why a team might want to architect their codebase in such a way. But what are the real life advantages to having multiple units of code to…