Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for C4 Models #1276

Open
lwalker-kforce opened this issue Feb 24, 2020 · 31 comments
Open

Support for C4 Models #1276

lwalker-kforce opened this issue Feb 24, 2020 · 31 comments

Comments

@lwalker-kforce
Copy link

lwalker-kforce commented Feb 24, 2020

We adopted C4 Models and use Azure DevOps Wiki's for our documentation. Currently, we model in Vizio, etc. and paste a screen shot into our wiki docs or have tried to use PlantUML. Azure DevOps supports mermaid natively now so I would like to see if there is already an easy way to support C4 and/or Azure shapes using Flowchart(s) + CSS or if there is an opportunity to support them some other way.

I have used PlantUML and extensions for both C4 and Azure models in our wiki docs. Here are a few extensions to help explain the intent hopefully.

https://github.com/RicardoNiepel/C4-PlantUML
https://github.com/adrianvlupu/C4-PlantUML
https://github.com/RicardoNiepel/Azure-PlantUML
https://github.com/dcasati/Azure-PlantUML

Perhaps an enhancement similar to the font-awesome support?

@lwalker-kforce lwalker-kforce added Status: Triage Needs to be verified, categorized, etc Type: Enhancement New feature or request labels Feb 24, 2020
@jgreywolf
Copy link
Contributor

Just playing around a bit - I created this using current flowchart functionality. I get that this does not completely match the example (Message Bus and Microservices) but like I said, just playing around...

Repro in Mermaid Live Editor

@nicholasf
Copy link

Having C4 in Mermaid would be terrific.

@vasylnakvasiuk
Copy link

vasylnakvasiuk commented Jul 21, 2020

Just playing around a bit - I created this using current flowchart functionality. I get that this does not completely match the example (Message Bus and Microservices) but like I said, just playing around...

Repro in Mermaid Live Editor

Agree, but we need more figures (database, message bus, etc.)
Plus would be a killer feature, if somehow you add clickable transition from 1 graph to another. So I will be able to describe different levels of my project (classes diagram, component diagram, context diagram) and connect 1 box with (zoom in) 1 another graph. And obviously will be able to go back (zoom out).

@fossro
Copy link

fossro commented Feb 18, 2021

Just adding my vote here, support for C4 models in mermaid would be awesome!

@simonbrowndotje
Copy link

simonbrowndotje commented Mar 18, 2021

Since this issue is still open ... I appreciate this isn't native Mermaid support, but you can do a Mermaid export from the open source Structurizr DSL & CLI combo:

@haraldreingruber
Copy link

@simonbrowndotje That sounds like a really nice approach, thanks for sharing!

@marqh
Copy link

marqh commented Apr 23, 2021

native Mermaid support for C4 would be massively valuable.

Is there progress or intent in this domain?

@fossro
Copy link

fossro commented Jun 15, 2021

Just want to add my support to this idea. Having support for C4 in Mermaid would be super valuable!
What can we do to prioritize this feature?

@ecofone
Copy link

ecofone commented Jul 1, 2021

Will be really great to have C4 native support! any news?

@simonbrowndotje
Copy link

What can we do to prioritize this feature?

Perhaps it's worth discussing what you'd like to see in such a feature. "Supporting the C4 model" could range from some pre-defined styles and shapes through to adding new keywords to the Mermaid syntax (like you see with C4-PlantUML, for example). Each has a different level of effort required, and there are already solutions that provide similar functionality. You should also consider sponsoring the author if this feature has value to you. As I mentioned above, a Structurizr DSL to Mermaid exporter is already available too.

@uadev
Copy link

uadev commented Jan 27, 2022

Just playing around a bit - I created this using current flowchart functionality. I get that this does not completely match the example (Message Bus and Microservices) but like I said, just playing around...

Repro in Mermaid Live Editor

If we look at this live editor repro, we see that just adding C4 shapes would cover > 80% of all cases.

@jodosha
Copy link

jodosha commented Feb 14, 2022

Please make it happen. 🙏

@nrktkt
Copy link

nrktkt commented Mar 3, 2022

Having just tried to make a c4 diagram with plain mermaid for the past few days, as someone who doesn't care much about shapes and styles, I can say that the biggest issue right now is that flow diagrams are directional, and c4 (system) diagrams are not. This results in non-optimally placed nodes, crossed edges, and confusing edge labels.

I got this far

