init
parent
c12f24f09f
commit
a234d78b5c
@ -0,0 +1,86 @@
|
||||
{
|
||||
"C4_Person": {
|
||||
"prefix": "Person",
|
||||
"body": [
|
||||
"Person(${1:alias}, \"${2:label}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add Person to C4 diagram"
|
||||
},
|
||||
"C4_Person_Descr": {
|
||||
"prefix": "Person with Description",
|
||||
"body": [
|
||||
"Person(${1:alias}, \"${2:label}\", \"${3:description}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add Person with Description to C4 diagram"
|
||||
},
|
||||
|
||||
"C4_Container": {
|
||||
"prefix": "Container",
|
||||
"body": [
|
||||
"Container(${1:alias}, \"${2:label}\", \"${3:technology}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add Container to C4 diagram"
|
||||
},
|
||||
"C4_Container_Descr": {
|
||||
"prefix": "Container with Description",
|
||||
"body": [
|
||||
"Container(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add Container with Description to C4 diagram"
|
||||
},
|
||||
|
||||
"C4_System": {
|
||||
"prefix": "System",
|
||||
"body": [
|
||||
"System(${1:alias}, \"${2:label}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add System to C4 diagram"
|
||||
},
|
||||
"C4_System_Descr": {
|
||||
"prefix": "System with Description",
|
||||
"body": [
|
||||
"System(${1:alias}, \"${2:label}\", \"${3:description}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add System with Description to C4 diagram"
|
||||
},
|
||||
|
||||
"C4_Relationship": {
|
||||
"prefix": "Relationship",
|
||||
"body": [
|
||||
"Rel(${1:from_alias}, ${2:to_alias}, \"${3:label}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add unidirectional Relationship to C4 diagram"
|
||||
},
|
||||
"C4_Relationship_Techn": {
|
||||
"prefix": "Relationship with Technology",
|
||||
"body": [
|
||||
"Rel(${1:from_alias}, ${2:to_alias}, \"${3:label}\", \"${4:technology}\")",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add unidirectional Relationship with Technology to C4 diagram"
|
||||
},
|
||||
|
||||
"C4_Layout_Right": {
|
||||
"prefix": "Layout to Right side",
|
||||
"body": [
|
||||
"Lay_R(${1:from_alias}, ${2:to_alias})",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add hidden layout line to put {to} to the right of {from}"
|
||||
},
|
||||
"C4_Layout_Left": {
|
||||
"prefix": "Layout to Left side",
|
||||
"body": [
|
||||
"Lay_L(${1:from_alias}, ${2:to_alias})",
|
||||
"$0"
|
||||
],
|
||||
"description": "Add hidden layout line to put {to} to the left of {from}"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
' Colors
|
||||
' ##################################
|
||||
|
||||
!define PERSON_BG_COLOR #08427B
|
||||
!define CONTAINER_BG_COLOR #438DD5
|
||||
!define SYSTEM_BG_COLOR #999999
|
||||
!define ELEMENT_FONT_COLOR #FFFFFF
|
||||
|
||||
!define TECHN_FONT_SIZE 12
|
||||
|
||||
' Styling
|
||||
' ##################################
|
||||
skinparam defaultTextAlignment center
|
||||
|
||||
skinparam wrapWidth 200
|
||||
skinparam maxMessageSize 200
|
||||
|
||||
skinparam rectangle {
|
||||
StereotypeFontSize 12
|
||||
}
|
||||
|
||||
skinparam Arrow {
|
||||
Color #666666
|
||||
FontColor #666666
|
||||
}
|
||||
|
||||
skinparam rectangle<<person>> {
|
||||
StereotypeFontColor ELEMENT_FONT_COLOR
|
||||
FontColor ELEMENT_FONT_COLOR
|
||||
BackgroundColor PERSON_BG_COLOR
|
||||
BorderColor #073B6F
|
||||
}
|
||||
|
||||
skinparam rectangle<<container>> {
|
||||
StereotypeFontColor ELEMENT_FONT_COLOR
|
||||
FontColor ELEMENT_FONT_COLOR
|
||||
BackgroundColor CONTAINER_BG_COLOR
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
|
||||
skinparam rectangle<<system>> {
|
||||
StereotypeFontColor ELEMENT_FONT_COLOR
|
||||
FontColor ELEMENT_FONT_COLOR
|
||||
BackgroundColor SYSTEM_BG_COLOR
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
|
||||
skinparam package<<boundary>> {
|
||||
StereotypeFontSize 0
|
||||
FontColor #999999
|
||||
BorderColor #cccccc
|
||||
}
|
||||
|
||||
' Layout
|
||||
' ##################################
|
||||
|
||||
!definelong LAYOUT_AS_SKETCH
|
||||
skinparam backgroundColor #EEEBDC
|
||||
skinparam handwritten true
|
||||
skinparam defaultFontName "Comic Sans MS"
|
||||
center footer <font color=red>Warning:</font> Created for discussion, needs to be validated
|
||||
!enddefinelong
|
||||
|
||||
!definelong LAYOUT_WITH_LEGEND
|
||||
hide stereotype
|
||||
legend right
|
||||
|= |= Type |
|
||||
|<PERSON_BG_COLOR> | person |
|
||||
|<CONTAINER_BG_COLOR> | container |
|
||||
|<SYSTEM_BG_COLOR> | external system |
|
||||
endlegend
|
||||
!enddefinelong
|
||||
|
||||
!define LAYOUT_TOP_DOWN top to bottom direction
|
||||
!define LAYOUT_LEFT_RIGHT left to right direction
|
||||
|
||||
' Elements
|
||||
' ##################################
|
||||
|
||||
!define Person(e_alias, e_label) rectangle "==e_label" <<person>> as e_alias
|
||||
!define Person(e_alias, e_label, e_descr) rectangle "==e_label\n\n e_descr" <<person>> as e_alias
|
||||
|
||||
!define Container(e_alias, e_label, e_techn) rectangle "==e_label\n//<size:TECHN_FONT_SIZE>[e_techn]</size>//" <<container>> as e_alias
|
||||
!define Container(e_alias, e_label, e_techn, e_descr) rectangle "==e_label\n//<size:TECHN_FONT_SIZE>[e_techn]</size>//\n\n e_descr" <<container>> as e_alias
|
||||
|
||||
!define System(e_alias, e_label) rectangle "==e_label" <<system>> as e_alias
|
||||
!define System(e_alias, e_label, e_descr) rectangle "==e_label\n\n e_descr" <<system>> as e_alias
|
||||
|
||||
|
||||
!define Rel_(e_from,e_to, e_label, e_direction="") e_from -e_direction-> e_to : "===e_label"
|
||||
!define Rel_(e_from,e_to, e_label, e_techn, e_direction="") e_from -e_direction-> e_to : "===e_label\n//<size:TECHN_FONT_SIZE>[e_techn]</size>//"
|
||||
|
||||
!define Rel(e_from,e_to, e_label) Rel_(e_from,e_to, e_label, "")
|
||||
!define Rel(e_from,e_to, e_label, e_techn) Rel_(e_from,e_to, e_label, e_techn, "")
|
||||
|
||||
!define Rel_D(e_from,e_to, e_label) Rel_(e_from,e_to, e_label, "DOWN")
|
||||
!define Rel_D(e_from,e_to, e_label, e_techn) Rel_(e_from,e_to, e_label, e_techn, "DOWN")
|
||||
|
||||
!define Rel_U(e_from,e_to, e_label) Rel_(e_from,e_to, e_label, "UP")
|
||||
!define Rel_U(e_from,e_to, e_label, e_techn) Rel_(e_from,e_to, e_label, e_techn, "UP")
|
||||
|
||||
!define Rel_L(e_from,e_to, e_label) Rel_(e_from,e_to, e_label, "LEFT")
|
||||
!define Rel_L(e_from,e_to, e_label, e_techn) Rel_(e_from,e_to, e_label, e_techn, "LEFT")
|
||||
|
||||
!define Rel_R(e_from,e_to, e_label) Rel_(e_from,e_to, e_label, "RIGHT")
|
||||
!define Rel_R(e_from,e_to, e_label, e_techn) Rel_(e_from,e_to, e_label, e_techn, "RIGHT")
|
||||
|
||||
!define Lay_R(e_from, e_to) e_from -[hidden]R- e_to
|
||||
!define Lay_L(e_from, e_to) e_from -[hidden]L- e_to
|
||||
@ -1,2 +1,140 @@
|
||||
# C4-PlantUML
|
||||
C4-PlantUML combines the benefits of PlantUML and the C4 model for providing a simple way of describing and communicate software architectures
|
||||
|
||||
C4-PlantUML combines the benefits of [PlantUML](http://en.plantuml.com/) and the [C4 model](https://c4model.com/) for providing a simple way of describing and communicate software architectures - especially during up-front design sessions - with an intuitive language using open source and platform independent tools.
|
||||
|
||||
C4-PlantUML includes macros, stereotypes, and other goodies (like VSCode Snippets) for creating C4 diagrams with PlantUML.
|
||||
|
||||
## Background
|
||||
|
||||
[PlantUML](http://en.plantuml.com/) is an open source project that allows you to create UML diagrams.
|
||||
Diagrams are defined using a simple and intuitive language.
|
||||
Images can be generated in PNG, in SVG or in LaTeX format.
|
||||
|
||||
PlantUML was created to allow the drawing of UML diagrams, using a simple and human readable text description.
|
||||
Because it does not prevent you from drawing inconsistent diagrams, it is a drawing tool and not a modeling tool.
|
||||
It is the most used text-based diagram drawing tool with [extensive support into wikis and forums, text editors and IDEs, use by different programming languages and documentation generators](http://en.plantuml.com/running).
|
||||
|
||||
The [C4 model](https://c4model.com/) for software architecture is an "abstraction-first" approach to diagramming, based upon abstractions that reflect how software architects and developers think about and build software.
|
||||
The small set of abstractions and diagram types makes the C4 model easy to learn and use.
|
||||
C4 stands for context, containers, components, and code — a set of hierarchical diagrams that you can use to describe your software architecture at different zoom levels, each useful for different audiences.
|
||||
|
||||
The C4 model was created as a way to help software development teams describe and communicate software architecture, both during up-front design sessions and when retrospectively documenting an existing codebase.
|
||||
|
||||
More information can be found here:
|
||||
|
||||
* [The C4 model for software architecture](https://c4model.com/)
|
||||
* [REAL WORLD PlantUML - Sample Gallery](https://real-world-plantuml.com/)
|
||||
* [Visualising and documenting software architecture cheat sheets](http://www.codingthearchitecture.com/2017/04/27/visualising_and_documenting_software_architecture_cheat_sheets.html)
|
||||
* [PlantUML and Structurizr - Create models not diagrams](http://www.codingthearchitecture.com/2016/12/08/plantuml_and_structurizr.html)
|
||||
|
||||
## Getting Started
|
||||
|
||||
At the top of your C4 PlantUML `.puml` file, you need to include the `C4_Container.puml` file found in the `root` of this repo.
|
||||
|
||||
To be independent of any internet connectifity, you can also download `C4_Container.puml` and reference it locally with
|
||||
|
||||
```plantuml
|
||||
!include path/to/C4_Container.puml
|
||||
```
|
||||
|
||||
If you want to use the always up-to-date version in this repo, use the following:
|
||||
|
||||
```plantuml
|
||||
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml
|
||||
```
|
||||
|
||||
After you have inlcluded `C4_Container.puml` you can use the defined macro definitions for the C4 elements: `Person`, `System`, `Container`, `Relationship`.
|
||||
|
||||
```plantuml
|
||||
@startuml Basic Sample
|
||||
!include C4_Container.puml
|
||||
|
||||
Person(personAlias, "Label", "Optional Description")
|
||||
Container(containerAlias, "Label", "Technology", "Optional Description")
|
||||
System(systemAlias, "Label", "Optional Description")
|
||||
|
||||
Rel(personAlias, containerAlias, "Label", "Optional Technology")
|
||||
@enduml
|
||||
```
|
||||
|
||||
In addition to this, it is also possible to define a system boundary.
|
||||
|
||||
Take a look a look at the following sample of a C4 Container Diagram:
|
||||
|
||||
```plantuml
|
||||
@startuml Basic Sample
|
||||
!include C4_Container.puml
|
||||
|
||||
Person(admin, "Administrator")
|
||||
package "Sample System" <<boundary>> as c1 {
|
||||
Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines")
|
||||
}
|
||||
System(twitter, "Twitter")
|
||||
|
||||
Rel(admin, web_app, "Uses", "HTTPS")
|
||||
Rel(web_app, twitter, "Gets tweets from", "HTTPS")
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Snipptes for Visual Studio Code
|
||||
|
||||
Lorem
|
||||
|
||||
https://medium.com/hack-visual-studio-code/share-snippets-with-your-team-in-vs-code-817801e853fb
|
||||
|
||||
## Layout Options
|
||||
|
||||
PlantUML uses [Graphviz](https://www.graphviz.org/) for his graph visualization. Thus the rendering itself is done automatically for you - that it one of the biggest advantages of using PlantUML.
|
||||
|
||||
...and also sometimes one of the biggest disadvantages, if the rendering is not what the user intended.
|
||||
|
||||
For this reason, C4-PlantUML also comes with some layout options.
|
||||
|
||||
### LAYOUT_TOP_DOWN or LAYOUT_LEFT_RIGHT
|
||||
|
||||
With the two macros `LAYOUT_TOP_DOWN` and `LAYOUT_LEFT_RIGHT` it is possible to easily change the flow visualization of the diagram. `LAYOUT_TOP_DOWN` is the default.
|
||||
|
||||
```plantuml
|
||||
@startuml Basic Sample
|
||||
!include C4_Container.puml
|
||||
|
||||
' Not needed because this is the default
|
||||
LAYOUT_TOP_DOWN
|
||||
|
||||
Person(admin, "Administrator")
|
||||
package "Sample System" <<boundary>> as c1 {
|
||||
Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines")
|
||||
}
|
||||
System(twitter, "Twitter")
|
||||
|
||||
Rel(admin, web_app, "Uses", "HTTPS")
|
||||
Rel(web_app, twitter, "Gets tweets from", "HTTPS")
|
||||
@enduml
|
||||
```
|
||||
|
||||
Using `LAYOUT_LEFT_RIGHT`
|
||||
|
||||
```plantuml
|
||||
@startuml Basic Sample
|
||||
!include C4_Container.puml
|
||||
|
||||
LAYOUT_LEFT_RIGHT
|
||||
|
||||
Person(admin, "Administrator")
|
||||
package "Sample System" <<boundary>> as c1 {
|
||||
Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines")
|
||||
}
|
||||
System(twitter, "Twitter")
|
||||
|
||||
Rel(admin, web_app, "Uses", "HTTPS")
|
||||
Rel(web_app, twitter, "Gets tweets from", "HTTPS")
|
||||
@enduml
|
||||
```
|
||||
|
||||
### LAYOUT_WITH_LEGEND
|
||||
|
||||
Colors can help to add additional information or simply to make the diagram more aesthetically pleasing.
|
||||
|
||||
|
||||
## Advanced Samples
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
@startuml "bigbankplc"
|
||||
!include ..\C4_Container.puml
|
||||
|
||||
LAYOUT_TOP_DOWN
|
||||
'LAYOUT_AS_SKETCH
|
||||
LAYOUT_WITH_LEGEND
|
||||
|
||||
|
||||
Person(customer, Customer, "A customer of the bank, with personal bank accounts")
|
||||
|
||||
package "Internet Banking System" <<boundary>> as c1 {
|
||||
|
||||
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
|
||||
|
||||
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser")
|
||||
|
||||
Container(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
|
||||
|
||||
Container(backend_api, "API Application", "Java, Docker Container", "Provides Internet banking functionality via API")
|
||||
|
||||
Container(database, "Database", "SQL Database", "Stores user registraion information, hased auth credentials, access logs, etc.")
|
||||
}
|
||||
|
||||
System(email_system, "E-Mail System", "The internal Microsoft Exchange system")
|
||||
System(banking_system, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||
|
||||
Rel(customer, web_app, "Uses", "HTTPS")
|
||||
Rel(customer, spa, "Uses", "HTTPS")
|
||||
Rel(customer, mobile_app, "Uses")
|
||||
|
||||
Rel_R(web_app, spa, "Delivers")
|
||||
|
||||
Rel(spa, backend_api, "Uses", "async, JSON/HTTPS")
|
||||
|
||||
Rel(mobile_app, backend_api, "Uses", "async, JSON/HTTPS")
|
||||
|
||||
Rel_L(backend_api, database, "Reads from and writes to", "sync, JDBC")
|
||||
Rel_R(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS")
|
||||
Rel_U(backend_api, email_system, "Sends e-mails using", "sync, SMTP")
|
||||
|
||||
Rel(email_system, customer, "Sends e-mails to")
|
||||
|
||||
rectangle test
|
||||
email_system -UP-> test
|
||||
test -LEFT-> customer
|
||||
hide test
|
||||
|
||||
@enduml
|
||||
@ -0,0 +1,49 @@
|
||||
@startuml "bigbankplc"
|
||||
!include ..\C4_Container.puml
|
||||
|
||||
skinparam wrapWidth 200
|
||||
skinparam maxMessageSize 200
|
||||
|
||||
LAYOUT_TOP_DOWN
|
||||
'LAYOUT_AS_SKETCH
|
||||
LAYOUT_WITH_LEGEND
|
||||
|
||||
|
||||
Person(customer, Customer, "A customer")
|
||||
|
||||
package "Customer Information System" <<boundary>> as c1 {
|
||||
|
||||
Container(app, "Customer Application", "Javascript, Angular", "Allows customers to manage their profile")
|
||||
|
||||
Container(customer_service, "Customer Service", "Java, Spring Boot", "The point of access for customer information")
|
||||
|
||||
Container(message_bus, "Message Bus", "RabbitMQ", "Transport for business events")
|
||||
|
||||
Container(reporting_service, "Reporting Service", "Ruby", "Creates normalised data for reporting purposes")
|
||||
|
||||
Container(audit_service, "Audit Service", "C#/.NET", "Provides organisation-wide auditing facilities")
|
||||
|
||||
Container(customer_db, "Customer Database", "Oracle 12c", "Stores customer information")
|
||||
|
||||
Container(reporting_db, "Reporting Database", "MySQL", "Stores a normalized version of all business data for ad hoc reporting purposes")
|
||||
|
||||
Container(audit_store, "Audit Store", "Event Store", "Stores information about events that have happened")
|
||||
}
|
||||
|
||||
Rel(customer, app, "Uses", "HTTPS")
|
||||
|
||||
Rel_R(app, customer_service, "Updates customer information using", "async, JSON/HTTPS")
|
||||
|
||||
Rel_L(customer_service, app, "Sends events to", "WebSocket")
|
||||
Rel_R(customer_service, message_bus, "Sends customer update events to")
|
||||
Rel(customer_service, customer_db, "Stores data in", "JDBC")
|
||||
|
||||
Rel(message_bus, reporting_service, "Sends customer update events to")
|
||||
Rel(message_bus, audit_service, "Sends customer update events to")
|
||||
|
||||
Rel(reporting_service, reporting_db, "Stores data in")
|
||||
Rel(audit_service, audit_store, "Stores events in")
|
||||
|
||||
Lay_R(reporting_service, audit_service)
|
||||
|
||||
@enduml
|
||||
@ -0,0 +1,49 @@
|
||||
@startuml "bigbankplc"
|
||||
!include ..\C4_Container.puml
|
||||
|
||||
LAYOUT_TOP_DOWN
|
||||
'LAYOUT_AS_SKETCH
|
||||
LAYOUT_WITH_LEGEND
|
||||
|
||||
|
||||
Person(anonymous_user, "Anonymous User")
|
||||
Person(aggregated_user, "Aggregated User")
|
||||
Person(administration_user, "Administration User")
|
||||
|
||||
package "techtribes.js" <<boundary>> as c1 {
|
||||
|
||||
Container(web_app, "Web Application", "Java, Spring MVC, Tomcat 7.x", "Allows users to view people, tribes, content, events, jobs, etc. from the local tech, digital and IT sector")
|
||||
|
||||
Container(rel_db, "Relational Database", "MySQL 5.5.x", "Stores people, tribes, tribe membership, talks, events, jobs, badges, GitHub repos, etc.")
|
||||
|
||||
Container(filesystem, "File System", "FAT32", "Stores search indexes")
|
||||
|
||||
Container(nosql, "NoSQL Data Store", "MongoDB 2.2.x", "Stores from RSS/Atom feeds (blog posts) and tweets")
|
||||
|
||||
Container(updater, "Updater", "Java 7 Console App", "Updates profiles, tweets, GitHub repos and content on a scheduled basis")
|
||||
}
|
||||
|
||||
System(twitter, "Twitter")
|
||||
System(github, "GitHub")
|
||||
System(blogs, "Blogs")
|
||||
|
||||
|
||||
Rel(anonymous_user, web_app, "Uses", "HTTPS")
|
||||
Rel(aggregated_user, web_app, "Uses", "HTTPS")
|
||||
Rel(administration_user, web_app, "Uses", "HTTPS")
|
||||
|
||||
Rel(web_app, rel_db, "Reads from and writes to", "SQL/JDBC, post 3306")
|
||||
Rel(web_app, filesystem, "Reads from")
|
||||
Rel(web_app, nosql, "Reads from", "MongoDB wire protocol, port 27017")
|
||||
|
||||
Rel_U(updater, rel_db, "Reads from and writes data to", "SQL/JDBC, post 3306")
|
||||
Rel_U(updater, filesystem, "Writes to")
|
||||
Rel_U(updater, nosql, "Reads from and writes to", "MongoDB wire protocol, port 27017")
|
||||
|
||||
Rel(updater, twitter, "Gets profile information and tweets from", "HTTPS")
|
||||
Rel(updater, github, "Gets information about public code repositories from", "HTTPS")
|
||||
Rel(updater, blogs, "Gets content using RSS and Atom feeds from", "HTTP")
|
||||
|
||||
Lay_R(rel_db, filesystem)
|
||||
|
||||
@enduml
|
||||
Loading…
Reference in New Issue