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

the relation line between boundary seems a little strange #229

Closed featheryus closed 1 year ago

featheryus commented 2 years ago

The line to the right, but starting from the left side

Potherca commented 2 years ago

@featheryus Could you post an example to help illustrate what you mean?

(I moved your comment into the issue description, hope you don't mind)

miriamgreis commented 2 years ago

I have a similar problem. As soon as I introduce lines to a boundary, no matter what type of boundary, the diagrams start looking not that nice.

So here is an example:

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

System_Boundary(yxz, "YXZ"){
    Container_Boundary(A, "A"){
        Component(B, "B")
        Component(C, "C")
        Component(D, "D")
        Component(E, "E")
        Rel(B, C, "references")
        Rel(B, D, "references")
    }
    Container_Ext(F, "F")
    Container_Ext(G, "G")
    Rel(A, F, "includes")
    Rel(A, G, "includes")
}

System(system, "System")
BiRel_Neighbor(system, A, "relates to")

Person(person, "Person")
Rel(person, A, "does something")

LAYOUT_WITH_LEGEND()
@enduml

I don't understand why the line from System to A is so strangely placed and also why F and G are not simply placed below A as it would happen if A wouldn't be a boundary.

If I remove the _Neighbor from the relation between System and A, it really doesn't look better because the lines are going to the right instead of just straight to the top of the boundary.

image
Potherca commented 2 years ago

Thank you for posting an example @miriamgreis, that gives us something to work with!

Lets try to answer your questions...

Why is the line from System to A placed as it is?

By default, PlantUML aligns things implicitly (trying horizontally first and vertically second), which can give weird or undesirable results.

To change the layout, this project provides methods to set a direction explicitly, in the shape of (Bi)Rel_Down/Up/Left/Right.

For instance, using the provided example, we are unhappy with the layout of the relation between System and A.

So, instead of using BiRel_Neighbor, we can try BiRel_Up, BiRel_Down, BiRel_Left, or BiRel_Right and see which gives a better result:

Method Result
BiRel_Neighbor
BiRel_Up
BiRel_Down
BiRel_Left
BiRel_Right

Each of the Up/Down/Left/Right methods also has a shorthand notation, if you feel more so inclined: BiRel_U, BiRel_D, BiRel_L, or BiRel_R

Why are F and G not placed below A?

This has to do with things somewhat beyond our control... C4-PlantUML feeds instructions to PlantUML, which uses Graphviz to create the layout. Because of how things work internally, A is treated differently, as it is a container. This means using the Up/Down/Left/Right suffix most likely won't make much difference.

Reversing the order in which elements are declared will sometimes help, so Rel_Back(F, A, "includes") could be tried... However, Rel_Back does not (yet) have support for Up/Down/Left/Right, so the result might not be as good.

I could create a ticket to add Up/Down/Left/Right to the Rel_Back to make this problem easier to solve. :thinking:

miller79 commented 2 years ago

I have a question on this as well because I think the issue isnt' necessarily where the boxes are but how the arrows are drawn. In the system example, I'm not sure why it would try to draw the arrow to the right vs just connecting to the left box. This behavior seems to be only with boundaries but would be interested if there is work arounds outside of just playing with locations.

Potherca commented 2 years ago

I hate having to repeat this, but the majority of placement options are beyond our control, as they are decided by PlantUML or Graphviz.

It might be useful to have a look at LayoutOptions.md, which tries to explain these things and gives guidance on how to deal with quirks like these.

miller79 commented 2 years ago

Thanks for being direct and honest. So really until PlantUML or Graphviz address those, there's not a lot of adjustments that can happen. That's fair and I've been able typically to find a combination of layouts to work with what I need to do just was curious after seeing this if any efforts were going on to assist with that. If I get some spare time I may poke those teams and see their thoughts on adding more feature enhancements on that side.

viblo commented 1 year ago

Not sure if I can ressurect this one, or should create a new. Anyway, I was researching this problem a bit, and noticed there's a workaround suggested in the PlantUML forum. Basically you can create a sub diagram in the Boundary. It wont be possible to make relations to the inner elements, but in many cases I think that can be ok.

However, for this to work the Boundary procedure needs to put its body (the "inner" elements) within the [ {{ }} ] part. Is it possible to do such things? Otherwise maybe we could request it as a feature from PlantUML?

Something like this:

@startuml Debug
!include <C4/C4_Context>

HIDE_STEREOTYPE()

Boundary(frontend, "Frontend"){
    System(x, "X", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
    System(y, "Y", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
    ' System(z, "Z", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
    ' System(w, "W", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
}

rectangle backend [
    "Backend"
    {{
        System(a, "A", "Lorem ipsum dolor ")
        System(b, "B", "Lorem ipsum dolor")
    }}
    ]

System(i, "I", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") 
System(j, "J", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") 

Rel(x, backend, "")
Rel(y, backend, "")

Rel_R(i, backend, "")
Rel_L(j, backend, "")

footer Generated at %date("yyyy-MM-dd HH:mm")
@enduml