# Class diagrams

> Page: https://docs.plotwork.dev/class-diagrams. Index of every page: https://docs.plotwork.dev/llms.txt

Draw the classes of an object model, the members each one holds, and the relations between them, with the marks UML gives each relation: a hollow triangle for inheritance, a diamond for composition, an open arrow for an association. It is for developers who document a domain model, an interface and its implementations, or a design pattern, and for the agents that write those diagrams for them.

## TL;DR

| Question | Answer |
|---|---|
| What is it for? | An object model: classes with attributes and methods, and how they inherit, implement, own, and use one another. Packages group classes, and notes hang off a class. |
| What is the header? | `class "Title" desc="Summary" direction=down`. The title names the picture, and `desc` is its alt text. |
| What does a class look like? | `class Order "Order" type=class stereotype="entity" tone=blue {`, then one quoted member for each line, then `}`. |
| What do the relations look like? | `Dog extends Animal`, `Duck implements Flyer`, `Car owns Engine`, `Library has Book`, and the arrows `->`, `<->`, `-->`, and `--`. |
| Which Mermaid type converts? | `classDiagram` and `classDiagram-v2`. Members are turned round to name first, and styling is dropped. See [From Mermaid](#from-mermaid). |
| What are the limits? | 200 classes, 400 relations, 40 packages, and 60 members in one class. Past a limit the diagram is refused with `E140`. |
| How is it drawn? | Parents and wholes sit above their children, lines bend at right angles, and a box grows to fit its text. The theme chooses every color, in light and dark. |

## Ask your agent

```text
Use Plotwork to draw the classes of a notification service. A Notifier queues Messages and delivers each one through a Channel. Channel is an interface with EmailChannel and SmsChannel implementing it. A Message has a Priority enum, and a Template class is abstract. Group the channels in a package, and add a note that a message is kept until every channel has confirmed delivery.
```

```text
Use Plotwork to draw the Observer pattern as a class diagram. A Subject interface notifies Observer interfaces. WeatherStation implements Subject, and Display, Logger, and Alarm implement Observer. Show that the subject has many observers.
```

## Example

**Diagram source**

```diagram
class "Notification service" desc="A notifier queues messages and delivers each one through a channel. Channels are interchangeable, so a new one needs no change to the notifier."

class Notifier stereotype="service" {
  "-queue: Queue<Message>"
  "+send(m: Message): void"
  "+retry(): int"
}

class Message {
  "+id: uuid"
  "+body: String"
  "+priority: Priority"
}

class Priority type=enum {
  "LOW"
  "NORMAL"
  "URGENT"
}

class Template "Template<T>" type=abstract {
  "+render(data: T): String" abstract
  "+named(n: String): Template" static
}

package channels "Channels" {
  class Channel type=interface {
    "+deliver(m: Message): Ack"
  }
  class Email "EmailChannel" {
    "-host: String"
    "+deliver(m: Message): Ack"
  }
  class Sms "SmsChannel" {
    "-gateway: String"
    "+deliver(m: Message): Ack"
  }
}

Notifier "1" owns "*" Message : "queues"
Notifier "1" has "1..*" Channel : "delivers through"
Notifier --> Template : "renders with"
Message --> Priority
Email implements Channel
Sms implements Channel

note on Message : "Kept until every channel has confirmed delivery."
```

*Picture: Notification service: 7 classes, 1 package, 6 relations. A notifier queues messages and delivers each one through a channel. Channels are interchangeable, so a new one needs no change to the notifier.*

**Text description**

**Classes:**

- Notifier: class, service
  - private queue: Queue<Message>
  - public send(m: Message): void
  - public retry(): int
- Message: class
  - public id: uuid
  - public body: String
  - public priority: Priority
- Priority: enum
  - LOW
  - NORMAL
  - URGENT
- Template<T>: abstract class
  - public render(data: T): String (abstract)
  - public named(n: String): Template (static)
- Package Channels:
  - Channel: interface
    - public deliver(m: Message): Ack
  - EmailChannel: class
    - private host: String
    - public deliver(m: Message): Ack
  - SmsChannel: class
    - private gateway: String
    - public deliver(m: Message): Ack

**Relations:**

- Notifier (1) is composed of Message (*): queues
- Notifier (1) aggregates Channel (1..*): delivers through
- Notifier depends on Template<T>: renders with
- Message depends on Priority
- EmailChannel implements Channel
- SmsChannel implements Channel

**Notes:**

- Note on Message: Kept until every channel has confirmed delivery.

## The language

A statement is words, quoted strings, `key=value` options, and the arrows. A `#` outside quotes starts a comment. Ids are letters, digits, `_`, and a `-` inside the id. A name with other characters, or with type parameters, goes in the label: `class Repo "Repository<T>"`.

### Statements

| Statement | Meaning |
|---|---|
| `class "Title" desc="..." direction=down` | The header. `direction` is `down` (the default, parents above children), `right`, `up`, or `left`. `auto` is read as `down`. |
| `desc "text"` | The description for readers who cannot see the picture. The same as `desc=` on the header. |
| `class <id> "Label" type=<type> stereotype="<word>" tone=<tone> {` | Declares a class. The label, `type`, `stereotype`, and `tone` are optional. Without the `{` the class has no members. Members are the lines that follow, and a `}` on its own line closes the class. |
| `"+name: type" static abstract` | A member of the open class: the whole text in double quotes, then its flags. |
| `package <id> "Label" tone=<tone> {` | A frame with a corner tab around the classes and packages written inside it. A `}` on its own line closes it. Packages nest three deep. |
| `<from> "1" <relation> "0..*" <to> : "label"` | A relation between two classes. A cardinality at either end and the label are optional. It may stand anywhere, before or after the classes it names. |
| `note on <id> : "text"` | A note card joined to a class by a dotted line. |
| `note : "text"` | A note that stands alone. |

A class and a package share one set of ids, and an id used twice is error `E130`. A relation that names an unknown class is `E131`.

### Class types

| `type=` | Drawn as | Default tone | Use for |
|---|---|---|---|
| `class` | Plain name | blue | A concrete class. This is the default. |
| `abstract` | Name in italics under «abstract» | violet | A class that is only extended. |
| `interface` | Name under «interface» | aqua | A contract of methods that other classes implement. |
| `enum` | Name under «enumeration» | amber | A fixed set of named values. Each member line is one value. |

`stereotype="service"` adds a word in guillemets, such as «service». With a type that has its own word, the two share the line: «interface, service». `tone=` takes any tone of the theme and changes the header band. A color value is never accepted.

### Members

A member is one quoted string. Its first character may be a mark that says who sees it, drawn in the gutter of the box.

| Mark | Visibility |
|---|---|
| `+` | public |
| `-` | private |
| `#` | protected |
| `~` | package |
| none | not said |

A member with a parenthesis is a method, and every other member is an attribute. Attributes are drawn first and methods below a divider, whatever order you write them in. The colon after the name, or after the parameters of a method, starts the type. A colon inside brackets belongs to the name, so `"+pair: Map<a:b, int>"` has the type `Map<a:b, int>`. A flag follows the string.

| Flag | Drawn as |
|---|---|
| `static` | Underlined |
| `abstract` | In italics |

```plotwork
class Account {
  "-balance: Money"
  "#limit: Money"
  "+deposit(amount: Money): void"
  "+open(owner: Person): Account" static
  "+close(): void" abstract
}
```

### Relations

Write an inheritance or a realization from the child to the parent, and a composition or an aggregation from the whole to the part. The class at the upper end is the one the layout puts first, so with `direction=down` parents and wholes are above.

| Written | Kind | Line | Mark |
|---|---|---|---|
| `Dog extends Animal` | inheritance | solid | hollow triangle at `Animal` |
| `Duck implements Flyer` | realization | dashed | hollow triangle at `Flyer` |
| `Car owns Engine` | composition | solid | filled diamond at `Car` |
| `Library has Book` | aggregation | solid | hollow diamond at `Library` |
| `Order -> Customer` | association | solid | open arrow at `Customer` |
| `Order <-> Customer` | two-way association | solid | open arrow at both ends |
| `Order --> Mailer` | dependency | dashed | open arrow at `Mailer` |
| `Order -- Invoice` | link | solid | none |

A cardinality is a quoted string of at most 12 characters, such as `"1"`, `"0..1"`, `"*"`, or `"1..*"`. It sits beside the line at its end. The label is a pill on the line. The arrows `..>` and `<-->` belong to flow diagrams, so a class diagram refuses them with `E344` and the hint says what to write.

```plotwork
Customer "1" -> "0..*" Order : "places"
Order "1" owns "1..*" Line : "contains"
Employee "0..1" -> "*" Employee : "manages"
```

A relation from a class to itself is a loop on the side of the box that the layers do not run through. Several classes that extend or implement the same parent, and name no cardinality at the parent, leave it in one trunk.

Every relation, each with its mark:

**Diagram source**

```diagram
class "Every relation" desc="The eight relations, each with the mark it is drawn with."

class Animal type=abstract {
  "+name: String"
}
class Dog
class Pet type=interface
class Poodle
class Engine
class Car {
  "+start(): void"
}
class Wheel
class Tyre
class Mapper
class Route
class Plan
class Driver

Dog extends Animal
Poodle implements Pet
Car "1" owns "1" Engine : "has"
Car "1" has "4" Wheel
Driver "1" -> "0..*" Car : "drives"
Wheel <-> Tyre
Mapper --> Route : "reads"
Route -- Plan
```

*Picture: Every relation: 12 classes, 8 relations. The eight relations, each with the mark it is drawn with.*

**Text description**

**Classes:**

- Animal: abstract class
  - public name: String
- Dog: class
- Pet: interface
- Poodle: class
- Engine: class
- Car: class
  - public start(): void
- Wheel: class
- Tyre: class
- Mapper: class
- Route: class
- Plan: class
- Driver: class

**Relations:**

- Dog extends Animal
- Poodle implements Pet
- Car (1) is composed of Engine (1): has
- Car (1) aggregates Wheel (4)
- Driver (1) is associated with Car (0..*): drives
- Wheel and Tyre
- Mapper depends on Route: reads
- Route is linked to Plan

### Notes

A note is a card. `note on Order : "A placed order cannot be edited."` joins it to a class with a dotted line, and `note : "Domain model, version 2."` stands alone.

## Limits and warnings

Warnings never stop rendering. An error stops it and the diagram is not drawn.

| Limit | Value | What happens past it |
|---|---|---|
| Classes in one diagram | 200 | Error `E140`, before any layout, with a hint to split along a package. |
| Relations | 400 | `E140`. |
| Packages | 40 | `E140`. Packages nested deeper than 3 give `E345`. |
| Members of one class | 60 | `E140`. |
| Members in all | 1,200 | `E140`. |
| Layers that relations skip over | 600 | `E140`. Each skipped layer costs far more than a box, so draw a long chain as two diagrams. |
| A cardinality | 12 characters | `E343`. |
| A box | 480px wide | The text is cut with an ellipsis and the diagram gets `W203`. |

| Code | When it fires | Fix |
|---|---|---|
| `E340` | A `type=` that is not `class`, `abstract`, `interface`, or `enum`. | Use the nearest type the message names. |
| `E341` | A member that is not a quoted string, or has no name once the mark is taken off. | Write `"+name: type"`. |
| `E342` | A relation word that is not `extends`, `implements`, `owns`, or `has`. | Use the nearest word the message names. |
| `E343` | A cardinality that is empty or longer than 12 characters. | Shorten it, or move the words into the label. |
| `E344` | An arrow that means nothing in a class diagram, such as `..>` or `<-->`. | Use `-->` for a dependency or `<->` for a two-way association. |
| `E345` | Packages nested deeper than three. | Flatten the packages. |
| `E140` | A limit above is passed. | Split the diagram along a package. |
| `E130`, `E131` | An id used twice, or a relation to a class that is not declared. | Rename the duplicate, or declare the class. |
| `E135`, `E136` | An unknown member flag, or an empty `stereotype=`. | Use `static` or `abstract`, or give the stereotype a word. |
| `W200` | More than 12 classes, plus 2 for each package, up to 24. | Split the diagram by package or by domain. |
| `W201` | A class that no relation or note reaches. | Connect it or remove it. |
| `W202` | The diagram is wider than a Markdown column. | Use `direction=down`, shorten labels, or split it. |
| `W203` | Text was cut with an ellipsis in a box. | Shorten the text. |
| `W320` | A class with more than 12 members. | Keep the members that matter, or split the class. |
| `W321` | A class that is its own ancestor, at the relation that closes the loop. | Remove or turn round the relation. |
| `W322` | A class that implements another class declared `type=class`. | Declare the target `type=interface`, or use `extends`. |
| `W323` | The same relation of the same kind written twice. | Delete one. |

## From Mermaid

`classDiagram` and `classDiagram-v2` convert to a class diagram. Convert one with `convert_mermaid`, or a whole Markdown file with `sync_markdown` and `convertMermaid` set to true. A Mermaid front matter `title:` becomes the title, and `accTitle` and `accDescr` become the title and the description.

```mermaid-source
---
title: Pets
---
classDiagram
  class Animal {
    <<abstract>>
    +String name
    +makeSound() void
  }
  class Dog
  Animal <|-- Dog
  Owner "1" --> "*" Animal : owns
  note for Dog "Good boy."
```

That becomes `Dog extends Animal`, `Owner "1" -> "*" Animal : "owns"`, and `note on Dog : "Good boy."`. `Animal` becomes `type=abstract`, and the two members are turned round to `+name: String` and `+makeSound(): void`, each reported with `M240`.

| Mermaid | Plotwork | Report |
|---|---|---|
| `class A`, `class A { ... }`, a name used only in a relation | A class, with the members as written | None |
| `class A~T~`, `class A["Label"]`, `` class `Odd name` `` | The label `A<T>`, the bracketed label, or a valid id with the name as the label | `M206` when an id is renamed |
| `+String name`, `+getName() String` | `+name: String`, `+getName(): String` | `M240` |
| `+name: String` | Kept, with the spaces tidied | None |
| A trailing `$` or `*` on a member | `static`, `abstract` | None |
| `<<interface>>`, `<<abstract>>`, `<<enumeration>>` | `type=interface`, `type=abstract`, `type=enum` | None |
| Any other `<<Service>>` | `stereotype="Service"` | None |
| A second annotation on one class | Dropped | `M242` |
| `A <\|-- B`, `A --\|> B` | `B extends A`, `A extends B` | None |
| `A ..\|> B`, `A <\|.. B` | `implements`, written from the child | None |
| `*--`, `--*`, `o--`, `--o` | `owns` and `has`, from the whole | None |
| `-->`, `..>`, `<-->`, `--` | `->`, `-->`, `<->`, `--` | None |
| `..` with no marker, a lollipop `()--`, a marker at both ends | The nearest of the eight relations | `M241` |
| A cardinality and a `: text` label | The same, on the end it was on | A cardinality over 12 characters moves into the label with `M205` |
| `namespace N { ... }` | `package N { ... }` | None |
| `note "text"`, `note for A "text"` | `note : "text"`, `note on A : "text"` | `M205` for a line break |
| `direction TB`, `BT`, `LR`, `RL` | `down`, `up`, `right`, `left` | None |
| `classDef`, `cssClass`, `style`, `:::name`, `%%{init}%%` | Dropped | `M200` |
| `link`, `callback`, `click` | Dropped | `M201` |
| A class or namespace that is never closed | Closed where the next statement starts | `M217` |
| A line that cannot be read | The conversion stops | `M110`, or `M218` when the conversion is lenient |

The [migration guide](https://docs.plotwork.dev/migrating-from-mermaid.md) lists every conversion code.

## See also

| Doc | Why |
|---|---|
| [Writing diagrams](https://docs.plotwork.dev/writing-diagrams.md) | The language for flow, sequence, and schema diagrams, and the options every kind shares |
| [Examples to copy](https://docs.plotwork.dev/examples.md) | Finished diagrams with the prompt that gets an agent to write each one |
| [Migrating from Mermaid](https://docs.plotwork.dev/migrating-from-mermaid.md) | What converts, what is dropped, and every `M` code |
| [Git graphs](https://docs.plotwork.dev/git-graphs.md) | Branches, commits, and merges |
| [Gantt charts](https://docs.plotwork.dev/gantt-charts.md) | A plan in days, with dependencies |
| [State diagrams](https://docs.plotwork.dev/state-diagrams.md) | States and the transitions between them |
| [Timelines](https://docs.plotwork.dev/timelines.md) | Events in time order |
| [User journeys](https://docs.plotwork.dev/user-journeys.md) | A person's steps, scored |
| [Mind maps](https://docs.plotwork.dev/mind-maps.md) | A topic and its branches |
| [Language reference](https://docs.plotwork.dev/reference/language.md) | Every word of the language |
| [Diagram kinds](https://docs.plotwork.dev/reference/language/kinds.md) | The ten kinds and what each draws |
