Skip to content

Commit

Permalink
Merge pull request #53 from 8T4/features/new-builders-and-themes
Browse files Browse the repository at this point in the history
New README.md
  • Loading branch information
yanjustino authored Mar 15, 2024
2 parents 17c4f2b + 67c881e commit 5c79196
Show file tree
Hide file tree
Showing 23 changed files with 276 additions and 171 deletions.
144 changes: 78 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Deployment diagrams. The library generates the following diagram types: PNG, SVG
> There are benefits to using these tools over the heavier alternatives, including easy version control and the ability to generate the DSLs from many sources. ools in this space that we like include Diagrams, Structurizr DSL, AsciiDoctor Diagram and stables such as WebSequenceDiagrams, PlantUML and the venerable Graphviz. It's also fairly simple to generate your own SVG these days, so don't rule out quickly writing your own tool either. One of our authors wrote a small Ruby script to quickly create SVGs, for example.
> [Thoughtworks Technology Radar](https://www.thoughtworks.com/en-br/radar/techniques/diagrams-as-code)
# Getting Started
## Getting Started

First, you will need the [.NET 5.0+](https://docs.microsoft.com/pt-br/dotnet/standard/net-standard)
and [Java](https://www.java.com/en/download/) to run C4Sharp. Also, you should install the C4Sharp package in your project.
Expand All @@ -29,103 +29,117 @@ This package is available through [Nuget Packages](https://www.nuget.org/package
To build a diagram using the C4S library we need to identify the structures and their relationships through a class that inherits properties directly from DiagramBuildRunner. See the following example of building a container diagram:

```C#
namespace C4Bank.Deposit.Architecture;

public class ContainerDiagram : DiagramBuildRunner
public class ContainerDiagramSample : ContainerDiagram
{
protected override string Title => "C4Bank Context of Deposit Area";
protected override DiagramType DiagramType => DiagramType.Container;

protected override string Title => "Container diagram for Internet Banking System";

protected override IEnumerable<Structure> Structures => new Structure[]
{
new Person("Customer", "Customer", "Bank Customer"),
new SoftwareSystem("OTBank.Finance", "Finance", "OTBank Finance System", Boundary.External),
new SoftwareSystem("C4Bank.Account", "Account", "C4Bank Account System"),
new Api<DepositReceived>("Aspnet/C#", "ACL"),
new EventStreaming<RegisteredAccount>("kafka", "Partition 01"),
Person.None | Boundary.External
| ("Customer", "Personal Banking Customer", "A customer of the bank, with personal bank accounts."),

SoftwareSystemBoundary.New("Deposit",
new Api<DepositoProcessingWorker>("C#"),
new Database<IDepositRepository>("SQL Server", "Deposit Data Base"),
new ServerConsole<SynchronizeNewAccountConsumer>("C#", "Kafka Consumer"),
new Database<IAccountRepository>("SQL Server", "Account Data Base")
),
SoftwareSystem.None | ("BankingSystem", "Internet Banking System",
"Allows customers to view information about their bank accounts, and make payments."),

SoftwareSystem.None | Boundary.External
| ("MailSystem", "E-mail system", "The internal Microsoft Exchange e-mail system."),

Bound("c1", "Internet Banking",
Container.None | (WebApplication, "WebApp", "WebApp", "C#, WebApi",
"Delivers the static content and the Internet banking SPA"),

Container.None | (Spa, "Spa", "Spa", "JavaScript, Angular",
"Delivers the static content and the Internet banking SPA"),

Container.None | (Mobile, "MobileApp", "Mobile App", "C#, Xamarin",
"Provides a mobile banking experience"),

Container.None | (Database, "SqlDatabase", "SqlDatabase", "SQL Database",
"Stores user registration information, hashed auth credentials, access logs, etc."),

Container.None | (Queue, "RabbitMQ", "RabbitMQ", "RabbitMQ",
"Stores user registration information, hashed auth credentials, access logs, etc."),

Container.None | (Api, "BackendApi", "BackendApi", "Dotnet, Docker Container",
"Provides Internet banking functionality via API.")
)
};

protected override IEnumerable<Relationship> Relationships => new[]
{
It("Customer") > It("OTBank.Finance") | "send deposit",
It("OTBank.Finance") > It<DepositReceived>() | ("POST", "HTTP"),
It<DepositoProcessingWorker>() < It<DepositReceived>() | ("POST", "HTTP"),
It<DepositoProcessingWorker>() > It<IDepositRepository>(),
this["Customer"] > this["WebApp"] | ("Uses", "HTTPS"),
this["Customer"] > this["Spa"] | ("Uses", "HTTPS"),
this["Customer"] > this["MobileApp"] | "Uses",

this["WebApp"] > this["Spa"] | "Delivers" | Position.Neighbor,
this["Spa"] > this["BackendApi"] | ("Uses", "async, JSON/HTTPS"),
this["MobileApp"] > this["BackendApi"] | ("Uses", "async, JSON/HTTPS"),
this["SqlDatabase"] < this["BackendApi"] | ("Uses", "async, JSON/HTTPS") | Position.Neighbor,
this["RabbitMQ"] < this["BackendApi"] | ("Uses", "async, JSON"),

It("Customer") > It("C4Bank.Account") | "register",
It("C4Bank.Account") > It<RegisteredAccount>() | "produces",
It<SynchronizeNewAccountConsumer>() > It<RegisteredAccount>() | "consumes",
It<SynchronizeNewAccountConsumer>() > It<IAccountRepository>(),
It<DepositoProcessingWorker>() > It<IAccountRepository>(),
};
this["Customer"] < this["MailSystem"] | "Sends e-mails to",
this["MailSystem"] < this["BackendApi"] | ("Sends e-mails using", "sync, SMTP"),
this["BackendApi"] > this["BankingSystem"] | ("Uses", "sync/async, XML/HTTPS") | Position.Neighbor
};
}
```
The following code shows how to compile the diagram:

```c#

There are two strategies for compiling diagrams in your project: self-compiling and using the `C4SCLI` tool.

#### a) self-compiling approach:

```c#
internal static class Program
using C4Sharp.Diagrams;
using C4Sharp.Diagrams.Plantuml;
using C4Sharp.Diagrams.Themes;
using ModelDiagrams.Diagrams;

var diagrams = new DiagramBuilder[]
{
private static void Main()
{
var diagrams = new[]
{
new ContainerDiagram().Build(),
};
new ContextDiagramSample(),
new ComponentDiagramSample(),
new ContainerDiagramSample(),
new EnterpriseDiagramSample(),
new SequenceDiagramSample(),
new DeploymentDiagramSample()
};

var path = Path.Combine("..", "..", "..", "..", "..", "docs", "images");

new PlantumlSession()
.UseDiagramImageBuilder()
.UseDiagramSvgImageBuilder()
.Export(diagrams);
}
}
new PlantumlContext()
.UseDiagramImageBuilder()
.Export(path, diagrams, new DefaultTheme());
```
<small>see the complete code [here](./samples/Basic/C4Sharp.Sample/Program.cs)</small>

#### b) Using the C4SCLI tool:
The result of the previous code is the following diagram:
![img](./docs/images/container-diagram-for-internet-banking-system-c4container.png)

### Using the C4SCLI tool:

> [!TIP]\
> The `C4SCLI` can be used in DevOps pipelines, removing the need to manually compile diagrams. For this, install `C4SCLI` tool and execute de the following command:
```shell
$ c4scli build <solution path> [-o <output path>]
```
see the following sample

```bash
$ mkdir assets
$ c4scli build /src/c4sharp.sln -o /c4
...
### Customizing the diagram

C4 diagram PNG files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.png
Themes are used to customize the diagram. The following code shows how to use the `ParadisoTheme` theme to compile the diagram:

C4 diagram SVG files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.svg

C4 diagram MD files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.mermaid.md

C4 diagram PUML files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.puml
```c#
new PlantumlContext()
.UseDiagramImageBuilder()
.Export(path, diagrams, new ParadisoTheme());
```

>[!WARNING]
> only compatible with projects using c4sharp version 5.0+
The result of the previous code is the following diagram:
![img](./docs/images/container-diagram-for-internet-banking-system-v2-c4container.png)

The previous steps will result in the following image:

![img](./docs/images/c4bank-deposit-area-c4container.png)

You can customize the diagram by implementing the SetStyle() method, as in the following example:
Using the `C4S` library, you can customize the diagram by implementing the SetStyle() method, as in the following example:

```c#
protected override IElementStyle? SetStyle()
Expand Down Expand Up @@ -183,8 +197,6 @@ Rel(BankingSystem, MailSystem, "Sends e-mails", "SMTP")
Rel(BankingSystem, Mainframe, "uses")
```

See the complete code [here](./docs/system-enterprise-diagram-for-internet-banking-system-c4context.mermaid.md).


# Learn
- See more in our [sample code](./samples):
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
@startuml component-diagram-for-internet-banking-system-c4component
!include ../.c4s/C4_Component.puml

UpdateElementStyle("system", $bgColor=#1a67be,$fontColor=#FFFFFF,$borderColor=#175eaa,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_system", $bgColor=#999999,$fontColor=#FFFFFF,$borderColor=#8a8a8a,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("person", $bgColor=#0d437b,$fontColor=#FFFFFF,$borderColor=#0d437b,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("component", $bgColor=#85bbf0,$fontColor=#000000,$borderColor=#78a8d9,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_component", $bgColor=#999999,$fontColor=#FFFFFF,$borderColor=#8a8a8a,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("container", $bgColor=#438dd4,$fontColor=#FFFFFF,$borderColor=#3e82c5,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_container", $bgColor=#999999,$fontColor=#FFFFFF,$borderColor=#8a8a8a,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateBoundaryStyle($elementName=system,$bgColor=#FFFFFF,$fontColor=#000000,$borderColor=#000000,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=container,$bgColor=#FFFFFF,$fontColor=#000000,$borderColor=#000000,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=enterprise,$bgColor=#FFFFFF,$fontColor=#000000,$borderColor=#000000,$shadowing="false",$shape=RoundedBoxShape())
UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
SHOW_PERSON_PORTRAIT()
LAYOUT_TOP_DOWN()

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@ LAYOUT_TOP_DOWN()

title Container diagram for Internet Banking System

Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
Person_Ext(Customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.")

System_Boundary(c1, "Internet Banking") {
Container(Corporate.Finance.Limits.Service.ServiceBus, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA")
Container(WebApp, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA")
Container(Spa, "Spa", "Spa:JavaScript, Angular", "Delivers the static content and the Internet banking SPA")
Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
ContainerDb(Database, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
ContainerQueue(Queue, "RabbitMQ", "Queue:RabbitMQ", "Stores user registration information, hashed auth credentials, access logs, etc.")
Container(MobileApp, "Mobile App", "Mobile:C#, Xamarin", "Provides a mobile banking experience")
ContainerDb(SqlDatabase, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
ContainerQueue(RabbitMQ, "RabbitMQ", "Queue:RabbitMQ", "Stores user registration information, hashed auth credentials, access logs, etc.")
Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.")
}


Rel(customer, Corporate.Finance.Limits.Service.ServiceBus, "Uses", "HTTPS")
Rel(customer, Spa, "Uses", "HTTPS")
Rel(customer, MobileApp, "Uses")
Rel_Neighbor(Corporate.Finance.Limits.Service.ServiceBus, Spa, "Delivers")
Rel(Customer, WebApp, "Uses", "HTTPS")
Rel(Customer, Spa, "Uses", "HTTPS")
Rel(Customer, MobileApp, "Uses")
Rel_Neighbor(WebApp, Spa, "Delivers")
Rel(Spa, BackendApi, "Uses", "async, JSON/HTTPS")
Rel(MobileApp, BackendApi, "Uses", "async, JSON/HTTPS")
Rel_Back_Neighbor(Database, BackendApi, "Uses", "async, JSON/HTTPS")
Rel_Back(Queue, BackendApi, "Uses", "async, JSON")
Rel_Back(customer, MailSystem, "Sends e-mails to")
Rel_Back_Neighbor(SqlDatabase, BackendApi, "Uses", "async, JSON/HTTPS")
Rel_Back(RabbitMQ, BackendApi, "Uses", "async, JSON")
Rel_Back(Customer, MailSystem, "Sends e-mails to")
Rel_Back(MailSystem, BackendApi, "Sends e-mails using", "sync, SMTP")
Rel_Neighbor(BackendApi, BankingSystem, "Uses", "sync/async, XML/HTTPS")
@enduml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@startuml container-diagram-for-internet-banking-system-v2-c4container
!include ../.c4s/C4_Container.puml

UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2)
UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1)
UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape())
SHOW_PERSON_PORTRAIT()
LAYOUT_TOP_DOWN()

title Container diagram for Internet Banking System v2

Person_Ext(Customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.")

System_Boundary(c1, "Internet Banking") {
Container(WebApp, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA")
Container(Spa, "Spa", "Spa:JavaScript, Angular", "Delivers the static content and the Internet banking SPA")
Container(MobileApp, "Mobile App", "Mobile:C#, Xamarin", "Provides a mobile banking experience")
ContainerDb(SqlDatabase, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
ContainerQueue(RabbitMQ, "RabbitMQ", "Queue:RabbitMQ", "Stores user registration information, hashed auth credentials, access logs, etc.")
Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.")
}


Rel(Customer, WebApp, "Uses", "HTTPS")
Rel(Customer, Spa, "Uses", "HTTPS")
Rel(Customer, MobileApp, "Uses")
Rel_Neighbor(WebApp, Spa, "Delivers")
Rel(Spa, BackendApi, "Uses", "async, JSON/HTTPS")
Rel(MobileApp, BackendApi, "Uses", "async, JSON/HTTPS")
Rel_Back_Neighbor(SqlDatabase, BackendApi, "Uses", "async, JSON/HTTPS")
Rel_Back(RabbitMQ, BackendApi, "Uses", "async, JSON")
Rel_Back(Customer, MailSystem, "Sends e-mails to")
Rel_Back(MailSystem, BackendApi, "Sends e-mails using", "sync, SMTP")
Rel_Neighbor(BackendApi, BankingSystem, "Uses", "sync/async, XML/HTTPS")
@enduml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 5c79196

Please sign in to comment.