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
namespaceblocks. Top-levelorescarries no note; every other namespace adds a note sourced from<namespace>.hppif 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/tablenamemembers 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 betweentogetherblocks. - Layout engine — try
!pragma layout smetanaafter@startumlif 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
- compass-doc-add-class-diagram skill — drives the authoring.
- How do I generate PlantUML diagrams? — runs the build.
- PlantUML ER diagram conventions — sibling, for SQL schema.
- System Model — the system-level diagram lives here.