Coffee-Driven Development

Brewing Thoughts for Better Code and Stronger Teams
en nl

Diagrammen maken met Mermaid

21 februari 2022 Softwaredesign

Steeds weer kom ik Mermaid tegen als het gaat om het maken van diagrammen. Persoonlijk werk ik graag met (Plant)uml maar meestal moet ik diagrammen dan exporteren naar een afbeelding voordat ik het in de documentatie kan gebruiken.

Microsoft DevOps heeft ondertussen ondersteuning voor Mermaid, Github heeft nu ondersteuning voor Mermaid en aangezien dat twee platformen zijn die ik veelvuldig gebruik lijkt het me tijd om me eens te gaan verdiepen in Mermaid.

Wat is Mermaid

Mermaid is een tool om diagrammen te maken en te visualiseren door middel van het gebruik van code, gebaseerd op Javascript.

Een simpel voorbeeld van een Mermaid diagram in code:

graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

Ziet er zo uit als afbeelding:

A

B

C

D

Voorbeelden

Op de website van Mermaid staan veel voorbeelden maar niet veel complexe voorbeelden. Ik ga proberen een paar mooie voorbeelden te maken die laten zien wat edMermaid]1 allemaal kan.

Flowchart

Het is mogelijk om verschillende vormen te gebruiken, zo kun je ook designs van je architectuur maken:

Ordering pizzas

Pizza order

Customer

App

GraphQL_API

Events

Order Microservice

Order Data

Restaurant Microservice

Restaurant Data

Delivery Microservice

Delivery Data

graph TD;
    Customer(("Customer"))--Ordering pizzas-->App;
    App--Pizza order-->GraphQL_API;
    GraphQL_API-->Events(["Events"]);
    Events-->OrderMicroservice["Order Microservice"]
    OrderMicroservice-->OrderDatabase[("Order Data")]
    Events-->RestaurantMicroservice["Restaurant Microservice"]
    RestaurantMicroservice-->RestaurantDatabase[("Restaurant Data")]
    Events-->DeliveryMicroservice["Delivery Microservice"]
    DeliveryMicroservice<-->DeliveryDatabase[("Delivery Data")]

Bovenstaande is wel een beetje misbruik maken van een flowchart, onderstaande is iets meer waar het echt voor bedoeld is:

nee

Ja

nee

Nee

Ja

Begin

Plan onderhoudsbeurt in

Succesvol?

Internal Server Error

Opslaan in wachtrij

einde

verwerk reservering

Too Many Requests

Circuit vaker dan 3x verbroken?

Verbreek het circuit

Wacht 30 seconden, retry

De mermaid code:

flowchart TD
    A(Begin)= =>B[Plan onderhoudsbeurt in] ==> C{Succesvol?}
    C- ->|nee|D[Internal Server Error]
    D-->E[Opslaan in wachtrij]
    E-->F(einde)
    C===>|Ja|G[verwerk reservering]
    G==>F(einde)
    C-->|nee|H[Too Many Requests] --> K{Circuit vaker dan 3x verbroken?}
    K-->|Nee|I[Verbreek het circuit]
    K-->|Ja|E[Opslaan in wachtrij]
    I - -> J[Wacht 30 seconden, retry]
    J-->B

State diagram

Ongeveer hetzelfde diagram als hierboven maar nu met het `state diagram`:

ErrorHandling

Fouten

InternalServerError

Succes

broken < 3 times

broken >= 3 times

TooManyRequests

Plan_Onderhoud_In

Opslaan_In_Wachtrij

VerwerkReservering

Retry_Request

BreakCircuit

Wait30Seconds


stateDiagram-v2
    state request_state <<choice>>
    state error_state <<choice>>
    [*] --> Plan_Onderhoud_In
    Plan_Onderhoud_In --> request_state
    request_state --> error_state: Fouten
    error_state --> Opslaan_In_Wachtrij: InternalServerError
    Opslaan_In_Wachtrij --> [*]
    error_state --> ErrorHandling: TooManyRequests
    request_state --> VerwerkReservering: Succes
    VerwerkReservering --> [*]

    state ErrorHandling {
	state retry_state <<choice>>
	[*] --> Retry_Request
	Retry_Request --> retry_state
	retry_state --> BreakCircuit: broken < 3 times
	retry_state --> Opslaan_In_Wachtrij: broken >= 3 times
	BreakCircuit --> Wait30Seconds
	Wait30Seconds --> Retry_Request
    }

Sequence diagram

Hieronder staat een diagram van een mogelijke applicatie. Er is een menu aan toegevoegd, als je met je muis over de actor `Custom Application` gaat zie je twee menu items verschijnen.

