Closed dannief closed 3 years ago
Since the hexagon shape has recently been added to PlantUML, that part might be implemented.
@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
BR Helmut
@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.
@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.
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.
@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
Based on the Container and Microservice examples, and the slide from the talk:
We would need support for:
database
Databasehexagon
Microserviceperson
Personqueue
Message Busfolder
File systemBased on what we have, we are missing:
hexagon
(requested in https://github.com/plantuml-stdlib/C4-PlantUML/issues/12)person
(implemented in https://github.com/plantuml-stdlib/C4-PlantUML/pull/147)folder
(requested in https://github.com/plantuml-stdlib/C4-PlantUML/issues/104)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, ..)
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
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.
I'm not sure that we should make a copy of Structuriz.
I agree that we should definitely not.
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).
There's also a diamond shape now too -> Structurizr - Help - Shapes. :-)
... 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 ;-) )
... 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.
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).
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
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
@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
@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...
@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
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
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 ..,
In the examples section, (https://c4model.com/#Examples) , hexagons are used to depict a service in a container diagram