structurizr / java

Structurizr for Java
https://docs.structurizr.com/java
Apache License 2.0
1.01k stars 288 forks source link

prevent overlapping relations by changing the order in plantUML export #319

Closed chrikoch closed 2 months ago

chrikoch commented 2 months ago

Description

I know bidirectional relationships are not encouraged, but I have a scenario where two services call each other in different cases (A->B is http while B->A is Kafka), so I decided to model both relations. In the resulting diagram the relations are now rendered over each other so they can't be clearly read anymore.

I figured out this minimal example:

workspace "my workspace" {
  model {
    P1 = person "P1"
    A = softwareSystem "A" {
      group "group A1" {
        A1 = container "A1"
      }
      group "group A2" {
        A2 = container "A2"
      }
    }
    B = softwareSystem "B" {
      group "group B1" {
        B1 = container "B1" 
      }
      group "group B2" {
        B2 = container "B2" 
      } 
    }

    P1 -> A1 request
    P1 -> B1 request
    A2 -> B2 request
    B2 -> A2 response
    A1 -> A2 request
    B1 -> B2 request
  }

  views {
    container A {
      include A1
      include B1
      include A2
      include B2
      include P1
    }
  }

}

When exporting this to plantUML and rendering it via

docker run -v "$(pwd)/src:/usr/local/structurizr" structurizr/cli:2024.07.03 export -w model.dsl -f plantuml -o .
docker run -v "$(pwd):/data" plantuml/plantuml:1.2024.6 -tpng src/*.puml

the result is this where the relations between A2 and B2 are unreadable: structurizr-Container-001

As I figured out with plantUML (see https://forum.plantuml.net/19140/overlapping-arrows-when-components-are-in-rectangles?show=19141#a19141) this can be solved by changing this line in the puml file

B.B2 .[#707070,thickness=2].> A.A2 : "<color:#707070>response"

to

A.A2 <.[#707070,thickness=2]. B.B2 : "<color:#707070>response"

So having A.A2 on the left. Then the result is like this: structurizr-Container-001

So I suggest modifying the plantUML exporter, so that the elements are alphabetically ordered for example and the "smaller" element is always on the left (and changing the relation from > to < if necessary).

Priority

I have no budget and there's no rush, please add this feature for free

More information

No response

klu2 commented 2 months ago

StructurizrPlantUmlExporter already has these lines

if (relationshipView.isResponse() != null && relationshipView.isResponse()) {
    arrowStart = solid ? "<-" : "<.";
    arrowEnd = solid ? "-" : ".";
} else {
    arrowStart = solid ? "-" : ".";
    arrowEnd = solid ? "->" : ".>";
}

which should more or less do what you expect.

So how can we make a RelationshipView a response?

Unfortunately that setter is package-private and right now only be called in DynamicView, which is not what you need here - I'm sure @simonbrowndotje can help here, it's a more fundamental question if and how use response relationships should be available in static diagrams as well.

chrikoch commented 2 months ago

Yeah, that should solve my problem. However it's also not a perfect solution, as technically it is no response relationship, but simply a relation for another use case where the control flow is the other way around.

Actually, it would only be a workaround for a shortcoming in PlantUML :-( But I don't expect it to get fixed there.

simonbrowndotje commented 2 months ago

As you said in your PlantUML forum post, even this basic example doesn't work:

@startuml
rectangle "1" {
  component A
}
rectangle "2" {
  component B
}

A -> B: request
B -> A: response
@enduml

image

So I suggest modifying the plantUML exporter, so that the elements are alphabetically ordered for example and the "smaller" element is always on the left (and changing the relation from > to < if necessary).

This sounds overly complicated, and not something I want to add. It needs to be fixed in PlantUML really.