Posted on: April 14, 2023 06:57 PM
Posted by: Renato
Categories: Structurizr Diagramas c4 c4-models Docker
Views: 1121
Diagramas de Software - Modelos C4 com Structurizr
9 minutos de leitura
Visão geral
Em minha última postagem no blog , exploramos diferentes tipos de diagramas que podemos usar para descrever um sistema de software. Comparamos a criação desses diagramas tanto no Mermaid quanto no PlantUML. Um dos diagramas que mencionei foi do C4 Models . Nesta postagem do blog, vamos nos aprofundar nos modelos C4 e examinar algumas das razões pelas quais eles são tão eficazes. Também veremos a diferença entre modelagem e diagramas .
Meu git para quem quiser baixar:
- https://gitlab.com/cpdrenato/exemplo-structurizr-docker
Modelos C4
A melhor maneira de explicar o conceito é pensar em como usamos o Google Maps. Quando estamos explorando uma área no Google Maps, muitas vezes começamos a diminuir o zoom para nos ajudar a obter contexto. Uma vez que encontramos a área áspera, estamos interessados em poder ampliar para obter um pouco mais de detalhes. A partir daí podemos encontrar uma outra área de interesse onde podemos ampliar ainda mais e obter ainda mais detalhes. Os modelos C4 funcionam da mesma maneira. Existem 4 níveis de diagramas, com cada nível fornecendo mais detalhes do que o anterior.
Nível 1: Diagrama de Contexto do Sistema
Este nível é o mais reduzido. O diagrama concentra-se em atores (clientes com papéis específicos) e sistemas. Os sistemas podem ser aqueles que controlamos ou podem ser sistemas externos dos quais dependemos. O sistema no qual este diagrama se concentra é aquele que estamos construindo ou pelo qual somos responsáveis. Ele conterá uma ou mais partes móveis (ou seja, contêineres). Esta é a nossa visão geral que não fornece muitos detalhes, mas ajuda a fornecer contexto.
Nível 2: diagrama de contêiner
Este é o próximo nível de zoom, que geralmente é o mais interessante. Os contêineres geralmente são qualquer coisa que hospeda código ou armazena dados. São exemplos de contêineres:
- Aplicativos de página única
- servidores web
- Máquinas virtuais
- Funções sem servidor
- bancos de dados
- armazenamento de blobs
- Barramentos de mensagem
Os diagramas de contêiner ainda mostram atores e também podem fazer referência a sistemas externos.
Nível 3: diagrama de componentes
O próximo nível de zoom é o diagrama de componentes. Isso mostra os principais blocos de construção estruturais de seu aplicativo e suas interações. Este não é um mapeamento 1-1 de seu aplicativo, mas geralmente uma visão conceitual de seu aplicativo. O termo componente é vago aqui. Pode significar um componente React ou Blazor. Mas também pode representar um controlador ou serviço que contém a lógica de negócios.
Nível 4: diagrama de código
O nível mais profundo de zoom é o diagrama de código. Em contraste com o diagrama de componentes acima, este é um mapeamento 1-1 com seu código. Embora esse diagrama exista, muitas vezes não é usado, pois o código apresenta uma imagem muito semelhante.
Diagramas suplementares
Além dos 4 diagramas acima, há mais alguns dignos de nota:
- Diagrama do cenário do sistema: o diagrama de contexto fornece uma visão de um único sistema de software. O System Landscape Diagram mostra a coleção de todos os sistemas de software. Podemos considerar isso um diagrama empresarial .
- Diagrama de implantação: ao implantar na infraestrutura, geralmente há serviços adicionais, como rede, CDNs, gateways, balanceadores de carga, grupos de recursos. Eles são considerados separados dos contêineres, mas ainda precisam ser considerados para implantações. Podemos considerar isso semelhante a um diagrama de arquitetura de nuvem .
- Diagrama dinâmico: pode ser uma versão reduzida de qualquer um dos diagramas acima para mostrar um recurso ou caso de uso específico. Você pode pensar nisso como sendo semelhante a um diagrama de seqüência .
Modelagem x Diagramação
Agora que abordamos os diferentes tipos de diagramas C4, há mais um conceito importante a abordar - modelagem versus diagramas .
Modelagem é o ato de descrever seu sistema. Podemos descrever os atores, sistemas, contêineres, componentes e seus relacionamentos. Mas a modelagem pode ser vista como os dados sem a apresentação. A modelagem não determina como representaremos esses dados.
A diagramação é essencialmente desenhar imagens para representar visualmente nosso modelo.
Essa distinção se torna poderosa quando podemos criar um único modelo e reutilizar diferentes elementos dele em diferentes diagramas. Isso nos permite aplicar o princípio DRY aos nossos diagramas.
Estruturar
Até agora, cobrimos muita teoria. Como são esses diagramas e quais ferramentas podemos usar? Minha última postagem no blog mostrou uma breve olhada no uso de PlantUML e Mermaid. O PlantUML fez um trabalho razoável, mas o Mermaid infelizmente não tinha brilho.
Entre - Estruturar! 🙌
Structurizr é uma ferramenta incrível que nos permite modelar um sistema usando um DSL personalizado. Podemos então usar esse modelo para criar vários diagramas.
Configurar
Existem algumas versões diferentes do Structurizr . Para nossos propósitos, o Structurizr Lite funciona de forma fantástica. Isso pode ser instalado localmente via docker (recomendado) ou inicialização por mola.
Para instalar via docker, primeiro precisamos extrair a imagem do docker hub:
docker pull structurizr/lite
Em seguida, precisamos executar o contêiner expondo uma porta no host e um caminho para nosso diretório de trabalho. Por exemplo:
docker run -it --rm -p 8080:8080 -v C:Code/FolderName/usr/local/structurizr structurizr/lite
Uma ressalva a ser observada é que uma imagem do docker só pode apontar para um diretório de trabalho. Portanto, se você tiver vários espaços de trabalho em diretórios diferentes, precisará ter um contêiner em execução para cada um deles. Podemos contornar isso escrevendo um script auxiliar para a criação do contêiner e gerenciá-los por meio do docker desktop.
O script a seguir inicia um contêiner e requer um hostPort, hostFolder e containerName
param(
[Parameter(Mandatory)]
[int]$hostPort,
[Parameter(Mandatory)]
[string]$hostFolder,
[Parameter(Mandatory)]
[string]$containerName
)
docker run -d --name "structurizr-$containerName" -p $hostPort":8080" -v $hostFolder":/usr/local/structurizr" structurizr/lite
Isso nos permite ativar facilmente o conteúdo do Structurizr. Após a criação do contêiner, podemos visualizá-lo, inspecioná-lo e gerenciá-lo por meio do docker desktop:
Exemplos
Portanto, agora que temos nosso contêiner em execução, podemos começar a trabalhar em nosso modelo e diagramas.
Modelo
Vamos usar um exemplo de um sistema de comércio eletrônico. Em tal sistema, teríamos um modelo que se parece com:
model {
enterprise {
customerPerson = person "Customer"
warehousePerson = person "Warehouse Staff"
ecommerceSystem = softwareSystem "E-Commerce" {
storeContainer = container "Store SPA" "E-Commerce Store" "React" "Browser,Microsoft Azure - Static Apps,Azure"
stockContainer = container "Stock Management SPA" "Order fufillment, stock management, order dispatch" "React" "Browser,Microsoft Azure - Static Apps,Azure"
dbContainer = container "Database" "Customers, Orders, Payments" "SQL Server" "Database,Microsoft Azure - Azure SQL,Azure"
apiContainer = container "API" "Backend" "ASP.NET Core" "Microsoft Azure - App Services,Azure" {
group "Web Layer" {
policyComp = component "Authorization Policy" "Authentication and authorization" "ASP.NET Core"
controllerComp = component "API Controller" "Requests, responses, routing and serialisation" "ASP.NET Core"
mediatrComp = component "MediatR" "Provides decoupling of requests and handlers" "MediatR"
}
group "Application Layer" {
commandHandlerComp = component "Command Handler" "Business logic for changing state and triggering events" "MediatR request handler"
queryHandlerComp = component "Query Handler" "Business logic for retrieving data" "MediatR request handler"
commandValidatorComp = component "Command Validator" "Business validation prior to changing state" "Fluent Validation"
}
group "Infrastructure Layer" {
dbContextComp = component "DB Context" "ORM - Maps linq queries to the data store" "Entity Framework Core"
}
group "Domain Layer" {
domainModelComp = component "Model" "Domain models" "poco classes"
}
}
}
emailSystem = softwareSystem "Email System" "Sendgrid" "External"
# relationships between people and software systems
customerPerson -> storeContainer "Placers Orders" "https"
warehousePerson -> stockContainer "Dispatches Orders" "https"
apiContainer -> emailSystem "Trigger emails" "https"
emailSystem -> customerPerson "Delivers emails" "https"
# relationships to/from containers
stockContainer -> apiContainer "uses" "https"
storeContainer -> apiContainer "uses" "https"
apiContainer -> dbContainer "persists data" "https"
# relationships to/from components
dbContextComp -> dbContainer "stores and retrieves data"
storeContainer -> controllerComp "calls"
stockContainer -> controllerComp "calls"
controllerComp -> policyComp "authenticated and authorized by"
controllerComp -> mediatrComp "sends queries & commands to"
mediatrComp -> queryHandlerComp "sends query to"
mediatrComp -> commandValidatorComp "sends command to"
commandValidatorComp -> commandHandlerComp "passes command to"
queryHandlerComp -> dbContextComp "Gets data from"
commandHandlerComp -> dbContextComp "Update data in"
dbContextComp -> domainModelComp "contains collections of"
}
Para o DSL completo, veja aqui .
Há um pouco acontecendo aqui, mas a sintaxe do DSL é bastante direta e mapeia bem os conceitos explicados acima. Vamos examinar mais de perto a sintaxe de um contêiner.
Os contêineres são definidos com o formato:
[variableName] container = [name] [description] [technology] [tags]
variableName
: isso é usado para se referir ao contêiner em outro lugar no modelo (por exemplo, em relacionamentos)name
: o nome do nosso contêinerdescription
: uma descrição do que nosso contêiner é responsáveltechnology
: a principal tecnologia do contêiner (por exemplo, ASP.NET Core, SQL Server, Service Bus, etc)tags
: tags são opcionais, mas podem ser usadas para alterar a aparência do contêiner. Alguns temas dependem deles.
Os relacionamentos são definidos com o formato:
[entityFrom] -> [entityTo] [relationship] [transport]
entityFrom/entityTo
: as entidades entre as quais esta relação estárelationship
: uma ação para descrever o relacionamentotransport
: como a comunicação acontece (por exemplo, HTTPS, gRPC, WebSockets)
Contexto
Agora que temos nosso modelo, os diagramas se tornam triviais. Um diagrama de contexto pode ser renderizado com:
systemContext ecommerceSystem "Context" {
include * emailSystem
autoLayout
}
A visão acima nos dará este diagrama:
Recipiente
Um diagrama de contêiner pode ser gerado com esta exibição:
container ecommerceSystem "Container" {
include *
}
Que gera este diagrama:
Componente
Um diagrama de componentes pode ser gerado com esta visualização:
component apiContainer "Component" {
include * customerPerson warehousePerson
autoLayout
}
Que gera este diagrama:
Recursos Adicionais de Estruturação
Além de gerar diagramas a partir de modelos, o Structurizr também pode ser usado para documentar arquiteturas. Faz isso disponibilizando uma área para documentação e outra para ADR's (Architectural Decision Records).
Resumo
Neste post vimos uma introdução aos modelos C4 e as diferentes notações que ele fornece. Vimos como podemos começar a diminuir o zoom para obter mais detalhes e, em seguida, aumentar o zoom nos sistemas de interesse para obter mais detalhes. Isso nos ajuda a entender os sistemas novos e existentes. Examinamos as diferenças entre modelagem e diagramação e vimos que a principal vantagem disso é que nos permite manter nossos diagramas DRY.
Também vimos como o Structurizr fornece uma DSL que podemos usar para gerar modelos, diagramas, documentação e ADRs.
Também vimos que, em comparação com Mermaid e PlantUML , Structurizr é a opção premium para gerar diagramas C4 IMHO.
Vá lá e estude com os modelos C4! 😎
Referências
- Modelo C4
- Diagramas como Código 2.0
- Estruturar
- Estruturar Primeiros passos
- Referência Estrutural
- Código fonte
- https://www.dandoescode.com/blog/c4-models-with-structurizr
- https://structurizr.com/dsl
- https://github.com/cassiobotaro/modeloC4
- https://www.youtube.com/watch?v=eqIszmj0pEQ
Donate to Site
Renato
Developer