Por que representar a arquitetura de uma aplicação em diagramas?
Tags: c4, components, architecture, plantuml
Published: 2023-11-16 00:33:58

Você já pediu a um desenvolvedor para ele explicar como funciona o software que ele desenvolveu/desenvolve? Provavelmente a resposta vai conter algum rabisco de caixinhas e setas, na tentativa de representar visualmente como os componentes do software em questão se comunicam.

Na industria de software existem algumas notações conhecidas para representar a arquitetura de um software, como Linguagem de Modelagem Unificada (UML), o ArchiMate e o SysML. Porém na tentativa de "agilizar" a entrega, muitas equipes descartam essas notações e utilizam "caixinhas e setas" mais simples, na tentativa de representar a arquitetura do software. Mas será que vale descartar essas notações? Será que as equipes de desenvolvimento ainda conseguem representar bem a arquitetua?

## Diagramas C4

O modelo C4 foi criado como uma forma de ajudar as equipes de desenvolvimento de software a descrever e comunicar a arquitetura de software, tanto durante sessões iniciais de design quanto ao documentar retrospectivamente uma base de código existente. Com ele podemos representar em diversos níveis de detalhe como uma aplicação funciona. 
O modelo C4 sugere 4 níveis visões de diagramas para a representação de um software:

- Nível 1, System Context: Visão de como o a aplicação se comunica com mundo ao seu redor.
- Nível 2, Container: Amplia o escopo da aplicação, mostrando os blocos de construção técnicos de alto nível.
- Nível 3, Component: Amplia um contêiner individual, mostrando os componentes dentro dele.
- Nível 4, Code: Um diagrama de código, class UML por exemplo, pode ser usado para ampliar um componente individual, mostrando como esse componente é implementado.

Nesse Post apresento um exemplo do diagrama Nível 3 Component e como escrever utilizando o [PlantUml](https://github.com/plantuml-stdlib/C4-PlantUML/tree/master), em outras postagens trarei exemplos dos demais níveis.

### Contexto da Aplicação

A aplicação em questão é um E-commerce fictício, e o diagrama de Componentes apresenta a responsabilidade de cada um dos componentes da aplicação e suas integrações.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjgxy1kw9ptlsde28n5l.png)

### C-4 PlantUML
Para criar esse diagrama utilizei o C-4 PlantUml que fornece uma forma simples de criar diagras utilizando a sintaxe do PlantUml, segue o código desse diagrama 

```
@startuml
title <size:45>C4 Component diagram to Generic E-Commerce
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
!define DEVICONS https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/devicons
!define DEVICONS2 https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/devicons2
!define SPRITESURL https://raw.githubusercontent.com/rabelenda/cicon-plantuml-sprites/v1.0/sprites
!define FONTAWESOME https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/font-awesome-5
!includeurl SPRITESURL/kafka.puml
!includeurl SPRITESURL/cassandra.puml
!includeurl SPRITESURL/redis.puml
!include DEVICONS2/nestjs.puml
!include DEVICONS/angular.puml
!include DEVICONS/java.puml
!include DEVICONS/nodejs.puml
!include DEVICONS/mysql.puml
!include DEVICONS/redis.puml

!include FONTAWESOME/users.puml



Person(customer, "E-commerce customer", "Customer who wants to buy a product or service")


System_Boundary(core, "E-commerce Component core "){
    Container(product,"API ecommerce-ms-product", "Java - Quarkus", $sprite="java")
    Container(order,"API ecommerce-ms-order", "Java - Quarkus", $sprite="java")
    ContainerDb(product_db,"Database","MySql", "Holds product information", $sprite="cassandra")
    ContainerDb(order_db,"Database","Cassandra", "Holds order and invoice information", $sprite="mysql")
    ContainerDb(redisDB,"Memory Database","Redis","Memory database for search itens, cart itens, order and invoice information", $sprite="redis")
    Container(email, "API ecommerce-ms-email", "Java - Quarkus", "Service for email send", $sprite="java")

    System_Boundary(sale, "Sale components"){
        ContainerQueue(orderTopic,"TOPIC", "Kafka", "Topic for new order event", $sprite="kafka")
        Container(orderConsumer, "Consumer", "Nestjs", "Consumer of new order event", $sprite="nestjs")
        ContainerQueue(nfseTopic,"TOPIC", "Kafka", "Topic for issuing invoices event", $sprite="kafka")
        Container(nfseConsumer, "Consumer", "Nestjs", "Consumer of invoice issuance events", $sprite="nestjs")
    }
}

System_Boundary(app, "E-commerce Aplication "){
    Container(spa, "SPA", "Angular", "The main interface that the customer interacts with", $sprite="angular")
    Container(bff,"BFF","NodeJs","Backend to interface SPA", $sprite="nodejs")

}

System_Boundary(external, "External components"){
    Component_Ext(payment,"API", "Payment service")
    Component_Ext(nfse,"API", "NFS-e service")
}

Rel_Neighbor(customer,spa,"Uses","https")

Rel_R(spa,bff,"Use","https")
Rel(product,product_db, "Read/Write", "tcp")
Rel(order,order_db, "Read/Write", "tcp")

Rel_D(bff,product,"List products","https")
Rel(bff, orderTopic, "New order event", "tcp")
Rel(bff,redisDB, "Save cart itens, search", "http")
Rel_R(orderTopic, orderConsumer,"Order process","tcp")
Rel(orderConsumer,payment, "Confirm payment?", "https")
Rel(orderConsumer,order, "Save new order", "https")
Rel(orderConsumer,product,"Decreases inventory of sale products", "https")
Rel(orderConsumer,nfseTopic, "Confirmed payment, issue invoice event", "tcp")
Rel(nfseTopic,nfseConsumer, "Consumes","tcp")
Rel(nfseConsumer, nfse, "Uses", "https")
Rel(orderConsumer,email, "Send purchase confirmation email", "https")

@enduml
```
Uma representação bem feita dos componentes de uma aplicação e suas integrações pode te polpar algumas horas de reuniões na sua semana.

Para saber mais sobre o [C-4 Model](https://c4model.com/)
Sobre a sintaxe do [C-4 PlantUML](https://github.com/plantuml-stdlib/C4-PlantUML)

Plugin do [VSCode para o PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)