Iniciando com C4 Model

Simon Brown – Criador do C4 Model

Ele foi desenvolvido por Simon Brown, um arquiteto de software e consultor, e é amplamente utilizado por equipes de desenvolvimento de software em todo o mundo.

Para começar a usar o C4 Model, você precisará de uma ferramenta de modelagem de arquitetura, como o Microsoft Visio ou o PlantUML. Recomendo usar o PlantUML e integrar com o VSCode através de sua extensão. Em breve, vou elaborar um tutorial de uso do PlantUML com o VSCode, mas por enquanto, você pode visualizar os diagramas no servidor do PlantUML no link abaixo:

https://www.plantuml.com/plantuml

Isto posto, vamos seguir os seguintes passos:

Defina o escopo do sistema: antes de começar a modelar a arquitetura, é importante definir o escopo do sistema que você está trabalhando. Isso ajudará a determinar os componentes que devem ser incluídos no modelo e a orientar o nível de detalhe que será necessário.

Crie um diagrama de contexto: o primeiro nível do C4 Model é o diagrama de contexto, que deve mostrar os principais componentes externos ao sistema, como clientes, fornecedores e usuários finais, bem como o contexto em que o sistema será utilizado.

Crie um diagrama de contêiner: o segundo nível do C4 Model é o diagrama de contêiner, que deve mostrar os principais componentes do sistema, como servidores, banco de dados e aplicativos, bem como as dependências entre eles.

Adicione seus diagramas de classes à documentação do projeto para aumentar o nível de detalhamento no quarto nível do modelo C4.

O C4 Model é composto por quatro níveis hierárquicos:

Nível de contexto

Neste nível, são mostrados os principais componentes externos ao sistema, como clientes, fornecedores e usuários finais, bem como o contexto em que o sistema será utilizado.

@startuml C4_Context
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml

LAYOUT_LEFT_RIGHT()

Person(customer, "Cliente", "Cliente de uma concessionaria")
Person(dealer, "Concessionaria", "Concessionaria de veiculos")
Person(supplier, "Fornecedor", "Fornecedor de veiculos")

System_Boundary(system_app, "Aplicação Web") {
    System(web_app, "Sistema de Anúncios", "Exibe lista de veículos disponíveis para venda, possibilitando a escolha de um veículo e a compra do mesmo.")
}

Rel(customer, web_app, "Escolhe um veículo", "HTTP")
Rel(web_app, dealer, "Notifica", "E-mail")
Rel_L(dealer, supplier, "Comunica", "E-mail")
Rel(supplier, dealer, "Confirma venda", "E-mail")
Rel(web_app, customer, "Notifica", "E-mail")
@enduml

Comece importando a biblioteca de Context do C4 Model:
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml

' Indica a direção dos blocos no diagrama:
LAYOUT_LEFT_RIGHT()
' Cria as pessoas (atores) do diagrama:
Person(customer, "Cliente", "Cliente de uma concessionaria")
Person(dealer, "Concessionaria", "Concessionaria de veiculos")
Person(supplier, "Fornecedor", "Fornecedor de veiculos")
' Defina os limites do sistema:
System_Boundary(system_app, "Aplicação Web") {
    System(web_app, "Sistema de Anúncios", "Exibe lista de veículos disponíveis para venda, possibilitando a escolha de um veículo e a compra do mesmo.")
}
' Defina os relacionamentos e ações de cada elemento:
Rel(customer, web_app, "Escolhe um veículo", "HTTP")
Rel(web_app, dealer, "Notifica", "E-mail")
Rel_L(dealer, supplier, "Comunica", "E-mail")
Rel(supplier, dealer, "Confirma venda", "E-mail")
Rel(web_app, customer, "Notifica", "E-mail")

' Rel: Define um relacionamento padrao
' Rel_L: Força um elemento fique à ESQUERDA do elemento relacionado
' Rel_R: Força um elemento fique à DIREITA do elemento relacionado

Nível de contêiner

Neste nível, são mostrados os principais componentes do sistema, como servidores, banco de dados e aplicativos, bem como as dependências entre eles.

@startuml C4_Container
!include  https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

LAYOUT_LEFT_RIGHT()

Person(customer, "Cliente", "Cliente de uma concessionaria")
Person(dealer, "Concessionaria", "Concessionaria de veiculos")
Person(supplier, "Fornecedor", "Fornecedor de veiculos")

System_Boundary(advertising, "Sistema de Anúncios") {
    Container(next_app, "Sistema de Anúncios", "NextJS", "Permite ao cliente visualizar e enviar proposta de compra dos veículos")
}

Rel(dealer, supplier, "Compra veiculo", "HTTP")
Rel(customer, next_app, "Pesquisa veiculo", "HTTP")
Rel(dealer, next_app, "Pesquisa veiculo", "HTTP")
Rel(supplier, next_app, "Pesquisa veiculo", "HTTP")
Rel(next_app, customer, "Mostra veiculo", "HTTP")
Rel(next_app, dealer, "Mostra veiculo", "HTTP")
Rel(next_app, supplier, "Mostra veiculo", "HTTP")
@enduml

