structurizr / dsl

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

Filtering multiple relations between the same containers #83

Closed gsson closed 3 years ago

gsson commented 3 years ago

While attempting to model an existing system I found that I needed to link two containers with more than one relation. The relations indicated different types of data and were used for different purposes, so collapsing them into one would not be a great idea.

So far so good, but as the diagram grew I wanted to create views for the different purposes, to isolate the flows.

What is the proper way of selecting one of two relations between containers for inclusion in views?

I've tried filtered views, exclusions, negative expressions and a few more things, but I can't quite get it to render the way I want it to.

I've tried with 1.14.0 locally and on https://structurizr.com/dsl

Example below:

workspace {
    model {
        user = person "User" "..." Weekday,Weekend
        softwareSystem1 = softwareSystem "Software System" "..." {
            routerContainer = container "Router" "..." "Magic" Weekday,Weekend
            serviceContainer = container "Handler" "..." "Magic" Weekday,Weekend
        }
        softwareSystem2 = softwareSystem "External System" "..." Weekday,Weekend

        user -> routerContainer "Requests" Weekday,Weekend
        routerContainer -> serviceContainer "Weekday requests" Weekday
        routerContainer -> serviceContainer "Weekend requests" Weekend

        serviceContainer -> softwareSystem2 "Requests" Weekday,Weekend
    }

    views {
        container softwareSystem1 AllContainers {
            include *

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekend requests" Weekend' relation,
        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            include relationship.tag==Weekday

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekday requests" Weekday' relation
        container softwareSystem1 WeekendContainers {
            include element.tag==Weekend
            include relationship.tag==Weekend

            autolayout
        }

        theme default
    }
}

All three views render the same, like this: structurizr-WeekendContainers

simonbrowndotje commented 3 years ago

Something like this?

workspace {
    model {
        user = person "User" "..." Weekday,Weekend
        softwareSystem1 = softwareSystem "Software System" "..." {
            routerContainer = container "Router" "..." "Magic" Weekday,Weekend
            serviceContainer = container "Handler" "..." "Magic" Weekday,Weekend
        }
        softwareSystem2 = softwareSystem "External System" "..." Weekday,Weekend

        user -> routerContainer "Requests" Weekday,Weekend
        rel1 = routerContainer -> serviceContainer "Weekday requests" Weekday
        rel2 = routerContainer -> serviceContainer "Weekend requests" Weekend

        serviceContainer -> softwareSystem2 "Requests" Weekday,Weekend
    }

    views {
        container softwareSystem1 AllContainers {
            include *

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekend requests" Weekend' relation,
        container softwareSystem1 WeekdayContainers {
            include *
            exclude rel2

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekday requests" Weekday' relation
        container softwareSystem1 WeekendContainers {
            include *
            exclude rel1

            autolayout
        }

        theme default
    }
}
gsson commented 3 years ago

Hi!

Thanks, yes!

The only problem is that the real diagram contains quite a few more relations, so filtering them individually would be more work and more error prone than maintaining two separate models -- which is my fallback plan, but one I'd like to avoid

simonbrowndotje commented 3 years ago

In that case, filtering by tags should work. Just FYI though, you're specifying Weekend as the relationship description, not the tag:

routerContainer -> serviceContainer "Weekday requests" Weekday

See https://github.com/structurizr/dsl/blob/master/docs/language-reference.md#relationship for the syntax. Alternatively, you can do this:

routerContainer -> serviceContainer "Weekday requests" {
    tags "Weekday"
}
gsson commented 3 years ago

Ah yes, sorry, I guess I put together the example a bit too quickly! My real diagram had it mostly right though -- I did miss the technology field in a few places, but nothing that impacts this.

Trying again using this syntax:

<identifier> -> <identifier> [description] [technology] [tags]

Which gives this DSL snippet

workspace {
    model {
        user = person "User" "..." Weekday,Weekend
        softwareSystem1 = softwareSystem "Software System" "..." {
            routerContainer = container "Router" "..." "Magic" Weekday,Weekend
            serviceContainer = container "Handler" "..." "Magic" Weekday,Weekend
        }
        softwareSystem2 = softwareSystem "External System" "..." Weekday,Weekend

        user -> routerContainer "Requests" "Magic" Weekday,Weekend
        routerContainer -> serviceContainer "Weekday requests" "Conjuration" Weekday
        routerContainer -> serviceContainer "Weekend requests" "Abjuration" Weekend

        serviceContainer -> softwareSystem2 "Requests" "Magic" Weekday,Weekend
    }

    views {
        container softwareSystem1 AllContainers {
            include *

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekend requests" "Abjuration" Weekend' relation,
        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            include relationship.tag==Weekday

            autolayout
        }

        // I want this view to omit the 'routerContainer -> serviceContainer "Weekday requests" "Conjuration" Weekday' relation
        container softwareSystem1 WeekendContainers {
            include element.tag==Weekend
            include relationship.tag==Weekend

            autolayout
        }

        theme default
    }
}

Which unfortunately still renders pretty much like the original picture

simonbrowndotje commented 3 years ago

As it says at https://github.com/structurizr/dsl/blob/master/docs/language-reference.md#include:

Please note that including elements will also include the relationships between those elements.

So the following will include all elements tagged Weekday, plus all relationships between those elements.

include element.tag==Weekday

So you'll need to exclude the additional relationships that you don't want to see; for example:

        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            exclude relationship.tag!=Weekday
            include relationship.tag==Weekday

            autolayout
        }

or

        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            exclude relationship.tag==Weekend
            include relationship.tag==Weekday

            autolayout
        }

This will also work given how you've used tags:

        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            exclude relationship.tag!=Weekday

            autolayout
        }

As will this

        container softwareSystem1 WeekdayContainers {
            include element.tag==Weekday
            exclude *->*
            include relationship.tag==Weekday

            autolayout
        }

Hope that helps!

gsson commented 3 years ago

Yes, perfect!

I had tried exclude *->* and various other combinations, but I only tried it before the include element .... Didn't consider the order :)

Thanks a lot!