Azure Blob StorageAzure Api ManagementAzure AD B2CCustom ApplicationAzure Blob StorageAzure Api ManagementAzure AD B2CCustom Applicationauthenticate1token2request new SAS token3newly generated SAS token with expiration time4newly generated SAS token with expiration time5upload new file with SAS token6WikiSource
sequenceDiagram
    autonumber
    participant Custom Application
    participant Azure AD B2C
    participant Azure Api Management
    participant Azure Blob Storage
    link Custom Application: Wiki @https://google.com/search?q=mermaid+menu
    link Custom Application: Source @https://google.com/search?q=mermaid+menu
    Custom Application->>Azure AD B2C: authenticate
    Azure AD B2C->>Custom Application: token
    Azure AD B2C->>Azure Api Management: request new SAS token
    Azure Api Management->>Azure AD B2C: newly generated SAS token with expiration time
    Azure Api Management->>Custom Application: newly generated SAS token with expiration time
    Custom Application->>Azure Blob Storage: upload new file with SAS token

C4 Models

Helaas is het nog niet mogelijk om C4 te gebruiken zoals wel mogelijk is met C4-PlantUML. Nu grotere platformen Mermaid omarmen hoop ik dat hier snel ondersteuning voor komt zodat het visualiseren van een architectuur ook met Mermaid en C4 mogelijk wordt.

Het is overigens niet onmogelijk om dergelijke diagrammen te tekenen, er is alleen geen echte C4 ondersteuning voor. Een voorbeeld van het internet:

Customer Information (System)

Uses (https)

Updates customer informationusing
[async, JSON/HTTPS]

Sends events to
[WebSocket]

Stores data in
[jdbc]

Sends customer update
events to

Sends customer update
events to

Sends customer update
events to

Stores data in

Stores events in

Customer

Customer Application
(JavaScript/Angular)

Allow customers to manage their profile

Customer Service
(Java, Spring Boot)

The point of access for customer information

Customer Database
(Oracle, 12c)

Stores customer information

MessageBus

Reporting Service
[Ruby]

Creates normalized data for
reporting purposes

Audit Service
[C#,.Net]

Provides organization wide
auditing facilities

Reporting Database
[MySql]

Stores a normalized version
of all business data for
ad hoc reporting purposes

Audit Store
[Event store]

Stores information about
events that have happened

test

graph TB
    Customer--"Uses (https)"-->CustomerApp("Customer Application")
    subgraph "Customer Information (System)"
    CustomerApp["Customer Application<br/>(JavaScript/Angular)<br/><br/>Allow customers to manage their profile"]--"Updates customer informationusing<br/>[async, JSON/HTTPS]"-->CustomerService["Customer Service<br/>(Java, Spring Boot)<br/><br/>The point of access for customer information"]
    CustomerService--"Sends events to<br/>[WebSocket]"-->CustomerApp
    CustomerService--"Stores data in<br/>[jdbc]"-->CustomerDatabase("Customer Database<br/>(Oracle, 12c)<br/><br/>Stores customer information")
    CustomerService--"Sends customer update<br/>events to"-->MessageBus
    MessageBus--"Sends customer update<br/>events to"-->ReportingService
    MessageBus--"Sends customer update<br/>events to"-->AuditService["Audit Service<br/>[C#,.Net]<br/><br/>Provides organization wide<br/>auditing facilities"]
    ReportingService["Reporting Service<br/>[Ruby]<br/><br/>Creates normalized data for<br/>reporting purposes"]--"Stores data in"-->ReportingDatabase("Reporting Database<br/>[MySql]<br/><br/>Stores a normalized version<br/>of all business data for<br/>ad hoc reporting purposes")
    AuditService--"Stores events in"-->AuditStore["Audit Store<br/>[Event store]<br/><br/>Stores information about<br/>events that have happened"]
    end

Styling

Mermaid maakt gebruik van verschillende stijlen. In mijn blog gebruik ik de `default` stijl maar er zijn dus andere mogelijkheden. Daarnaast is het ook nog mogelijk om, met behulp van stylesheets, zelf aanpassingen te doen. Een voorbeeld van een aanpassing:

Start

Stop

flowchart LR
    id1(Start)-->id2(Stop)
    style id1 fill:#f9f,stroke:#333,stroke-width:4px
    style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5

Configuration

Mermaid is te configureren in javascript:

mermaid.initialize({
    startOnLoad:true,
    theme:"default",
    flowchart: {
	    curve: "linear"
    }
});

Je kunt deze configuratie ook per diagram doen of een globale configuratie overschrijven. In onderstaande voorbeeld gebruik ik geen rechte maar ronde lijnen voor de en het donkere thema flowchart:

a

b

c

d

%%{init: {"theme": "dark", "flowchart": { "curve": "basis" }}}%%
flowchart LR
   a --> b & c--> d

Zelf uitproberen

Ik moet zelf nog erg wennen aan de syntax en de mogelijkheden van Mermaid. Ik ga er de komende tijd mee aan de slag en waarschijnlijk word ik er dan vanzelf wel beter in. Wil je er zelf ook eens mee spelen? Je kunt makkelijk aan de slag met een online editor zodat je niets hoeft te installeren.

Deel je creaties als je die hebt, misschien kan ik deze post dan uitbreiden met wat meer voorbeelden.

Bronnen