plantuml-stdlib / C4-PlantUML

C4-PlantUML combines the benefits of PlantUML and the C4 model for providing a simple way of describing and communicate software architectures
MIT License
6.44k stars 1.1k forks source link

Support for more shapes #145

Closed dannief closed 3 years ago

dannief commented 3 years ago

Request to add support for more shapes e.g. hexagon, frame, folder, collections etc.

Simon Brown suggests in the documentation https://c4model.com/#Notation that ..,

You can then use colour and shapes to supplement the diagram, either to add additional information or simply to make the diagram more aesthetically pleasing.

In the examples section, (https://c4model.com/#Examples) , hexagons are used to depict a service in a container diagram

Potherca commented 3 years ago

Since the hexagon shape has recently been added to PlantUML, that part might be implemented.

All available shapes ![](http://www.plantuml.com/plantuml/png/JP51RiGW34Nt_nHMBj0hp5KSS58q1ASEI9tRruGawkQ_1qQ0uNLKjjgs30vLZSuS_aNJu0HUfLGw4xuyBLwWMp1hAv7jGxSWi4NgWP0iPA41XApD2pqHD6S9DMavw9_x_BPhwUSzvdEbccQwYCYLPpw4Re6lIlL30rYIdza3Y-OeHWDOZ3SlzCIt_FAgXIuYbIhc_GWzXiopP3eJHQDG3-mStluMT16xsE4R3U2dIHCw4-PDSLdzCe_17poywKntjRxJHRH3Gc_huZtsdxXjmajAxF_r1m00)
Diagram source code ```csharp @startuml actor actor actor/ "actor/" agent agent artifact artifact boundary boundary card card circle circle cloud cloud collections collections component component control control database database entity entity file file folder folder frame frame hexagon hexagon interface interface label label node node package package person person queue queue rectangle rectangle stack stack storage storage usecase usecase usecase/ "usecase/" @enduml ```
kirchsth commented 3 years ago

@dannief you could add your own macro with Hexagon like below, but then you would not have the support of all other new features. I would suggest that you are using the supported sprites like http://www.plantuml.com/plantuml/uml/hL9DZzCm5BpdLtWh3brfkpu05oIahTh2Lkf7wGSLf-hLVcaCZXtyd9QVptEQhI8-90wSx7Z6CvvvUQ888TQbpUwCKxRMA8eOAtedPO3Buyd4eZxMX45v5z75H-LB-Sq4LL0ivEZDO6N1nTry9l47uner7nv6J0RZC3nMIJgxqvZpfnXFFaz7oyNc7pnYNO4EhsMLz5baO1WTvCmOK1LCH98bKCGWDPuJHZUN3yl5ThYVR9RpoNyrQixWWkHB7Boz5NPB9S6TQWjjwD_Xht26ls4bVRS7VjaPVxdUJIDhPb3RwMpuPRdR7lRJxVDXDlauMOpxzrcsOe9t_KHy4BrHJT6N67gyNw6lB8fOG1GEKOigU5shI0o-kYPztsiCUlVPRO1zge0lRrR3fD46JDjjWQ9aYZ1SPSX1jTAHprLhUyM0FSI5k-yQlIXrhQ0oB3nSJPD-AYkjp-2qHH9WhU3PCP58M7yogYkNs5sjyR6lZtnx316EG9YKvaO5JpwFOlDfraXxg-cbXWVXWyOWs8wVVVP68Q-v3oL4urtNh3ChzipMQDk-hrtj22d9DxyU4nBU89plp_1XVStUF7cDe4dkarM2dz1fdlTF

@Potherca: which extensions do you plan in v2.3.0? I wouldn't support all 28 possible shapes, because the overhead is not so small. If we really want more shapes we could add the person (and few other) symbols but not more. And if another shape is required they should be added by the user itsef (and we add only a detailed desription of the required steps)

@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml

Person(A, "Person A")
System(S, "System S")

skinparam hexagon<<container>> {
    FontColor $ELEMENT_FONT_COLOR
    BorderColor $CONTAINER_BORDER_COLOR
    BackgroundColor $CONTAINER_BG_COLOR
}
!define Hexagon(e_alias, e_label, e_techn) hexagon "==e_label\n//<size:12>[e_techn]</size>//" <<container>> as e_alias
!define Hexagon(e_alias, e_label, e_techn, e_descr) hexagon "==e_label\n//<size:12>[e_techn]</size>//\n\n e_descr" <<container>> as e_alias
Hexagon(db1,"DB1", "SQL")

' Only the other Person alternative could be explicitly added but I would NOT do it for all 28 elements 
skinparam person<<external_person>> {
    FontColor $ELEMENT_FONT_COLOR
    BorderColor $EXTERNAL_PERSON_BORDER_COLOR
    BackgroundColor $EXTERNAL_PERSON_BG_COLOR
}
' "_" is not a valid shortcut, it is only a fast shortcut that we get a ~90% UI (empty line is removed in final solution)
!unquoted procedure PersonC4_Ext($alias, $label, $descr="", $tags="", $link="")
person "$getPerson($label, $descr, "_")$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link)
!endprocedure

PersonC4_Ext(C4, "Person C4")

SHOW_LEGEND()
@enduml

hexagon simple;

BR Helmut

dannief commented 3 years ago

@kirchsth I actually tried to add my own macros but realized that all features were not available unless I modified the library source code.

Tried modifying the source to add the shapes I wanted, but unfortunately got a 414 URI too long error when trying to include the library files locally. (I don't have the option of running plantuml locally at the moment). I don't like this option anyway because it will be harder to keep up with new versions if I modify source directly.

So I am using other colors and sprites for now. But It seems the best way is to wait until more shapes are directly supported.

kirchsth commented 3 years ago

@dannief you could use following pattern

@startuml
' convert it with additional command line argument -DRELATIVE_INCLUDE="." to use locally
!if %variable_exists("RELATIVE_INCLUDE")
  !include ./../C4_Component.puml
!else
  !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
!endif

' ===========================

' define additional calls
!unquoted procedure UpdateHexagonStyleToo($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="")
$elementTagSkinparams("hexagon", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing)
!endprocedure

!unquoted procedure SystemHexagon($alias, $label, $descr="", $sprite="", $tags="", $link="")
hexagon "$getSystem($label, $descr, $sprite)$getProps()" $toStereos("system", $tags) as $alias $getLink($link)
!endprocedure
!unquoted procedure SystemHexagon_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="")
hexagon "$getSystem($label, $descr, $sprite)$getProps()" $toStereos("external_system", $tags) as $alias $getLink($link)
!endprocedure

' requires C4_Container
!unquoted procedure ContainerHexagon($alias, $label, $techn, $descr="", $sprite="", $tags="", $link="")
hexagon "$getContainer($label, $techn, $descr, $sprite)$getProps()" $toStereos("container", $tags) as $alias $getLink($link)
!endprocedure
!unquoted procedure ContainerHexagon_Ext($alias, $label, $techn, $descr="", $sprite="", $tags="", $link="")
hexagon "$getContainer($label, $techn, $descr, $sprite)$getProps()" $toStereos("external_container", $tags) as $alias $getLink($link)
!endprocedure

' requires C4_Component
!unquoted procedure ComponentHexagon($alias, $label, $techn, $descr="", $sprite="", $tags="", $link="")
hexagon "$getComponent($label, $techn, $descr, $sprite)$getProps()" $toStereos("component",$tags) as $alias $getLink($link)
!endprocedure
!unquoted procedure ComponentHexagon_Ext($alias, $label, $techn, $descr="", $sprite="", $tags="", $link="")
hexagon "$getComponent($label, $techn, $descr, $sprite)$getProps()" $toStereos("external_component",$tags) as $alias $getLink($link)
!endprocedure

' set default styles 
skinparam hexagon {
    StereotypeFontSize 12
    shadowing false
}

UpdateHexagonStyleToo("system", $SYSTEM_BG_COLOR, $ELEMENT_FONT_COLOR, $SYSTEM_BORDER_COLOR, false)
UpdateHexagonStyleToo("external_system", $EXTERNAL_SYSTEM_BG_COLOR, $ELEMENT_FONT_COLOR, $EXTERNAL_SYSTEM_BORDER_COLOR, false)
UpdateHexagonStyleToo("container", $CONTAINER_BG_COLOR, $ELEMENT_FONT_COLOR, $CONTAINER_BORDER_COLOR, false)
UpdateHexagonStyleToo("external_container", $EXTERNAL_CONTAINER_BG_COLOR, $ELEMENT_FONT_COLOR, $EXTERNAL_CONTAINER_BORDER_COLOR, false)
UpdateHexagonStyleToo("component", $COMPONENT_BG_COLOR, $COMPONENT_FONT_COLOR, $COMPONENT_BORDER_COLOR, false)
UpdateHexagonStyleToo("external_component", $EXTERNAL_COMPONENT_BG_COLOR, $COMPONENT_FONT_COLOR, $EXTERNAL_COMPONENT_BORDER_COLOR, false)

' =====================================================

' if custom styless are required call additional $UpdateHexagonStyleToo()
!$COLOR_A_5 = "#7f3bf7"
!$COLOR_A_1 = "#fe00f7"
!$COLOR_NEUTRAL = "#6633f7"
UpdateElementStyle("external_component", $EXTERNAL_COMPONENT_BG_COLOR, $COLOR_A_5, $COLOR_A_1, false)
UpdateHexagonStyleToo("external_component", $EXTERNAL_COMPONENT_BG_COLOR, $COLOR_A_5, $COLOR_A_1, false)

' if an additional cutom tag is required then call UpdateHexagonStyleToo() too
AddElementTag("special", $bgColor=$COLOR_NEUTRAL)
UpdateHexagonStyleToo("special", $bgColor=$COLOR_NEUTRAL)

ContainerHexagon(containerHex, "Special Container", "techn", "special version", $tags="special")

ComponentHexagon(compHex, "Componet", "techn", "Optional Description")
ComponentHexagon_Ext(compHexExt, "Component Ext", "techn")

SHOW_LEGEND("false")
@enduml

BR Helmut

PS.: the used $...() calls are internal methods and could be changed in one of the following versions but if you put the common part in a separate file and include it from there then it should be not a big problem if you have to update this one file.

Potherca commented 3 years ago

I wouldn't support all 28 possible shapes, because the overhead is not so small.

@kirchsth I would suggest not supporting shapes unless they are part of the C4 Model, so for now only hex and person are missing (as they were also missing from PlantUML). Now they have been added there, we can add both here. Beyond that I think we have them all.

kirchsth commented 3 years ago

@Potherca: @dannief requests add support for more shapes e.g. hexagon, frame, folder, collections etc. contains basically everything and therefore I'm not sure if we should support everything.

And if we add additional shapes then we have a big missing part in the legend (what means hexagon?). I think the existing sprites have a better documentation factor.

Hexagon is basically solved (If I add the part between the lines we are basically done) but I would at least add the additional shapes via an additional "C4_AdditionalShapes.puml" file.

Best regards Helmut

PS.: Person shape can be already activated via MR #147

Potherca commented 3 years ago

Based on the Container and Microservice examples, and the slide from the talk:

Container example Microservice example

screenshot from slides

We would need support for:

Based on what we have, we are missing:

All available shapes

Diagram code ``` @startuml !$url = "https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/v2.2.0" !include $url/C4.puml !include $url/C4_Component.puml !include $url/C4_Container.puml !include $url/C4_Context.puml !include $url/C4_Deployment.puml !include $url/C4_Dynamic.puml rectangle database { ComponentDb('ComponentDb', 'ComponentDb', 'ComponentDb') ComponentDb_Ext('ComponentDb_Ext', 'ComponentDb_Ext', 'ComponentDb_Ext') ContainerDb('ContainerDb', 'ContainerDb', 'ContainerDb') ContainerDb_Ext('ContainerDb_Ext', 'ContainerDb_Ext', 'ContainerDb_Ext') SystemDb('SystemDb', 'SystemDb', 'SystemDb') SystemDb_Ext('SystemDb_Ext', 'SystemDb_Ext', 'SystemDb_Ext') } rectangle queue { ComponentQueue('ComponentQueue', 'ComponentQueue', 'ComponentQueue') ComponentQueue_Ext('ComponentQueue_Ext', 'ComponentQueue_Ext', 'ComponentQueue_Ext') ContainerQueue('ContainerQueue', 'ContainerQueue', 'ContainerQueue') ContainerQueue_Ext('ContainerQueue_Ext', 'ContainerQueue_Ext', 'ContainerQueue_Ext') SystemQueue('SystemQueue', 'SystemQueue', 'SystemQueue') SystemQueue_Ext('SystemQueue_Ext', 'SystemQueue_Ext', 'SystemQueue_Ext') } rectangle person { Person('Person', 'Person', 'Person') Person_Ext('Person_Ext', 'Person_Ext', 'Person_Ext') } rectangle "dashed rectangle" { Container_Boundary('Container_Boundary', 'Container_Boundary', 'Container_Boundary') Enterprise_Boundary('Enterprise_Boundary', 'Enterprise_Boundary', 'Enterprise_Boundary') System_Boundary('System_Boundary', 'System_Boundary', 'System_Boundary') } rectangle rectangle { Component('Component', 'Component', 'Component') Component_Ext('Component_Ext', 'Component_Ext', 'Component_Ext') Container('Container', 'Container', 'Container') Container_Ext('Container_Ext', 'Container_Ext', 'Container_Ext') System('System', 'System', 'System') System_Ext('System_Ext', 'System_Ext', 'System_Ext') Deployment_Node('Deployment_Node', 'Deployment_Node', 'Deployment_Node') Node('Node', 'Node', 'Node') } @enduml ```
kirchsth commented 3 years ago

If you follow the example https://c4model.com/#Examples (e.g. click on "Message bus and microservice") you end on Structurizr (and this is not C4 model itself anymore) and then you will find following shapes too (incl. rounded rectangles, circles, ..., component, ..)

https://static.structurizr.com/workspace/12541/diagrams/shapes.png

I'm not sure that we should make a copy of Structuriz. If you want that then we would have to extend e.g. legend too like in Structurizr with corresponding shapes https://c4model.com/img/bigbankplc-Containers-key.png

And if you compare the Structurizr shapes with the PlantUML shapes then I think Structurizr has the better layout at all. E.g. compare the flat PlantUML hexagons from my implementation sample above with the equilateral hexagon in Structurizr.

Potherca commented 3 years ago

I'm not sure that we should make a copy of Structuriz.

I agree that we should definitely not.

As Simon Brown stated in #97

there is no "C4 model notation" [..] feel free to use whatever shapes/icons you like

I think we should keep the shapes limited to those used in the examples on the c4model.com website as those will be most widely used (and not all shapes offered by https://structurizr.com/).


And if we add additional shapes then we have a big missing part in the legend (what means hexagon?). I think the existing sprites have a better documentation factor.

I think this is the core issue...

Adding the shape is only half of the solution. To my mind, we should not be adding shapes but Container, Components, etc.

The current status is:

C4 Model PlantUML Status Function
Anything rectangle :heavy_check_mark: Component, Container, System
Boundary rectangle :heavy_check_mark: ContainerBoundary, EnterpriseBoundary, SystemBoundary
Database database :heavy_check_mark: ComponentDb, ContainerDb, SystemDb
File system folder :x: (requested in #104)
Message Bus queue :heavy_check_mark: ComponentQueue, ContainerQueue, SystemQueue
Microservice hexagon :white_check_mark: (implemented in #147)
Node rectangle :heavy_check_mark: DeploymentNode, Node
Person person :white_check_mark: Person (implemented in #147)
Person rectangle :heavy_check_mark: Person
Queue queue :heavy_check_mark: ComponentQueue, ContainerQueue, SystemQueue

For the hexagon and folder shapes, we would add Microservice and FileSystem functions for Component, Container, and System (similar to Db and Queue).


compare the flat PlantUML hexagons from my implementation sample above with the equilateral hexagon in Structurizr

I'd say that if we offer the shape provided by PlantUML, that would satisfy the need for now. Any improvements to the shape can always be added later. (The same process that has occurred for the Person style/shape).

simonbrowndotje commented 3 years ago

There's also a diamond shape now too -> Structurizr - Help - Shapes. :-)

kirchsth commented 3 years ago

... therefore I prefer sprites in a rectangle and we don't have to extend the PlantUML implementation for each shape

(PS.: @simonbrowndotje: I expected something like this, I hope you do not show it in a presentation ;-) )

simonbrowndotje commented 3 years ago

... therefore I prefer sprites in a rectangle and we don't have to extend the PlantUML implementation for each shape

That seems sensible, unless you do something like Container(..., 'queue')? That aside, having a colour-based diagram key/legend that doesn't include shapes will likely confuse people. The sprites should really be included in the legend too.

Potherca commented 3 years ago

Maybe we could implement a named parameter, similar to $tags? :thinking:

That way, users could explicitly set a shape if they wanted to, we would be future-proof to any new shapes added to PlantUML and the added overhead/changes would be limited (in comparison to having to add new functions).

kirchsth commented 3 years ago

I compared the results of the 2 different microservice example layouts:

With existing $tags pattern (colors can be improved)

And with the requested hexagon:

And I think the rectangles produces the better layout (even without sprites)

BR Helmut

source links http://www.plantuml.com/plantuml/uml/bLLDR-Cs4BthLqpT0hK1RumjUYgmmFh3tGyujjToi4TXHD4IiHGfa9HJj-X_xr2oj7IYRP0S4d4qyzuRlj7alNLeN5tAw2UXcAmp3eLpbVrZDZFuU9SBLzHfRRbXMZckt1tJvUoRCAomhfWjVt-pbwZSm_rcnl-YzndFA9WiAHc5ukQkyj2_GgsehgHwS0M7avPIFmgLWwGaG9N1pMjXB3rf85wGcg6K5yBe1JudYEAFkw_9Vds8Tzjazt3SVDgknvCeccVPMd8FVCHyFA8speBnX7NLeodyakPBBRLvDrfgeqwaYvk5hBb_TQAywyl7GZW-cZn5hBYnmZew_W1KYhnm_uCNxGb1gp6hhTCbDrDOza-ZENHXdnbVYAXC5hfM6PhBcBsbb2uRFgcJDYKweTLe0lz44T1FVqrZhAemUrvLKh0sc-AVyOoM6L6vASnLNaiqFZptDjbUXFMUbAWmvzudOQ0o-YGazV6KhYj9hbSUSiTjgEETGbmPFmiBhPqF7WiEbHRAWJu1CiQj1Ugjbm4YQ9LkrM5ktmru-qnKIKYaFQ5v9fhxzWIBsdhM0wQfSFTV6WK6bQsqSGqlfGlbHV0pLyu-npNSvr8BGRU7BXQsUwZJY_-xD1mTjw1y6r9Oda663Xks7WogsbJQSlkg7h7EX0jqpFqvrB3yUNQtNH_zuzxeiyX8XpOvAc6R6ttpI25eOBo84p8XwV5rCbRfzmd8qj3y5JfCqJPITWQPvF3sD-PFiTE6snTS7lZUXjW3IuW-T2Falx_4NpO1DNQ6_CqpE7ichPePbFBx4FH6OGQ5PiD-lKPjPnbf20pp9ozjJJFN7NkbuTq0fhfsrza4Lw230i-SVbKLLpnxKSs_KNJWCbX0xQfuQ3iPVJmUzp6b-QJaqEwHWQ_xeShG_S0-y7UNUp2q5yMcy9dMzEm6U3EmCLeTCLUPxTlJ7kKhJsFDld57rOsgWUBmM-z0Ucrr8pO0RN5M0pZX6FVNtyo0Q3VdQh6yDd6xNuQMmiiodi4qm_4gY0PZWBqF3RRIKZzX2oUpg-YucffeWvVaCCHsWpIv_eF-SxER7pzjFoIRzOVrTZMUDFKhOHqgniTTzCQzIVIUMgvB-Hy0 http://www.plantuml.com/plantuml/uml/pLPjRzks4t-lJy7w7-0l0scC3dirO40TMtqe_E1Q3hgz4YZfR16XIPMaqhh3llkEOiJIdRh43eQrBsBnTFTx84_7ljI6AjFiUVICYO8t9P3Ac5h_CXef-kbgnqpLv8q6LKXXG9YhGkv7jqmLbJRLQFBpynMdmjpCPoFuZEzBA36OJJ2PCW7gghRG_oUDmBezrXDJ0TbApkKd9dQ4OnAXeYH7hvdI-2G9yX8k2yhv0J6ymByJuDiIjYrMMJB3fA2Ss3eTFMl4nqOQA4cjP05beu3Sr2Kry0O-qvqKgJbms4WPNnYwImqea9Va8jzD99Vgry405rja2vQvL2Me8A0hMhP-S3cCBe23zR91k5icQgheNiU3oj5XVXzHo79C4U8FesSWIcyawdMN7hI1_Rsx-89oHZM2S9e3nzyITD7fhXKpu9vHatPFd8dRriYzOZAus85ngF4nZCSOsfILahMEXmC4ayuVsjPjNSSm95GJ9udOaXbonItZDzOUTfObdyr_xiuslHAKP-VQnCvLyB5X2lHHN_Vwzs-_UxW6YagSlmsU83v6F657YWxYQKVUOzcV-ezespT2wF-flR2lfG1XUZV6l_stUi4JFA4NEeZ1vTDR8NJiM-57TErRuNpxs0aQZBtJQCCDqVQAqYJItNL2Eir_H0J_EMfpgE6L52PbNu2y-AbzusyEigLSG_Hd5FLVVi6SJdzFDyayktwTJPQpvHeZoIoP9ujDzcg9VzfWaBPSJvDr5srPXlqSlTCo-MsJh1VZMVP8Lfz_EltnQ9eWwlZj0ciVelIPvtaDM0FvZwVt9UVfy4teJCzNomLIUDOm6F26uNDj1xpUmoa2VD43Ig8eVRFyaAsITRfSPCkRpGmtASRu2fIM8YuQRUGUr2MP-AV1c7JX0MQwwp-xbeqegJh4nGjCwRB9Mx6LQayDas8mn4-k_RA-tXcqhiFiSLrpLhXiZB-ZTrGNYjNcaep5hk5K3Io__H-mzY8qCPBigQ0x8AO2fkpSsp8EgCxJXVUWTvLfK7UiW512wa8T_IL9QsLdmBMKnWOt5P1QCc68t19Q5A0rGOjU3M61Opyqxuc2XlvMMxn79BIGvOr6chbRaUj6MzOrpNDcvkzR1OeANKjbMbvCPyAAW3iGHd_Nim9RWau2q-ik5hfUD_d1_auKK0EQ2Ek6CmqbAQcXBQa78tMZQgb1ds3LIw9DoKmWPspNePJ9_qPNYsHZ7rTAth4ID95gHmNJxVu-_uGXqiAuCLqmZe-dgPdcN_kXpCDMcABTdEfMobBHWjkheR2hr4W5-e4phq5ffWq8yu_imSaWVNWe8V_yaBwV1TIqEvSlK98xooH5sv6SVsq9Vrwq99KiUexjHBNTaQ66uC1mrMfCi0FzqYiDzeRGN3RclbE9gQWX5Rq3_5FN8A1yK0rUmMlWmLHoy-F6EHcysMnMAQRPf6pjXalFj-x6R__n4RjtEmj6zK4Kb-GT3iRH4V2iPtuu7Ic8Kdjxqg9yW3oLnIqOh6vLzHG7Nxu7yTgQLcm0wd2cFJX16_ljTpt0t3YTNa_kJHnFcxxPy2WPnp2kEKw1Q35ws7serugZ_eOjx4nVuRXSJJIZXspTntQ4DBo_4b_DbkFDsyNhR9QyJXRJUDZMJvasL1GGTz6Zqnj6Bz5oi-T_0G00
kirchsth commented 3 years ago

The PlantUML supported shapes in "C4-PlantUML" style would look like:

The package shape (package stereotype would interfere with required border() stereotyp style), actor, actor/ and person (already realized with existing implementation) and usecase/ (ellipse with / has no real counterpart in C4-model samples) shouldn't be supported.

BR Helmut

PS.: source http://www.plantuml.com/plantuml/uml/pPXHQ-D64CVVzIcc9d09N2ESjb3ASHpr-Tg7f3dYzA5GC1jfB2rUxOZT4Jwtt7UlF5eP-UHUsrDO-kAO_rhp-ur0uudVU5QEcyeaNscRcIP7A9bh_qEQEhMxBZINpLFZqMLa6IrVPrIbM-soqdEPBhxz-hrHbd-zkqtn0wFDCM_3zO8iAstHNTU7qY-WiUrr5Le6BX4sP0pjj2t0Q8kWR0udnzfv1YPekM0eKyRisnf7mJ4WyLjjQ-LK1IL-K0LP-3C105WnEYJUr_YEBA_q7mZp6pdnfSexXuqo7fEFWnggGClJAZZM6vLDAv8PQl9f5SWOp5YJzHFhL3LPj3obo4ORd7GzcHmTJ2hHlk2a2fRoQGKygsmxiG8vLKopQ3ncodz13Kalq625bXzLiUfB-ijPUFHcBs7czvwnQjzTh7vRFIxlrZ_-j5xStzu_jCdoTdct_ELn_Uw-VP5myB7xXxVBXpuLvjNdaFAanWI61pigK-P0JE1WRCJ5XYaJ4tgOIb5vCiMY4ji_KLkqb3y_xmLaobfYU49eFEPmgIsZsw1o7dQQItYYnkRAxS7ptg1lB_cCOwsohIgYtXQP_761v2Bt6BvNdXqfp7wrcrqKoCSDyEHxXp4hvSt2eMBqOCbLocYFEUIA5Mp8WSEQ76jRGDsucZpAb9jT7Sg-TrJxowiPN31rNul-icz5FWJAmyyTS2vMAcDo8oT9una9Rk2JdXTAqzXAiaPq2_L8IT9uGeAJUzIlvsEbS13JAX15h5lvHrQInbCINESps0H6LeEpU6u3Q6yObeQnNtyIqouWnKt-unbf7S9eHg8GP6Jn6Ej87558U9sIR2PZ8-ShZ2SakCx7KZxMQSDuDg8mJxvWsv46mbOpwY7a9ssS0bx2ZXgJGy0uF4lvZyq4xFpccqJqP0CQoKaQxmuBRXvyo9sxNI6FwIJ0pYhiK2EhaCUp2i0Jg_Jlj6vYxXOzCn6r6fq_inPsSJmfuOMbq676oXPdnl_n99xO4JaV_b1wJ5-zSeUdF2DdqRr-7NuJUZXa2ydWvhlaup-q9INWV7FXb-71yUzMfejSr8sMVztImFMJxiJuV8EvLWLPPJxfyMs8Gvlpx_y_RGwDHvtsticR5jXKvYy0

kirchsth commented 3 years ago

@Potherca: I still think we should not add (too many) shapes, otherwise I would have to make a very generic implementation and we lose the C4 relation and create a new "Meta" notation (Could be a good idea for a separate git repository).

As an alternative I think we could consider the round and diagonal corners in the tag styles too (like shadow). Based on that we still could document everything via tags (and instead of a hexagon an octagon can be used).

What do you think?

BR Helmut

@startuml
!include https://raw.githubusercontent.com/kirchsth/C4-PlantUML/extended/C4_Container.puml
' uncomment the following line and comment the first to use locally
' !include C4_Container.puml

SHOW_PERSON_OUTLINE()

AddElementTag("service_container", $bgColor="CornflowerBlue", $fontColor="white")
skinparam rectangle<<service_container>> {
    DiagonalCorner 18
}

AddElementTag("persistent_container", $bgColor="lightBlue", $fontColor="white")
skinparam rectangle<<persistent_container>> {
    RoundCorner 25
}

Person(customer, Customer, "A customer")
System_Boundary(c1, "Customer Information") {
    Container(app, "Customer Application", "Javascript, Angular", "Allows customers to manage their profile")
    Container(customer_service, "Customer Service", "Java, Spring Boot", "The point of access for customer information", $tags="service_container")
    Container(message_bus, "Message Bus", "RabbitMQ", "Transport for business events")
    Container(reporting_service, "Reporting Service", "Ruby", "Creates normalised data for reporting purposes", $tags="service_container")
    Container(audit_service, "Audit Service", "C#/.NET", "Provides organisation-wide auditing facilities", $tags="service_container")
    ContainerDb(customer_db, "Customer Database", "Oracle 12c", "Stores customer information", $tags="persistent_container")
    ContainerDb(reporting_db, "Reporting Database", "MySQL", "Stores a normalized version of all business data for ad hoc reporting purposes", $tags="persistent_container")
    Container(audit_store, "Audit Store", "Event Store", "Stores information about events that have happened", $tags="persistent_container")
}

Rel(customer, app, "Uses", "HTTPS")
Rel_R(app, customer_service, "Updates customer information using", "async, JSON/HTTPS")
Rel_L(customer_service, app, "Sends events to", "WebSocket")
Rel_R(customer_service, message_bus, "Sends customer update events to")
Rel_D(customer_service, customer_db, "Stores data in", "JDBC")
Rel(message_bus, reporting_service, "Sends customer update events to")
Rel(message_bus, audit_service, "Sends customer update events to")
Rel(reporting_service, reporting_db, "Stores data in")
Rel(audit_service, audit_store, "Stores events in")
Lay_R(reporting_service, audit_service)

SHOW_FLOATING_LEGEND()
Lay_Distance(LEGEND(), message_bus)
@enduml

Updated: reduced DiagonalCorner from 25 to 18 that text is not outside of the area

Potherca commented 3 years ago

@kirchsth Yeah, I agree we need to limit things to shapes that have a defined meaning. I think your example using round and diagonal corners makes sense. The used octagon looks much better than the hexagon provided by PlantUML, to my eye. I think that could already be added in a separate MR.

I'm still in two minds about the folder shape...

kirchsth commented 3 years ago

@Potherca, @dannief: I added the rounded-box and eight-sided shapes support to branch #146 that we can draw diagrams like

@startuml
!include https://raw.githubusercontent.com/kirchsth/C4-PlantUML/extended/C4_Container.puml
' uncomment the following line and comment the first to use locally
' !include C4_Container.puml

AddElementTag("micro service", $shape=EightSidedShape(), $bgColor="CornflowerBlue", $fontColor="white")
AddElementTag("storage", $shape=RoundedBoxShape(), $bgColor="lightSkyBlue", $fontColor="white")

SHOW_PERSON_OUTLINE()

Person(customer, Customer, "A customer")

System_Boundary(c1, "Customer Information") {
    Container(app, "Customer Application", "Javascript, Angular", "Allows customers to manage their profile")
    Container(customer_service, "Customer Service", "Java, Spring Boot", "The point of access for customer information", $tags = "micro service")
    Container(message_bus, "Message Bus", "RabbitMQ", "Transport for business events")
    Container(reporting_service, "Reporting Service", "Ruby", "Creates normalised data for reporting purposes", $tags = "micro service")
    Container(audit_service, "Audit Service", "C#/.NET", "Provides organisation-wide auditing facilities", $tags = "micro service")
    ContainerDb(customer_db, "Customer Database", "Oracle 12c", "Stores customer information", $tags = "storage")
    ContainerDb(reporting_db, "Reporting Database", "MySQL", "Stores a normalized version of all business data for ad hoc reporting purposes", $tags = "storage")
    Container(audit_store, "Audit Store", "Event Store", "Stores information about events that have happened", $tags = "storage")
}

Rel_D(customer, app, "Uses", "HTTPS")

Rel_D(app, customer_service, "Updates customer information using", "async, JSON/HTTPS")

Rel_U(customer_service, app, "Sends events to", "WebSocket")
Rel_U(customer_service, message_bus, "Sends customer update events to")
Rel(customer_service, customer_db, "Stores data in", "JDBC")

Rel(message_bus, reporting_service, "Sends customer update events to")
Rel(message_bus, audit_service, "Sends customer update events to")

Rel(reporting_service, reporting_db, "Stores data in")
Rel(audit_service, audit_store, "Stores events in")

Lay_R(reporting_service, audit_service)

SHOW_LEGEND()
@enduml

I plan no other additional shapes.

BR Helmut

Potherca commented 3 years ago

Closing for now as the accepted shapes have been implemented in v2.3

Discussion regarding the "folder" shape can continue at https://github.com/plantuml-stdlib/C4-PlantUML/issues/104