Nível de componente

Neste nível, são mostrados os componentes mais detalhados do sistema, incluindo classes, módulos e pacotes de software.

@startuml C4_Component
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

' Diagrama c4 model de componentes
' para mais informações, veja https://c4model.com/

Person(customer, "Cliente", "Cliente de uma concessionaria")
Person(dealer, "Concessionaria", "Concessionaria de veiculos")
Person(supplier, "Fornecedor", "Fornecedor de veiculos")

System_Boundary(car_dealership, "Concessionaria de Veiculos") {
    Container(web_app, "Aplicacao Web", "Java, Spring MVC", "Exibe a lista de veiculos")
    Container(rest_api, "API REST", "Java, Spring MVC", "Exibe a lista de veiculos")
    Container(database, "Banco de Dados", "PostgreSQL", "Armazena os dados dos veiculos")
}

Rel(customer, web_app, "Visualiza a lista de veiculos")
Rel(customer, rest_api, "Visualiza a lista de veiculos")
Rel(dealer, web_app, "Visualiza a lista de veiculos")
Rel(dealer, rest_api, "Visualiza a lista de veiculos")
Rel(supplier, database, "Armazena os dados dos veiculos")

@enduml

Nível de classe

Neste nível, são mostrados os detalhes da implementação do código, como as interfaces e as classes concretas. Os detalhes mais profundos podem ser adicionados à medida que o projeto for se desenvolvendo. Num primeiro momento, apenas o nome das classes e seus relacionamentos já é suficiente. Pra esse exemplo, vou adicionar um diagrama de classes com as propriedades e métodos para passar uma idéia mais completa.

@startuml Class_Diagram

title Diagrama de Classes

' create a package for the classes
package "Classes" {
    class Customer
    class Dealer
    class Supplier
    class Vehicle
    class Car
    class Truck
    class Motorcycle
}

class Customer {
    -String name
    -String address
    -String phone
    -String email
    +String getName()
    +String getAddress()
    +String getPhone()
    +String getEmail()
    +void setName(String name)
    +void setAddress(String address)
    +void setPhone(String phone)
    +void setEmail(String email)
}

class Dealer {
    -String name
    -String address
    -String phone
    -String email
    +String getName()
    +String getAddress()
    +String getPhone()
    +String getEmail()
    +void setName(String name)
    +void setAddress(String address)
    +void setPhone(String phone)
    +void setEmail(String email)
}

class Supplier {
    -String name
    -String address
    -String phone
    -String email
    +String getName()
    +String getAddress()
    +String getPhone()
    +String getEmail()
    +void setName(String name)
    +void setAddress(String address)
    +void setPhone(String phone)
    +void setEmail(String email)
}

class Vehicle {
    -String make
    -String model
    -String year
    -String color
    -String vin
    -String licensePlate
    -String mileage
    -String price
    +String getMake()
    +String getModel()
    +String getYear()
    +String getColor()
    +String getVin()
    +String getLicensePlate()
    +String getMileage()
    +String getPrice()
    +void setMake(String make)
    +void setModel(String model)
    +void setYear(String year)
    +void setColor(String color)
    +void setVin(String vin)
    +void setLicensePlate(String licensePlate)
    +void setMileage(String mileage)
    +void setPrice(String price)
}

class Car extends Vehicle {
    -String engine
    -String transmission
    -String fuelType
    -String driveType
    -String bodyStyle
    -String interiorColor
    -String exteriorColor
    -String mileage
    -String price
    +String getEngine()
    +String getTransmission()
    +String getFuelType()
    +String getDriveType()
    +String getBodyStyle()
    +String getInteriorColor()
    +String getExteriorColor()
    +String getMileage()
    +String getPrice()
    +void setEngine(String engine)
    +void setTransmission(String transmission)
    +void setFuelType(String fuelType)
    +void setDriveType(String driveType)
    +void setBodyStyle(String bodyStyle)
    +void setInteriorColor(String interiorColor)
    +void setExteriorColor(String exteriorColor)
    +void setMileage(String mileage)
    +void setPrice(String price)
}

class Truck extends Vehicle {
    -String engine
    -String transmission
    -String fuelType
    -String driveType
    -String bodyStyle
    -String interiorColor
    -String exteriorColor
    -String mileage
    -String price
    +String getEngine()
    +String getTransmission()
    +String getFuelType()
    +String getDriveType()
    +String getBodyStyle()
    +String getInteriorColor()
    +String getExteriorColor()
    +String getMileage()
    +String getPrice()
    +void setEngine(String engine)
    +void setTransmission(String transmission)
    +void setFuelType(String fuelType)
    +void setDriveType(String driveType)
    +void setBodyStyle(String bodyStyle)
    +void setInteriorColor(String interiorColor)
    +void setExteriorColor(String exteriorColor)
    +void setMileage(String mileage)
    +void setPrice(String price)
}

