Do not speak Portuguese? Translate this site with Google or Bing Translator
Modelos C4 com Structurizr

Posted on: April 14, 2023 06:57 PM

Posted by: Renato

Views: 792

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:

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êiner
  • description: uma descrição do que nosso contêiner é responsável
  • technology: 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 relacionamento
  • transport: 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:

Diagrama de Contexto

Recipiente

Um diagrama de contêiner pode ser gerado com esta exibição:

container ecommerceSystem "Container" {
    include *
}

Que gera este diagrama:

Diagrama do Contêiner

Componente

Um diagrama de componentes pode ser gerado com esta visualização:

component apiContainer "Component" {
    include * customerPerson warehousePerson
    autoLayout
}

Que gera este diagrama:

Diagrama de componentes

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



2

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 0 Comments

No comments yet! Be the first to comment

Blog Search


Categories

OUTROS (15) Variados (109) PHP (127) Laravel (154) Black Hat (3) front-end (28) linux (110) postgresql (37) Docker (25) rest (5) soap (1) webservice (6) October (1) CMS (2) node (7) backend (13) ubuntu (54) devops (25) nodejs (5) npm (2) nvm (1) git (8) firefox (1) react (6) reactnative (5) collections (1) javascript (6) reactjs (7) yarn (0) adb (1) Solid (2) blade (3) models (1) controllers (0) log (0) html (2) hardware (3) aws (14) Transcribe (2) transcription (1) google (4) ibm (1) nuance (1) PHP Swoole (5) mysql (28) macox (4) flutter (1) symfony (1) cor (1) colors (2) homeOffice (2) jobs (3) imagick (2) ec2 (1) sw (1) websocket (1) markdown (1) ckeditor (1) tecnologia (14) faceapp (1) eloquent (14) query (3) sql (36) ddd (3) nginx (9) apache (4) certbot (1) lets-encrypt (3) debian (11) liquid (1) magento (2) ruby (1) LETSENCRYPT (1) Fibonacci (1) wine (1) transaction (1) pendrive (1) boot (1) usb (1) prf (1) policia (2) federal (1) lucena (1) mongodb (4) paypal (1) payment (1) zend (1) vim (3) ciencia (6) js (1) nosql (1) java (1) JasperReports (1) phpjasper (1) covid19 (1) saude (1) athena (1) cinnamon (1) phpunit (2) binaural (1) mysqli (3) database (37) windows (6) vala (1) json (2) oracle (1) mariadb (4) dev (12) webdev (24) s3 (4) storage (1) kitematic (1) gnome (2) web (2) intel (3) piada (1) cron (2) dba (13) lumen (1) ffmpeg (2) android (2) aplicativo (1) fedora (2) shell (4) bash (3) script (3) lider (1) htm (1) csv (1) dropbox (1) db (3) combustivel (2) haru (1) presenter (1) gasolina (1) MeioAmbiente (1) Grunt (1) biologia (1) programming (21) performance (3) brain (1) smartphones (1) telefonia (1) privacidade (1) opensource (3) microg (1) iode (1) ssh (3) zsh (2) terminal (3) dracula (1) spaceship (1) mac (2) idiomas (1) laptop (2) developer (36) api (4) data (1) matematica (1) seguranca (2) 100DaysOfCode (9) hotfix (1) documentation (1) laravelphp (9) RabbitMQ (1) Elasticsearch (1) redis (2) Raspberry (4) Padrao de design (4) JQuery (1) angularjs (4) Dicas (36) Kubernetes (2) vscode (2) backup (1) angular (3) servers (2) pipelines (1) AppSec (1) DevSecOps (4) rust (1) RustLang (1) Mozilla (1) algoritimo (1) sqlite (1) Passport (1) jwt (4) security (2) translate (1) kube (1) iot (1) politica (2) bolsonaro (1) flow (1) podcast (1) Brasil (1) containers (2) traefik (1) networking (1) host (1) POO (2) microservices (2) bug (1) cqrs (1) arquitetura (2) Architecture (3) sail (3) militar (1) artigo (1) economia (1) forcas armadas (1) ffaa (1) autenticacao (1) autorizacao (2) authentication (4) authorization (2) NoCookies (1) wsl (4) memcached (1) macos (2) unix (2) kali-linux (1) linux-tools (5) apple (1) noticias (2) composer (1) rancher (1) k8s (1) escopos (1) orm (1) jenkins (4) github (5) gitlab (3) queue (1) Passwordless (1) sonarqube (1) phpswoole (1) laraveloctane (1) Swoole (1) Swoole (1) octane (1) Structurizr (1) Diagramas (1) c4 (1) c4-models (1) compactar (1) compression (1) messaging (1) restfull (1) eventdrive (1) services (1) http (1) Monolith (1) microservice (1) historia (1) educacao (1) cavalotroia (1) OOD (0) odd (1) chatgpt (1) openai (3) vicuna (1) llama (1) gpt (1) transformers (1) pytorch (1) tensorflow (1) akitando (1) ia (1) nvidia (1) agi (1) guard (1) multiple_authen (2) rpi (1) auth (1) auth (1) auth (1) auth (1) Oh My Zsh (1) Manjaro (1) BigLinux (2) ArchLinux (1) Migration (1) Error (1) Monitor (1) Filament (1) LaravelFilament (1) replication (1) phpfpm (1) cache (1) vpn (1) l2tp (1) zorin-os (1) optimization (1) scheduling (1) monitoring (1) linkedin (1) community (1) inteligencia-artificial (2) wsl2 (1) maps (1) API_KEY_GOOGLE_MAPS (1)

New Articles



Get Latest Updates by Email