PlantUML class diagram conventions

Table of Contents

ORE Studio's class diagrams follow consistent rules so that any two components' diagrams look comparable. This doc captures how a diagram should look. The compass-doc-add-class-diagram skill drives the authoring; How do I generate PlantUML diagrams? runs the build. Return to Knowledge.

1. File locations

Diagram Path
Component projects/<component>/modeling/<component>.puml
System (top) projects/modeling/ores.puml

Create the modeling folder with mkdir -p if missing; each modeling dir also carries a CMakeLists.txt that adds the diagram target.

2. Skeleton

' GPL header (copy from any existing .puml)
@startuml
set namespaceSeparator ::

' <<< BODY GOES HERE >>>

' Local Variables:
' compile-command: "java -Djava.awt.headless=true -DPLANTUML_SECURITY_PROFILE=UNSECURE -DPLANTUML_LIMIT_SIZE=65535 -jar /usr/share/plantuml/plantuml.jar <FILE>.puml"
' End:
@enduml

Bump the copyright year as needed.

3. Namespaces

  • Nest namespace blocks. Top-level ores carries no note; every other namespace adds a note sourced from <namespace>.hpp if one exists.
  • No relationship arrows touch a namespace block.
Namespace name Colour Stereotype
database #C6F0D8 <<orm>>
any other #F2F2F2 (none)

4. Class & struct styling

Apply the first matching rule:

Condition Colour Stereotype Kind
Ends with _entity / _mapper / _repository and in repository/ #99CB99 <<orm>> class/struct
Ends with _option and in config/ #FFC072 <<config>> struct
Ends with _request or _response and in messaging/ #E1F5FF <<message>> struct
Ends with _exception #D6B19F <<exception>> class
Default struct #F7E5FF (none) struct
Default class #ECECEC (none) class

Stereotype goes after the class name: class foo <<orm>> #99CB99.

5. Members and notes

  • Include methods and fields with visibility markers (+ / - / #). Prefix fields with {field} (PlantUML disambiguation).
  • Skip: operator<<, default values, logging members, trivial getters/setters.
  • Always attach a note top of <name> — the first line is a one sentence "what is this for", followed by one line per field (type name // comment).
  • ORM structs with schema / tablename members omit those members from the class body and add them to the note instead:

    ORM Settings:
    - Schema:    my_schema
    - Tablename: my_table
    

6. Relationships

  • Use fully qualified names (ores::component::class).
  • Ignore external-component types entirely.
  • Always show inheritance.
  • Arrow vocabulary:

    Relation Arrow Notes
    Inheritance =-up-\ >= =derived -up-\ > base= (forces parent on top)
    Composition *-- Strong ownership.
    Aggregation o-- Weak ownership / reference.
    Association -- Plain "knows about".
    Dependency ..> Label : uses, : creates, : generates.
  • Use directional variants (-up-, -down-, -left-, -right-) to control layout when the default flow is ugly.

6.1. Note targets and fully-qualified names

A note ... of line takes a short name or a double-quoted fully-qualified one. An unquoted fully-qualified name is a trap: PlantUML reads the first segment as the target and draws an empty extra class named after it. The diagram still renders and the note still attaches, so the defect is invisible unless someone reads the picture.

note right of "ores::ore::xml::roundtrip_summary"  ' correct
note right of roundtrip_summary                    ' correct, when unambiguous
note right of ores::ore::xml::roundtrip_summary    ' adds a phantom class "ores"

Arrow lines are the opposite case: those take the unquoted fully-qualified name.

7. Implementation-file dependencies

Scan .cpp files for architecturally significant patterns:

  • Static method calls on component classes.
  • Instantiation of non-member helpers.
  • Message-handler patterns (deserialize(), response construction).

Only model these as A ..> B : uses if they are load-bearing for the design; otherwise leave them out.

8. Enumerations

enum example #F2DAFD {
    VALUE_1
    VALUE_2
}

9. Generators

Functions in generators/ whose name starts with generate_ use the generator stereotype:

class generate_foo <<generator>> #D89EF1 {}
note top of generate_foo
Generates a foo.
end note
generate_foo --> ores::foo::bar : generates

10. Test suites

Test classes give the diagram visibility into test coverage. They live in a tests namespace at the component level. One class per test file (foo_tests.cpp → foo_tests); methods list each TEST_CASE as a public void method.

Styling:

Property Value
Stereotype <<test suite>>
Colour #C5E1A5 (light green)
Namespace color #F2F2F2 (same as other namespaces)

Each test class gets a note describing what it covers, and a ..> ores::component::class : tests dependency arrow to the classes under test. No relationship arrows to external types.

11. Layout

PlantUML defaults can spread a diagram horizontally; aim for an aspect ratio between 2:1 and 3:1. Tools:

  • together blocks — group related classes (request/response pairs, entity/mapper/repository chains, related test suites).
  • Hidden relationships (-[hidden]down-) — stack vertically within or between together blocks.
  • Layout engine — try !pragma layout smetana after @startuml if the default GraphViz engine misplaces classes outside their namespaces.

Place groupings and hidden relationships at the top of each namespace, before the class definitions.

12. System-level diagram

The system-level diagram (projects/modeling/ores.puml) uses PlantUML's component syntax (not class syntax) with packages per architectural layer:

Layer Colour
Foundation #LIGHTBLUE
Infrastructure #LIGHTGREEN
Domain #LIGHTYELLOW
Application #LIGHTCORAL

For each component, place its note right of <component> inside the package block, immediately after the component definition. Source the description from the namespace @brief in projects/<component>/include/<component>/<component>.hpp.

Component dependencies come from target_link_libraries in each projects/<component>/src/CMakeLists.txt; ignore external libraries.

13. Evaluation checklist

Check How
No class-to-namespace arrows Search for namespace in arrow lines.
Correct stereotype order class name <<stereo>> #COLOR.
Consistent colours Match the styling table above.
No phantom note target Search note .* of for an unquoted :: name.
Syntax valid cmake --build --target generate_<component>_diagram.

14. See also

Emacs 29.3 (Org mode 9.6.15)