graph TD
    A(["A</br>[Container: ...]"])
    B["B<br/>[Software System: ...]<br/> ..."]

    subgraph "... </br>[Software System]"
    C("C</br>[Container: ...]</br>...")
    D("D </br>[Container: ...]</br>...")
    E("E </br>[Container: ...]</br> ...")
    F("F </br>[Container: ...]</br> ...")
    G("G </br>[Container: ...]")
    end

    A--"... </br> [...]"-->B-->C--"... </br> [...]"-->B
    A--"... </br> ...]"-->C
    
    C--"... </br> [...]"-->D
    E--"..."-->D
    E--"..."-->J("J </br>[Container: ...]</br> ...")
    H("H </br>[Container: ...]</br> ...")
    J-- ... -->H

    C--"... </br>  [...]"-->F
    G-- ... -->F
    I("... </br>[Container: ...]</br> ...")
    G-- ... -->I-- ... --> H
Loading

before deciding to stop because the output had become illegible.

If there were another mode in mermaid like the flowchart, but which doesn't try to enforce directionality, I think that would be sufficient for my (and most) usage.

@simonbrowndotje
Copy link

I can say that the biggest issue right now is that flow diagrams are directional, and c4 (system) diagrams are not.

It's really a tooling issue, and specifically the way that auto-layout algorithms work. As a human, it's relatively easy to create a nice diagram layout, and we can use contextual information that's not present in the diagram to organise elements to better tell a story. Here's a version of your example that I manually organised in <1 minute by dragging boxes around.

Manual layout

When it comes to automatic layout, most of the tools use a similar approach - they rank nodes based upon dependencies. You can sometimes influence the behaviour by changing the ordering of lines in your definition, change the node/edge/rank separation, and PlantUML provides some statements that can be used to tweak the algorithm. But ultimately the resulting layouts look very similar.

PlantUML

PlantUML

### Mermaid

Mermaid

Graphviz (viz.js)

Graphviz

In contrast to manual or automatic layouts, interactive visualisations don't make diagrams that are neatly embedded in traditional static documentation, but they do provide a lot more flexibility. These static screenshots don't do them justice, but here are a couple alternative ways to present the same information.

Ilograph

Ilogaph

d3.js

d3.js

It's all trade-offs. If you want to take a look at any of the above in more detail, here's a Structurizr DSL version of your diagram.

@nrktkt
Copy link

nrktkt commented Mar 7, 2022

@simonbrowndotje would you mind updating those graphs you made (awesome comparison) with labels for the edges? I think the edge label locations is a huge part of the legibility problem I'm seeing. Mermaid seems to put labels on only a finite set of y axis positions, so there's a much higher likelihood of overlap (iirc plantuml doesn't do this).

most of the tools use a similar approach - they rank nodes based upon dependencies

I believe that mermaid ALSO ranks nodes based upon direction in flow diagram mode. So my suggestion is to do something like add a UD (undirected) mode to flow diagrams in addition to the existing TD and LR modes.

@simonbrowndotje
Copy link

Sure, here you go:

(if you click "View source", you can edit the descriptions)

@dminca
Copy link

dminca commented Jun 19, 2022

Having C4 model would be really helpful to keep things DRY.

I've seen this vid about Diagrams as Code 2.0 by Simon Brown at Goto '21 and he actually has a DSL prepared for achieving this https://github.com/structurizr/dsl, hope this helps to give more clarity on the details of this feature.

@simonbrowndotje
Copy link

Having C4 model would be really helpful to keep things DRY.

hope this helps to give more clarity on the details of this feature

I think you'll need to be more specific in what you're looking for, because there's a fundamental mismatch of approach between Mermaid and the Structurizr DSL:

  • 1 Mermaid definition = 1 diagram
  • 1 Structurizr DSL definition = many diagrams

@jgreywolf
Copy link
Contributor

There appears to be some interest in this diagram type. If you would like to see this please provide a little more detail on how you would expect this to look/work (syntax suggestions, etc)

@jgreywolf jgreywolf added Contributor needed Status: Awaiting Reply Type: New Diagram and removed Type: Enhancement New feature or request Status: Triage Needs to be verified, categorized, etc labels Mar 7, 2023
@Ogglas
Copy link
Contributor

Ogglas commented Mar 17, 2023

@jgreywolf I think you are already on the right path in your own docs: https://mermaid.js.org/syntax/c4c.html that I think @ashishjain0512 and @pinghe started writing.

Fixing the unfinished features, getting out of experimental diagram and agreeing on syntax and properties this would be good to go in my world.

Your own examples on GitHub using Mermaid below (experimental so it might brake in the future). :)

