structurizr / dsl

Structurizr DSL
https://docs.structurizr.com/dsl
Apache License 2.0
1.41k stars 266 forks source link

Support conditionals and loops in dynamic views #115

Closed juanrferia closed 2 years ago

juanrferia commented 2 years ago

Nowadays dynamic views support parallel sequences. It would be great if they also support conditionals and loops, so we can communicate those type of dynamic behavior accordingly.

Given this example:

workspace {

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        c = softwareSystem "C"
        d = softwareSystem "D"
        e = softwareSystem "E"
    }

    views {

        dynamic * {
            a -> b "Get data (id)"

            b -> c "Get Core data (id)"
            c -> b "Core data" 

            b -> d "Get Additional data (id)"
            d -> b "Additional data"

            b -> e "Get Part data (part id)"
            e -> b "Part data"

            b -> b "Aggregate Data"
            b -> a "Data"
            autoLayout
        }
    }

}

Let’s suppose getting Additional Data is only required under some condition in Core data (conditional), and Core data include a list of Parts, which requires getting Part data for each part separately (Looping)

Nowadays there is no way to communicate that behavior as part of the dynamic view.

I believe a Communication Diagram generated from that dynamic view could support representing it based on Guards on messages. On the other hand, PlantUML (and probably others) sequence diagrams support those concepts by “opt”, “alt/else” and “loop” messaging blocks.

simonbrowndotje commented 2 years ago

The C4 model and Structurizr tooling are designed to be simple, and cater for "a majority" audience. What you're asking for takes you across that line, and into the realms of UML. If you need such features, I think you may have outgrown the tooling, and you're likely better off using UML directly given its much richer semantics.

juanrferia commented 2 years ago

Thanks Simon.

I do see the benefits of modeling that behavior with Structurizr, as it would let me separate it from the diagramming tool used to represent it. But I also fully understand you reject those features if they are out of scope of C4 model and Structurizr.

I think I got confused because I found parallel sequences in scope and, then, I didn't think conditions/loops are out of scope. What are the key differences between them to let first be accepted while second are not?

simonbrowndotje commented 2 years ago

The parallel sequence support really does nothing more than reuse the same sequence numbers, and I added it to provide a simple way to show parallel activities with the Structurizr cloud service/on-premises installation/Lite. I did look at making this more sophisticated (e.g. supporting nested hierarchical numbering, like UML does), but the UML specification for this is quite long and not particularly straightforward. So what we have at the moment is a "it's enough for most people" approach.

Translating dynamic views to PlantUML/WebSequenceDiagrams/etc requires a stricter set of semantics. It also requires more information than what's captured in the current version of the Structurizr workspace to do this, because the workspace doesn't include any information about these parallel sequences. If you look at the JSON for the dynamic views, you'll see that each relationship has a sequence number (named order), but there's nothing in there that describes the grouping of relationships into parallel sequences. All of this is possible, of course, but it'll require a significant amount of work, and the end-result will essentially be a re-implementation of the semantics that URL already has. Add on conditionals, guards, etc and you're essentially into UML territory. If this level of precise semantics are required by people, I'd recommend dropping Structurizr and adopting a fully fledged UML tool.

juanrferia commented 2 years ago

I'm not dropping Structurizr to adopt UML, but the other way around. No intention at all to move back to UML. But there are some basic needs on dynamic behavior I need to reflect on architecture diagrams to ensure architecture is communicated properly. If they are not supported on C4 Model / Structurizr then I will explore the option to use directly PlantUML for dynamic views. My first thought is I will miss some benefits of using Structurizr:

If you have any advice, I would appreciate it :) . Thanks!

simonbrowndotje commented 2 years ago

then I will explore the option to use directly PlantUML for dynamic views

Yes, using UML directly will be the best option if you need more preciseness and semantics than what the C4 model/Structurizr provides. For suggestions, off the top of my head:

  1. Write a PlantUML diagram generator (use the Structurizr for Java library to load the workspace), perhaps using hints in the relationship descriptions to generate the appropriate PlantUML code for conditionals, loops, etc.
  2. Handcraft your PlantUML diagrams, and write a parser that checks the content of the PlantUML diagram definition against the model. Element IDs are not guaranteed to be the same each time you run the DSL parser though, so you may need to implement some matching rules to compare model elements to those defined in PlantUML.
  3. Look at something like pumla that provides a way to use PlantUML in a model-based way.
juanrferia commented 2 years ago

Thank you!

juanrferia commented 2 years ago

Hi Simon. Question about approach 2:

As you pointed to, and also documented in the DSL language reference, we can only use the identifiers in the DSL-based workspace or in another DSL-based workspace extending the original one. Once a DSL-based workspace is parsed, those identifiers are gone and cannot be used anymore to reference to the elements.

Is it a decision part of the design? Or maybe a current limitation that could be fixed?

simonbrowndotje commented 2 years ago

Correct, the DSL identifiers are only used while the DSL is being parsed, and they're not retained in the JSON version of the workspace. I have no plans to change this.

juanrferia commented 2 years ago

Is there any possible workaround? Can I create a script or plugin to, for example, add a custom property on the element to keep track on the identifier used in DSL?

simonbrowndotje commented 2 years ago

Unfortunately not. And things like implied relationships are not assigned identifiers during DSL processing, so there would likely be some identifiers missing too.

juanrferia commented 2 years ago

What if StructurizrDslParser allows getting access to the identifier register after parsing?

https://github.com/structurizr/dsl/blob/master/src/main/java/com/structurizr/dsl/StructurizrDslParser.java#L34

I believe it would let me use same DSL identifiers in PlantUML code, as I would be able to get elements in the model with those identifiers to peform required actions to validate against the model and properly render elements.

What do you think?

simonbrowndotje commented 2 years ago

Sure, I can add a public getter for the identifiers register.

juanrferia commented 2 years ago

Great! Thank you!