structurizr / dsl

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

Common deployment elements between environments #205

Closed dgutson closed 1 year ago

dgutson commented 1 year ago

It would be good if there would be the idea of extending deploymentEnvironments, for example having a base deploymentEnvironment with some deploymentNodes, and then two deploymentEnvironment with some extended nodes. I understans some basic extension could be done with includes, but a first class language feature would be very useful. Single node vs multi node for example have a lot of things in common. I think that inheritance here is the right concept. So you define the nested hierarchy (environment-nodes-containers) and then you inherit and extend (environment-node-more_containers) by name, optionally more_nodes.

pkunze commented 1 year ago

If I understand correctly, I think this is what deployment groups are meant for...

Think something along the lines of the following:

workspace {

    model {
        softwareSystem = softwareSystem "Software System" {
            database = container "Database"
            api = container "Service API" {
                -> database "Uses"
            }
        }

        commonSoftwareSystem = softwareSystem "Common Service"

        api -> commonSoftwareSystem "Uses shared service"

        deploymentEnvironment "Example" {
            serviceInstance1 = deploymentGroup "Service Instance 1"
            serviceInstance2 = deploymentGroup "Service Instance 2"
            deploymentNode "Server 1" {
                containerInstance api serviceInstance1
                containerInstance database serviceInstance1
            }
            deploymentNode "Server 2" {
                containerInstance api serviceInstance2
                containerInstance database serviceInstance2
            }

            deploymentNode "Server 3" {
                softwareSystemInstance commonSoftwareSystem serviceInstance1,serviceInstance2
            }

        }
    }

    views {
        deployment * "Example" {
            include *
            autolayout
        }
    }
}
dgutson commented 1 year ago

Thanks @pkunze , this is not exactly what I mean. What I want is a mean of reuse, that's why I bring inheritance (as in object oriented design), and avoid copy/paste. I don't want to create artificial deploymentNodes because of this.

The only way I found so far is by !including files, but I don't want either to bloat the file system with small files.

dgutson commented 1 year ago

@simonbrowndotje I'd like either !ref or extends for cases like this:

workspace {

    model {
        ss1 = softwareSystem "Software System" {
            database = container "Database"
            api = container "Service API" {
                -> database "Uses"
            }
        }

        ss2 = !ref ss1 {    # or extends ss1
            db2 = container "db2"
        }
    }

    views {
        container ss2 {
            include *
            autolayout
        }
    }
}
dgutson commented 1 year ago

Note: I specially would like to extend deployment environments within the same model, despite I think the feature should be useful for any type of entity.

simonbrowndotje commented 1 year ago

Closing as not planned ... I'd recommend building yourself a DSL plugin to clone deployment environments, as that's probably much more straightforward than modifying the DSL and parser.

dgutson commented 1 year ago

But an entity is a closed object, once cloned I won't be able to extend it (eg append more containerinstances), will I? The only solution I can think is, given two entities, implement a union operator and obtain a new resulting one. What do you think?

dgutson commented 1 year ago

We will try to implement the originally requested feature as a plugin:

workspace {

    model {
        ss1 = softwareSystem "Software System" {
            database = container "Database"
            api = container "Service API" {
                -> database "Uses"
            }
        }

        ss2 = softwareSystem "s2" { 
            db2 = container "db2"
        }
    }

     !plugin "extend" {
         base "ss1"
         der "ss2"
     }

    views {
        container ss2 {
            include *
            autolayout
        }
    }
}

(Don't remember if the syntax is correct). I will report back.