# C4 Model

## [About](https://c4model.com/)

A simple and clear model for documenting/visualizing Software Architecture.

It has 4 levels of detailed diagrams.

<img src="https://3504937856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0EGG63nx7YH8cXDSuL3u%2Fuploads%2Fouex08YwbOq5LYAhgruz%2Ffile.excalidraw.svg?alt=media&#x26;token=4bfd7307-c512-4558-8d57-0f8c3f36a0a7" alt="" class="gitbook-drawing">

## Levels

### [Context](https://c4model.com/abstractions/software-system) (Software System)

It is the highest level of abstraction and describes something that delivers value to its users.

This includes the software system being modelled, and any other depended softwares.

{% hint style="danger" %}
What is not Software Systems:

* Product domains.
* Bounded contexts.
* Business capabilities.
* Feature teams, tribes or squads.
  {% endhint %}

Diagram [exemple](https://c4model.com/diagrams/system-context).

### [Container](https://c4model.com/abstractions/container)

Represents an application or data store. (It is a **Deployable Unit**)

A container is something that needs to be running in order for overall software systems to work.

{% hint style="success" %}

* **Server-side web applications:** A container could be a Node.js application, a Ruby on Rails application, etc.
* **Client-side applications:** A container could be an Angular or React `SPA` or `SSR`.
* **Serverless functions:** A container could be a single serverless function (Ex.: Lambda, Azure Function, etc).
* **Database:** A container could be a relational database, noSQL or Amazon RDS.
* **File systems:** A container could be full local file system or portion or a larger networked fs (Ex.: SAN, NAS, etc).
* **Shell scripts:** Could be a single shell script in `Bash`.
  {% endhint %}

Diagram [example](https://c4model.com/diagrams/container).

### [Component](https://c4model.com/abstractions/component)

It is a grouping of related functionalities encapsulated behind a well defined interface.

All the Components inside a container execute in the same process space.

{% hint style="success" %}

* **OOP languages:** A component is made up of classes and interfaces.
* **Procedural programming languages:** A component could be made up of a number of files in a particular directory.
* **JS:** A component could be a JS module.
  {% endhint %}

Diagram [example](https://c4model.com/diagrams/component).

### [Code](https://c4model.com/abstractions/code)

These are one or more elements constructed with the basic building blocks of the used programming language, (like `class`, `interface`, `enums`, `function`, `object`, etc).

Diagram [example](https://c4model.com/diagrams/code).

## [PlantUML](https://github.com/plantuml/plantuml-stdlib)

It is a library to create C4 Model diagrams through code.

{% hint style="info" %}
A VSCode plugin named `PlantUML` is also available to run PlantUML.
{% endhint %}

{% hint style="danger" %}
Requires **Java** and [**Graphviz**](https://graphviz.org/).
{% endhint %}

### Creating a Context

{% code title="context.puml" %}

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

title "Digital Wallet Context"
Person(client, "Client", "Wallet User")

System(wallet, "Digital Wallet System", "Digital Wallet")

System_Ext(apm, "APM", "Application Performance Monitoring")
System_Ext(payment_gateway, "Payment Gateway", "Payment Processor")

Rel(client, wallet, "Uses", "HTTPS")
Rel(wallet, apm, "Uses", "HTTPS")
Rel(wallet, payment_gateway, "Uses", "HTTPS")

@enduml
```

{% endcode %}

Then execute in `VSCode` this command `PlantUML: Preview Current Diagram`.

### Creating Containers

{% code title="context.puml" %}

```plant-uml
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
' Define a tag "async" to make dashed Rel lines
AddRelTag("async", $lineStyle = DashedLine())

title "Digital Wallet Containers"
Person(client, "Client", "Wallet User")

System_Ext(payment_gateway, "Payment Gateway", "Payment Processor")

System_Boundary(digital_wallet, "Digital Wallet") {
    Container(spa, "SPA", "React", "Digital Wallet Web App")
    Container(wallet_core, "Wallet Core", "Typescript", "Wallet Core is responsible for the transactions")
    Container(balance_service, "Balance Microservice", "Typescript", "Returns customer balance")
    Container(statement_service, "Statement Microservice", "Typescript", "Returns customer statement")
    Container(payment_acl, "Payment ACL", "Typescript", "Anti-corruption layer for Payment Gateways")

    ContainerDb(wallet_core_db, "Wallet DB", "MySQL")
    Rel(wallet_core, wallet_core_db, "Uses", "MySQL Driver")
    
    ContainerDb(balance_db, "Balance DB", "MySQL")
    Rel(balance_service, balance_db, "Uses", "MySQL Driver")
    
    ContainerDb(statement_db, "Statement DB", "MySQL")
    Rel(statement_service, statement_db, "Uses", "MySQL Driver")
    
    ContainerDb(payment_acl_db, "Payment ACL DB", "MySQL")
    Rel(payment_acl, payment_acl_db, "Uses", "MySQL Driver")
    
    Rel(client, spa, "Uses", "HTTPS")
    Rel(spa, wallet_core, "Uses", "Json/HTTPS")
    Rel(spa, balance_service, "Uses", "Json/HTTPS")
    Rel(spa, statement_service, "Uses", "Json/HTTPS")
    
    Rel(wallet_core, payment_acl, "Uses", "Json/HTTPS")
    Rel(payment_acl, payment_gateway, "Uses", "Json/HTTPS")
    
    ' wallet_core will produce events that will be consumed by balance & statement
    Rel(wallet_core, balance_service, "Uses", "Topic", $tags = "async")
    Rel(wallet_core, statement_service, "Uses", "Topic", $tags = "async")
}

@enduml
```

{% endcode %}