class Motorcycle extends Vehicle {
    -String engine
    -String transmission
    -String fuelType
    -String driveType
    -String bodyStyle
    -String interiorColor
    -String exteriorColor
    -String mileage
    -String price
    +String getEngine()
    +String getTransmission()
    +String getFuelType()
    +String getDriveType()
    +String getBodyStyle()
    +String getInteriorColor()
    +String getExteriorColor()
    +String getMileage()
    +String getPrice()
    +void setEngine(String engine)
    +void setTransmission(String transmission)
    +void setFuelType(String fuelType)
    +void setDriveType(String driveType)
    +void setBodyStyle(String bodyStyle)
    +void setInteriorColor(String interiorColor)
    +void setExteriorColor(String exteriorColor)
    +void setMileage(String mileage)
    +void setPrice(String price)
}

Customer "1" -- "1..*" Vehicle : compra
Dealer "1" -- "1..*" Vehicle : gerencia
Dealer "1" -- "1..*" Supplier : comunica
Supplier "1" -- "1..*" Vehicle : fornece
Vehicle "1" -- "1..*" Car
Vehicle "1" -- "1..*" Truck
Vehicle "1" -- "1..*" Motorcycle
@enduml

Bom, pra começar já temos um bom material!

Documentar a arquitetura de um software é importante por diversas razões. Algumas dessas razões incluem:

Comunicação: A documentação da arquitetura permite que os membros do time compreendam como o software foi projetado e como os componentes se relacionam uns com os outros. Isso facilita a comunicação e a colaboração entre os membros do time, pois todos estão trabalhando a partir de uma base comum de conhecimento.

Manutenção: A documentação da arquitetura também é útil para a manutenção do software, pois permite que novos desenvolvedores entendam rapidamente como o software foi projetado e como ele funciona. Isso pode tornar mais fácil identificar problemas e implementar soluções.

Evolução: A documentação da arquitetura também é importante para o planejamento de futuras alterações e evoluções no software. Isso permite que o time tenha uma visão clara de como o software está atualmente e como ele pode ser modificado de maneira a manter a integridade e a qualidade do software.

Utilizar o C4 Model para documentar a arquitetura de um software pode ajudar a garantir que a documentação seja completa e precisa, e pode ser uma ferramenta útil para comunicar a arquitetura do software aos membros do time e a outros stakeholders.

Por enquanto, é isso! Fique ligado que em breve teremos mais artigos sobre arquitetura de software, documentação e muito mais.

Vlw :=)

Facebook
Twitter
LinkedIn
A Emoção no Desenvolvimento de Software

O Paradoxo Ágil: Quando Correr Mais Significa Entregar Menos

Velocidade sem qualidade é só combustível pro retrabalho. Neste artigo eu destrincho, sem gourmetização, o paradoxo que assombra times ágeis: entregar rápido sem transformar o backlog em um cemitério de bugs e dívidas técnicas. Como arquiteto nas trincheiras, explico por que agilidade não é sinônimo de pressa e mostro práticas reais — nada de hype — para estabilizar fluxo, proteger qualidade e parar de brincar de apostar contra a própria equipe.

DevOps

Implantação Contínua com Kubernetes: O Campo Minado que Ninguém Te Conta

Kubernetes não é o vilão — o problema é fingir que implantação contínua vira mágica só porque você criou meia dúzia de YAMLs. Neste artigo, explico onde os times realmente se queimam, por que pipelines quebram no meio do caminho, e quais decisões de arquitetura viram dívidas técnicas silenciosas. Sem gourmetização, sem hype: só o que realmente importa para rodar CD de verdade em produção.

Refatoração de código

Quando a Refatoração Vira Areia Movediça em Arquiteturas de Microserviços

Refatorar é importante, mas transformar isso em rotina cega pode virar um buraco negro em ambientes distribuídos. Neste artigo eu, Rei Nascimento, mostro por que a refatoração contínua pode corroer equipes, criar microserviços frágeis e desacelerar escala. Vamos direto ao ponto, sem gourmetização.

7 comentários em “Iniciando com C4 Model”

  1. Dá pra usar o C4 Model junto com ferramentas tipo o PlantUML pra gerar os diagramas direto do código. Facilita muito a manutenção da documentação.

  2. Dá pra usar o C4 Model junto com ferramentas tipo o PlantUML ou Mermaid pra gerar os diagramas automaticamente, facilita muito o dia a dia na hora de manter a documentação.

  3. maria_lima

    Esse modelo C4 realmente salvou meu dia. A gente estava apanhando pra fazer uma doc consistente na sprint, e a documentação oficial é bem complexa nessa parte.

  4. Dá pra usar o PlantUML ou o Mermaid pra gerar os diagramas do C4 Model de forma automática, facilita muito a manutenção da doc.

  5. Para criar os diagramas do C4 Model, o PlantUML junto com a extensão do VS Code facilita muito. Ajuda a manter a documentação no código.

  6. C4 Model é ótimo para padronizar a documentação. Dá pra usar o Structurizr junto com ele pra gerar os diagramas de forma mais eficiente também, ajuda demais no dia a dia.

  7. Para quem está começando com C4 Model, é bom lembrar que dá pra integrar com ferramentas como Structurizr para gerar os diagramas automaticamente.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *