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.41k stars 1.1k forks source link

Wrong rendering for Rel_R #332

Closed Oleg3n closed 10 months ago

Oleg3n commented 10 months ago

Hi With code like this:

@startuml C4_test2
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

System_Boundary(feature2, "Feature 2") {
    Container(ms2, "ms2", "Feature")
}

Lay_D(ms1, ms2)

Rel(ms1, kafka, "Publish")
Rel_L(ms2, kafka, "Publish")

Rel_R(con1, kafka, "Consume")
Rel_R(kafka, con2, "Consume")

@enduml

I am getting the below image

image

Shouldn't "kafka" be on the right side from "con 1" ? Thanks in advance

kirchsth commented 10 months ago

Hi @Oleg3n,

did you read https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/LayoutOptions.md#layout-guidance-and-practices ?

I think you have a sample which is not perfect rendered, but I think if you remove the Lay_D(ms1, ms2) it produces a better (your expected?) result.

BR Helmut

Oleg3n commented 10 months ago

Hi Helmut Thank you for the quick reply. Yes, I did read. Do you mean I break some rule? Or that I should have understood that drawing results are not predictable? :) Your trick is working for this minimal working test. What I initially tried to build is a diagram similar to this but vertically mirrored (DBs on the right, Externals on the left): image

and the best result I was able to achieve is this:

image

So I am trying to understand if I am doing something wrong or is it 'expected behavior'.

Code for the first image

@startuml C4_test3
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

System_Boundary(connectors, "Connectors") {
    Container(sink1, "Sink 1", "Sink connector")
    Container(sink2, "Sink 2", "Sink connector")
}

System_Ext(ext1, "External 1", "External System")
System_Ext(ext2, "External 2", "External System")

ContainerQueue(kafka, "Kafka")

System_Boundary(feature1, "Feature 1") {
    Container(ms1, "Component 1", "Feature")
    ContainerDb(db1, "DB")
}
System_Boundary(feature2, "Feature 2") {
    Container(ms2, "Component 2", "Feature")
    ContainerDb(db2, "DB")
}
System_Boundary(feature3, "Feature 3") {
    Container(ms3, "Component 3", "Feature")
    ContainerDb(db3, "DB")
}

Lay_D(sink1, sink2)
Lay_D(ms1, ms2)
Lay_D(ms1, ms2)
Lay_D(ms2, ms3)
Lay_D(ms2, ms3)

Rel_L(sink1, ext1, "Publish")
Rel_L(sink2, ext2, "Publish")

Rel(sink1, kafka, "Consume")
Rel_R(sink2, kafka, "Consume")

Rel(ms1, kafka, "Publish")
Rel_L(ms2, kafka, "Publish")
Rel(ms3, kafka, "Publish")

Rel_L(ms1, db1, "Persist")
Rel_L(ms2, db2, "Persist")
Rel_L(ms3, db3, "Persist")

@enduml

Code for the second image. The only difference from the first is _R replaced with _L and vice versa.

@startuml C4_test1
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

System_Boundary(connectors, "Connectors") {
    Container(sink1, "Sink 1", "Sink connector")
    Container(sink2, "Sink 2", "Sink connector")
}

System_Ext(ext1, "External 1", "External System")
System_Ext(ext2, "External 2", "External System")

ContainerQueue(kafka, "Kafka")

System_Boundary(feature1, "Feature 1") {
    Container(ms1, "Component 1", "Feature")
    ContainerDb(db1, "DB")
}
System_Boundary(feature2, "Feature 2") {
    Container(ms2, "Component 2", "Feature")
    ContainerDb(db2, "DB")
}
System_Boundary(feature3, "Feature 3") {
    Container(ms3, "Component 3", "Feature")
    ContainerDb(db3, "DB")
}

Lay_D(sink1, sink2)
Lay_D(ms1, ms2)
Lay_D(ms1, ms2)
Lay_D(ms2, ms3)
Lay_D(ms2, ms3)

Rel_R(sink1, ext1, "Publish")
Rel_R(sink2, ext2, "Publish")

Rel(sink1, kafka, "Consume")
Rel_L(sink2, kafka, "Consume")

Rel(ms1, kafka, "Publish")
Rel_R(ms2, kafka, "Publish")
Rel(ms3, kafka, "Publish")

Rel_R(ms1, db1, "Persist")
Rel_R(ms2, db2, "Persist")
Rel_R(ms3, db3, "Persist")

@enduml
kirchsth commented 10 months ago

Hi @Oleg3n,

I fear it is basically the "expected" behavior and I have no better rules.

I tried it with a different LAYOUT_LANDSCAPE(), changed the order of definitions, moved internal relations into the system boundaries, removed some double defined LAY_D() calls (and used feature1 instead of ms1, because I think the layout of the outside boundaries could be better(?)) and got something like this.

BR Helmut

Oleg3n commented 10 months ago

Thank you, Helmut. This is really helpful. This unpredictability for _L and _R makes me crazy but this is good news that eventually it should be possible to achieve the desired result. I appreciate your help and effort. All the very best in this New year Oleg