C4 System Context Diagram (C4Context):

    C4Context
      title System Context diagram for Internet Banking System
      Enterprise_Boundary(b0, "BankBoundary0") {
        Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
        Person(customerB, "Banking Customer B")
        Person_Ext(customerC, "Banking Customer C", "desc")

        Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")

        System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")

        Enterprise_Boundary(b1, "BankBoundary") {

          SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

          System_Boundary(b2, "BankBoundary2") {
            System(SystemA, "Banking System A")
            System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
          }

          System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
          SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")

          Boundary(b3, "BankBoundary3", "boundary") {
            SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
            SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
          }
        }
      }

      BiRel(customerA, SystemAA, "Uses")
      BiRel(SystemAA, SystemE, "Uses")
      Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
      Rel(SystemC, customerA, "Sends e-mails to")

      UpdateElementStyle(customerA, $fontColor="red", $bgColor="grey", $borderColor="red")
      UpdateRelStyle(customerA, SystemAA, $textColor="blue", $lineColor="blue", $offsetX="5")
      UpdateRelStyle(SystemAA, SystemE, $textColor="blue", $lineColor="blue", $offsetY="-10")
      UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50")
      UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20")

      UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
Loading

C4 Container diagram (C4Container):

    C4Container
    title Container diagram for Internet Banking System

    System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system", $tags="v1.0")
    Person(customer, Customer, "A customer of the bank, with personal bank accounts", $tags="v1.0")

    Container_Boundary(c1, "Internet Banking") {
        Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser")
        Container_Ext(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
        Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
        ContainerDb(database, "Database", "SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
        ContainerDb_Ext(backend_api, "API Application", "Java, Docker Container", "Provides Internet banking functionality via API")

    }

    System_Ext(banking_system, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

    Rel(customer, web_app, "Uses", "HTTPS")
    UpdateRelStyle(customer, web_app, $offsetY="60", $offsetX="90")
    Rel(customer, spa, "Uses", "HTTPS")
    UpdateRelStyle(customer, spa, $offsetY="-40")
    Rel(customer, mobile_app, "Uses")
    UpdateRelStyle(customer, mobile_app, $offsetY="-30")

    Rel(web_app, spa, "Delivers")
    UpdateRelStyle(web_app, spa, $offsetX="130")
    Rel(spa, backend_api, "Uses", "async, JSON/HTTPS")
    Rel(mobile_app, backend_api, "Uses", "async, JSON/HTTPS")
    Rel_Back(database, backend_api, "Reads from and writes to", "sync, JDBC")

    Rel(email_system, customer, "Sends e-mails to")
    UpdateRelStyle(email_system, customer, $offsetX="-45")
    Rel(backend_api, email_system, "Sends e-mails using", "sync, SMTP")
    UpdateRelStyle(backend_api, email_system, $offsetY="-60")
    Rel(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS")
    UpdateRelStyle(backend_api, banking_system, $offsetY="-50", $offsetX="-140")
Loading

@nrktkt
Copy link

nrktkt commented Mar 21, 2023

@Ogglas I think those examples highlight my issue with mermaid's layout engine for c4 usage. The relationship lines are all over each other and the objects; making the diagram illegible.

@Ogglas
Copy link
Contributor

Ogglas commented Mar 22, 2023

@nrktkt I agree but with experimental support I do not expect much more. Relationship lines can be solved and I still think they are on the right track here

@CraigLager
Copy link

Really hoping for better C4 support soon. The experimental version is pretty close but is basically unusable at the component level.

@pinghe
Copy link
Contributor

pinghe commented Sep 24, 2023

@Ogglas I think those examples highlight my issue with mermaid's layout engine for c4 usage. The relationship lines are all over each other and the objects; making the diagram illegible.

For now this is just an experimental chart. You can use UpdateRelStyle(from, to, ?textColor, ?lineColor, ?offsetX, ?offsetY) to adjust the position of the labels to temporarily solve part of the problem!

UpdateRelStyle(customerA, bankA, "red", "blue", "-40", "60")
UpdateRelStyle(customerA, bankA, $offsetX="-40", $offsetY="60", $lineColor="blue", $textColor="red")
UpdateRelStyle(customerA, bankA, $offsetY="60")

@kepler
Copy link

kepler commented Oct 18, 2023

Having C4 model would be really helpful to keep things DRY.

hope this helps to give more clarity on the details of this feature

I think you'll need to be more specific in what you're looking for, because there's a fundamental mismatch of approach between Mermaid and the Structurizr DSL:

* 1 Mermaid definition = 1 diagram

* 1 Structurizr DSL definition = many diagrams

Is there any clarification and decision made on whether this will stay as the case or if there are plans on supporting 1 model => several diagrams/views?

@kputh
Copy link

kputh commented Oct 23, 2023

Perhaps it's worth discussing what you'd like to see in such a feature. "Supporting the C4 model" could range from some pre-defined styles and shapes through to adding new keywords to the Mermaid syntax (like you see with C4-PlantUML, for example).

(1) I'd like to see a solution that decouples architecture model and view (diagram) like Structurizr does. It would allow me to reuse my architecture model across any number of diagrams. Something else I like about Structurizr is the low number of DSL primitives.

(2) Also, I'd like to have distinguishable syntax for "boxes and arrows". Preferably one that looks like the other Mermaid diagram syntaxes. At the moment the C4 syntax looks like this:

Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
BiRel(customerA, SystemAA, "Uses")

and I'd rather have something like this:

Person CustomerA : "Banking Customer A" "A customer of the bank, with personal bank accounts."
System SystemAA : "Internet Banking System" "Allows customers to view information about their bank accounts, and make payments."
CustomerA --> SystemAA : "Uses"

(3) Furthermore, there are some recommendations ("Notation, notation, notation") for C4 diagrams. When you measure the current state of C4 diagrams in Mermaid against these, all relationships should be unidirectional.

(4) Just a thought: is the Structurizr DSL open-source and can Mermaid parse this kind of language? Maybe you don't have to invent a whole new DSL and can use the architecture model part of the Structurizr DSL in C4 diagrams.

@simonbrowndotje
Copy link

(1) I'd like to see a solution that decouples architecture model and view (diagram) like Structurizr does.

@kputh ... why not just use Structurizr, or one of the similar tools that decouples model from view? For example:

(4) Just a thought: is the Structurizr DSL open-source

Both the Structurizr DSL and underlying Structurizr for Java library are open source.

@kputh
Copy link

kputh commented Oct 23, 2023

@kputh ... why not just use Structurizr, or one of the similar tools that decouples model from view?

Well, it's about reach. Big software development platforms like GitHub, GitLab and Azure DevOps support Mermaid out of the box. If something like Structurizr ends up in Mermaid, it will be available on all of these platforms and any on-premises installation – without the administrative hassle and cost associated with adding plugins/extensions/whatever. I tested the current draft of Mermaid C4 diagrams on gist/GitHub – it works –, and I doubt anybody at GitHub lost any thought on supporting C4 diagrams.

@CraigLager
Copy link

What @kputh is detailing is exactly my issue at the moment. We have a very good mermaid plugin for Confluence, but to use C4 diagrams we need to use an alternative (none of which are very good and all incur an extra cost)

By the way @simonbrowndotje, love your work!!

@simonbrowndotje
Copy link

simonbrowndotje commented Oct 24, 2023

Cloning the Structurizr DSL requires porting ~20K lines of Java code, in addition to building any specific interactive diagram features (e.g. double-click to zoom) ... so I would hope that somebody is willing to financially sponsor such a large feature request.

Big software development platforms like GitHub, GitLab and Azure DevOps support Mermaid out of the box.

We have a very good mermaid plugin for Confluence

As I said before, a Structurizr to Mermaid export already exists (code), and it's bundled into the Structurizr CLI. It's relatively trivial to setup something like a GitHub Action that runs the CLI export command against a Structurizr DSL file to generate a collection of Mermaid definitions, which can then be committed to the repo and rendered as usual via GitHub, GitLab, Azure DevOps, your existing Confluence plugins, etc.

@garethcthomasdev
Copy link

Hi, I'm a big fan of both c4 and mermaid. I'm currently exporting component diagrams directly from code as part of our CI/CD process, and in the PlantUML world I make use of the element properties

like this

SetPropertyHeader("Class","Method")
AddProperty("MyService","MyMethod")
AddProperty("MyService","MyOtherMethod")
Component(mycomponentname, "demo component", "", "implements interfaces X,Y, Z ", "cogs", "")

is there anything I can do to help implement the same in the Mermaidjs ?

Here's the relevant documentation

https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/README.md#element-and-relationship-properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests