Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Most people use PrecessOn or Darw.io to draw UML diagrams, which are barely usable but not professional. Here is a tool for drawing UML: PlantUML

1. PlantUML

PlantUML was created in 2009 and is widely known but rarely used. Because it uses a special DSL for drawing, PlantUML’s diagrams are “written” rather than “drawn” compared to other tools.

Although there is a learning cost, more professional UML diagrams can be drawn, and the text format is easy to save. This article summarizes the basic usage of PlantUML to help you get started quickly.

Installation environment

PlantUML is a Java program, so you can run it with the JDK. Jar files can be downloaded directly from the official website for execution. Of course, it also provides plug-ins for IDEA and VSCode.

Note that PlantUML’s native rendering relies on Graphviz, and environment variables need to be installed and configured in advance. If you use VSCode, you can also use cloud rendering, just do the following:

You can then preview the UML while “writing” it in VSCode.

Next we’ll learn how to write beautiful UML, starting with Hello World just like any other language.

2. Hello World

//hello.pu
@startuml
Hello <|-- World
@enduml
Copy the code

PlantUML files usually have a.pu suffix,

The command line specifies the PU.

java -jar plantuml.jar hello.pu
Copy the code

PNG will be generated between @startuml and @enduml in the current directory

In addition to.pu, @startuml and @endUML can also recognize and generate PNGS in various source files, such as.c,.C ++,.htm,.java, etc., so we can write the UML that matches the source code into a comment:

/ * * *@startuml
 * class JavaSource {
 *   - String message
 * }
 * @enduml* /
public class JavaSource {}
Copy the code

Note that a set of @startuml/ @endUML corresponds to a PNG file, and if there are multiple groups in a file, the resulting PNG file name will be suffixed with an increment number. You can also specify a filename immediately after @startuml

@startuml foo
class Foo
@enduml

@startuml bar
class Bar
@enduml

@startuml baz
class Baz
@enduml
Copy the code

3. Basic grammar

annotation

What follows a single quote is a comment

@ startuml no - scale 'is this annotation Hello < | - World @ endumlCopy the code

Title

Title followed by title

@startuml
title Hello Title
Hello <|-- World
@enduml
Copy the code

Multi-line title

The input between title and end title can be newline

@startuml
title
Hello
Title
end title
Hello <|-- World
@enduml
Copy the code

Heading styles

PlantUML supports the use of Creole, a markup language similar to markdown, to enrich text styles.

Reference: en.wikipedia.org/wiki/Creole…

@startuml
title
* __Hello__
* **World**
end title
Hello <|-- World
@enduml
Copy the code

Figure note

Caption The caption is followed by a caption

Figure 1 @ startuml caption Hello < | - World @ endumlCopy the code

header/footer

@startuml
header Hello
Hello <|-- World
footer World
@enduml
Copy the code

Header footer allows you to append comments to both the header and the tail. By default, the header is right-aligned and the footer is centered.

alignment

@startuml
left header Hello
Hello <|-- World
right footer World
@enduml
Copy the code

Add left Center right before header footer to set alignment

Multi-line header/footer

Same as title, header… end header , footer … end footer

@startuml
header
Hello
Header
end header

Hello <|-- World

footer
World
Footer
end footer
@enduml
Copy the code

magnification

@startuml no-scale
Hello <|-- World
@enduml

@startuml scale-1.5
scale 1.5
Hello <|-- World
@enduml

@startuml scale-0.5
scale 0.5
Hello <|-- World
@enduml
Copy the code

Scale can set the magnitude for UML

4. The class diagram

Class

@startuml
class Hello
class World
@enduml
Copy the code

The class specified class

Interface

@startuml
interface Hello
interface World
@enduml
Copy the code

Interface Specifies the interface.

An abstract class

@startuml
abstract class Hello
@enduml
Copy the code

Abstract class specifies the abstract class

The enumeration

@startuml
enum HelloWorld {
    ONE
    TWO
    THREE
}
@enduml
Copy the code

Enum Specifies the enumeration, {… } defines enumeration values

Type of relationship

There are six relationships between types in UML:

  • Generalization.
  • Realization
  • Connection (Association)
  • Aggregation
  • Combination (Composition)
  • Rely on (Dependency)

Let me explain one by one:

generalization

A generalization relationship is an inheritance of a class, which in Java corresponds to the extends keyword.

@startuml
Child --|> Parent
Parent2 <|-- Child2
@enduml
Copy the code

< | — – | > specifies the inheritance relationship

implementation

Implements a relationship corresponding to the implements keyword

@startuml Plane .. |> Flyable Flyable <|.. Plane @endumlCopy the code

. | >, < |.. , dots represent dotted lines

Rely on

Dependencies represent usage relationships. In Java, dependent objects/classes occur in the form of method parameters, local variables, and static method calls. For example, when the cook looks at the recipe while cooking, the cook “uses” the recipe, and when the cook follows it, the relationship ends (temporarily).

@startuml Chef .. > Recipe @endumlCopy the code

associated

Association relationship: owning. Compared with dependence, which is temporary and unidirectional, correlation is long-term and equal (bidirectional), so correlation is stronger than dependence. For example, couples, teachers and students in real life. Long term and mutual. In addition, association can represent one-to-one, one-to-many, many-to-one, many-to-many, etc.

@startuml
Address <-- Husband
Husband <--> Wife
Husband2 -- Wife2
@enduml
Copy the code

Because it’s stronger than a dependency, it’s a solid line plus an arrow. The arrows can be omitted for bidirectional associations.

The latter two relations, “aggregation” and “combination”, both belong to relational relations and are used to indicate the relation between the whole and the parts of the relational relations. In Java, the whole and part relationship between a Class and its member variable Class type is the same.

The aggregation

The aggregation relation is weaker than the composition, the whole and the parts are separable. For example, the department and employees, there are many employees in the department, the employee leaves the department still exists, not affected. If the department dissolves, employees can go to other departments (the whole and part can be separated).

@startuml
Department o-- Employee
@enduml
Copy the code

O stands for hollow diamond

combination

In the combinatorial relationship, the whole and the part are inseparable, and the life cycle of the whole and the part is consistent, so the existence of the other side is meaningless. For example, the human body is composed of four limbs, limbs can not exist without the human body, the human body without limbs can not be complete

@startuml
Body "1"*"2" Arm
Body "1"*"2" Leg
@enduml
Copy the code

* represents a solid diamond

We also see a multitime representation of numbers, wrapped in double quotes, between the line segment and the Class. The same goes for many-to-many.

Finally, summarize the six relationships

inheritance implementation Rely on associated The aggregation combination
Relationship between meaning Function extension Function implementation use have Whole – Part (HAS-A) Whole – part (contains-a)
Relationship between characteristics Temporary, unidirectional Long-term, bidirectional (equality) The whole is separable from the parts The whole is inseparable from the parts, and the life cycle is the same
Java syntax extends implements Method parameters, local variables, static method calls Member variables Member variables Member variables
Relationship between strong and weak strong strong weak The strong The strong Very strong
Real case Father and son Planes/birds can fly Chefs use recipes Husband and wife, teacher and student Department – Staff Human body – Limbs
Graphical point to The arrow points to the parent class Arrow pointing to interface The arrow points to the user It points to the owner in both directions The arrow points to the part and the diamond points to the whole The arrow points to the part and the diamond points to the whole

The integrated use of

@startuml
interface One
interface Two
interface Three extends Two
interface Four
class Five implements One, Three
class Six extends Five implements Four {
    field: String
    method(): void
}
@enduml

Copy the code

Member variables, member methods

@startuml
class Hello {
    one: String
    three(param1: String, param2: int): boolean
    String two
    int four(List<String> param)
}
@enduml
Copy the code

The class definition is followed by braces to declare the members, and then the variables are declared in the order of their name: type, followed by type. Methods and members can be mixed up in order, resulting in a graph that automatically divides into two groups

Member visibility

UML uses the following notation to represent visibility

Character Visibility
- private
# protected
~ package private
+ public

But PlantUML takes the text correspondence a step further:

@startuml
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml
Copy the code

Of course, you can turn off this graphical fit and continue using literal symbols

@startuml
skinparam classAttributeIconSize 0
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml
Copy the code

Turn off the graphical symbol with Skinparam classAttributeIconSize 0

Abstract methods

@startuml
class Hello {
    {abstract} one: int
    {abstract} two(): int
}
@enduml
Copy the code

The member is abstracted by the {abstract} bit in front of it

A static method

@startuml
class Hello {
    {static} ONE: int
    {static} two(): int
}
@enduml
Copy the code

Add {static} to indicate static methods

The generic

@startuml
class Hello<H>
class World<W> 
@enduml
Copy the code

Class name followed by < generic >

Package diagram

@startuml
package one.two {
    class Hello
}

package three.four {
    World -- Hello
}
@enduml
Copy the code

package

{… } class UML diagrams can be written in

The order of declarations in the package diagram

@startuml
package three.four {
    World -- Hello
}

package one.two {
    class Hello
}
@enduml
Copy the code

The order of the package diagram is important. For example, the classes in one.two are dependent on three.

Remarks (Note)

@startuml
class Fizz
note left: fizz

class Buzz
note right: buzz

class Foo
note top: foo

class Bar
note bottom: bar
@enduml
Copy the code

Use note < top | | bottom left | right > : < note > add notes to a UML diagram, note the content can be a Creole syntax

Specify the target class

@startuml
Fizz -- Buzz
note left of Fizz: fizz
note right of Buzz: buzz
@enduml
Copy the code

Note < location > of < target >: < remarks > is used to generate remarks for the specified target Class

Remarks for class relationships

@startuml
Fizz -- Buzz
note on link: fizz-buzz
note left: buzz
@enduml
Copy the code

Note on link: < remarks > You can add remarks to the relationship of the class diagram

Add a name to the note

@startuml
note "Hello World" as n1
Hello -- n1
World .. n1

note "Fizz Buzz" as n2
@enduml
Copy the code

Note “< note >” as < name > is used to set a name for a note. Once you have a name, you can associate a note with multiple classes by name

Multi-line comment

@startuml class Hello note left Hello World end note Fizz -- Buzz note on link Fizz Buzz end note note left of Fizz fizz  buzz end note note as n1 Foo Bar end note @endumlCopy the code

End note is used to end multiple lines of remarks