structurizr / dsl

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

physical deployment forcing logical structure #196

Closed dgutson closed 1 year ago

dgutson commented 1 year ago

Consider the situation where there is a microservice with a database. This database is only used by this microservice, and the microservice cannot exist without the db. The two obvious patterns are to ship (deploy) the microservice with the database in the same container, or have a shared database among the microservices. At logical level, it shouldn't matter (should it?). However, because

In the C4 model, components are not separately deployable units

I am forced to represent the logical model according to how I ship the physical model. In logical terms, the microservice is encapsulated, therefore I would like to put code and data together in the same container containing two components : code and DB. But because the deployment model is the "shared database" one, I cannot follow the logical encapsulation. One could argue that this is not just a logical/deployment mismatch but a different pattern at logical levels. So, @simonbrowndotje what's your adivse here? I would be happy if both worlds (logical model and deployment) could get disentangled and therefore the logical's containers are different from the containerInstances, allowing containerInstances to just contain components. In my example, have two containerInstance, one for the service, one for the shared DB.

simonbrowndotje commented 1 year ago

This is a question about the C4 model rather than the DSL.

At logical level, it shouldn't matter (should it?).

It should ... software architecture diagrams need to reflect reality.

In logical terms, the microservice is encapsulated, therefore I would like to put code and data together in the same container containing two components : code and DB.

Assuming that you're not using an in-memory/embedded database (e.g. H2, HSQLDB , etc) ... logically you might have one "microservice", but physically you still have two C4 containers. For example; an API endpoint (code) and a database schema (data). How you deploy those two C4 containers is a different question, as illustrated by this example DSL and the example diagrams below:

workspace {

    !identifiers hierarchical

    model {
        serviceX = softwareSystem "Service X" {
            api = container "API X" {
                technology "Java/Spring Boot"
            }
            db = container "Database Schema X" {
                technology "MySQL"
                api -> this
            }
        }

        serviceY = softwareSystem "Service Y" {
            api = container "API Y" {
                technology "Java/Spring Boot"
            }
            db = container "Database Schema Y" {
                technology "MySQL"
                api -> this
            }
        }

        example1 = deploymentEnvironment "Example 1" {
            deploymentNode "Server" {
                deploymentNode "Docker Container - X" {
                    containerInstance serviceX.api
                    deploymentNode "MySQL" {
                        containerInstance serviceX.db
                    }
                }
                deploymentNode "Docker Container - Y" {
                    containerInstance serviceY.api
                    deploymentNode "MySQL" {
                        containerInstance serviceY.db
                    }
                }
            }
        }

        example2 = deploymentEnvironment "Example 2" {
            deploymentNode "Server" {
                deploymentNode "Docker Container - X" {
                    containerInstance serviceX.api
                }
                deploymentNode "Docker Container - Y" {
                    containerInstance serviceY.api
                }

                deploymentNode "Docker Container - DB" {
                    deploymentNode "MySQL" {
                        containerInstance serviceX.db
                        containerInstance serviceY.db
                    }
                }
            }
        }
    }

    views {
        deployment * example1 "Example1" {
            include *
            autoLayout lr
        }

        deployment * example2 "Example2" {
            include *
            autoLayout lr
        }
    }

}

Separate deployments

Here, service X and Y are deployed in separate Docker containers.

image

Co-located DB schema deployments

And here the DB schemas for service X and Y are deployed on the same MySQL database server.

image

You could also have multiple services sharing a single DB schema, but that's seen as bad practice. 😀

Closing this issue since it's not about the DSL, but feel free to join the Slack group for further discussion.

dgutson commented 1 year ago

Interesting nesting (first case):

Just to be sure, could you please include here the code for the second case too, the Co-located one?

dgutson commented 1 year ago

Sorry, it is the deploymentEnvironment "Example 2". Still processing. Thanks.