-
-
Notifications
You must be signed in to change notification settings - Fork 12
Home
Home CLI Samples Q&A How‐to guides Quick‐starts Tutorials
C4InterFlow is a comprehensive Application Architecture focused framework designed for anyone in an organisation, who wants to either contribute to (or just to explore) the Application Architecture documentation.
These concepts are borrowed from C4 Model created by Simon Brown. Image source: www.c4model.com
C4InterFlow introduces two new concepts: Interface and Flow. Multiple Interfaces can be added to Software Systems, Containers or Components. Interfaces express capabilities exposed by these structures. Interfaces exposed by a given structure can be used by other structures. In fact, the only way to form Relationships between structures in C4InterFlow, is for one structure to Use the other structure's Interface. Interface may have one or many Flows that express its behaviour, including how and when it Uses other Interfaces. Flows can be nested.
In C4InterFlow a Business Process can be constructed with one or more Activities that are performed by Actors. Each Activity has to have a Flow, which has to use at least one Interface to be complete.
Each structure can be expressed using C4InterFlow Architecture as Code DSL either in C#, YAML or JSON. A single AaC file can have as little as one structure in it, or it can have all structures for the entire Namespace in it. In theory, you can even have all Namespaces and all of their structures stored in a single AaC file.
Below are some examples of AaC in C#, YAML and JSON
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace DotNetEShop.SoftwareSystems
{
public partial class BasketApi : ISoftwareSystemInstance
{
public static SoftwareSystem Instance => new SoftwareSystem(typeof(BasketApi), "Basket Api")
{
Description = "",
Boundary = Boundary.Internal
};
public partial class Containers
{
}
public partial class Interfaces
{
}
}
}
DotNetEShop:
SoftwareSystems:
BasketApi:
Label: Basket Api
Boundary: Internal
Description: ''
Containers: {}
Interfaces: {}
{
"DotNetEShop": {
"SoftwareSystems": {
"BasketApi": {
"Label": "Basket Api",
"Boundary": "Internal",
"Description": "",
"Containers": {},
"Interfaces": {}
}
}
}
}
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace DotNetEShop.SoftwareSystems
{
public partial class BasketApi
{
public partial class Containers
{
public partial class Grpc : IContainerInstance
{
public static Container Instance => new Container(typeof(Grpc), "Grpc")
{
ContainerType = ContainerType.None,
Description = "",
Technology = "",
Boundary = Boundary.Internal
};
public partial class Components
{
}
public partial class Interfaces
{
}
public partial class Entities
{
}
}
}
}
}
DotNetEShop:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Label: Grpc
Description: ''
ContainerType: None
Boundary: Internal
Technology: ''
Components: {}
Interfaces: {}
Entities: {}
{
"DotNetEShop": {
"SoftwareSystems": {
"BasketApi": {
"Containers": {
"Grpc": {
"Label": "Grpc",
"Description": "",
"ContainerType": "None",
"Boundary": "Internal",
"Technology": "",
"Components": {},
"Interfaces": {},
"Entities": {}
}
}
}
}
}
}
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace DotNetEShop.SoftwareSystems
{
public partial class BasketApi
{
public partial class Containers
{
public partial class Grpc
{
public partial class Components
{
public partial class BasketService : IComponentInstance
{
public static Component Instance => new Component(typeof(BasketService), "Basket Service")
{
ComponentType = ComponentType.None,
Description = "",
Technology = ""
};
public partial class Interfaces
{
}
}
}
}
}
}
}
DotNetEShop:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Components:
BasketService:
Label: Basket Service
ComponentType: None
Description: ''
Technology: ''
Interfaces: {}
{
"DotNetEShop": {
"SoftwareSystems": {
"BasketApi": {
"Containers": {
"Grpc": {
"Components": {
"BasketService": {
"Label": "Basket Service",
"ComponentType": "None",
"Description": "",
"Technology": "",
"Interfaces": {}
}
}
}
}
}
}
}
}
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace DotNetEShop.SoftwareSystems
{
public partial class BasketApi
{
public partial class Containers
{
public partial class Grpc
{
public partial class Components
{
public partial class BasketService
{
public partial class Interfaces
{
public partial class GetBasket : IInterfaceInstance
{
public static Interface Instance => new Interface(typeof(GetBasket), "Get Basket")
{
Description = "",
Path = "",
IsPrivate = false,
Protocol = "",
Flow = new Flow(Interface.GetAlias<GetBasket>())
.Use<DotNetEShop.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.GetBasketAsync>()
.If(@"data is not null")
.Use<DotNetEShop.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.Interfaces.MapToCustomerBasketResponse>()
.EndIf(),
Input = "",
InputTemplate = "",
Output = "",
OutputTemplate = ""
};
}
}
}
}
}
}
}
}
DotNetEShop:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Components:
BasketService:
Interfaces:
GetBasket:
Label: Get Basket
Description: ''
Path: ''
IsPrivate: false
Protocol: ''
Flows:
- Type: Use
Expression: DotNetEShop.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.GetBasketAsync
- Type: If
Expression: data is not null
Flows:
- Type: Use
Expression: DotNetEShop.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.Interfaces.MapToCustomerBasketResponse
Input: ''
InputTemplate: ''
Output: ''
OutputTemplate: ''
{
"DotNetEShop": {
"SoftwareSystems": {
"BasketApi": {
"Containers": {
"Grpc": {
"Components": {
"BasketService": {
"Interfaces": {
"GetBasket": {
"Label": "Get Basket",
"Description": "",
"Path": "",
"IsPrivate": false,
"Protocol": "",
"Flows": [
{
"Type": "Use",
"Expression": "DotNetEShop.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.GetBasketAsync"
},
{
"Type": "If",
"Expression": "data is not null",
"Flows": [
{
"Type": "Use",
"Expression": "DotNetEShop.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.Interfaces.MapToCustomerBasketResponse"
}
]
}
],
"Input": "",
"InputTemplate": "",
"Output": "",
"OutputTemplate": ""
}
}
}
}
}
}
}
}
}
}
C4InterFlow is aligned with C4 Model in terms of diagrams' Level of Details, which are Context (Level 1), Container (Level 2) and Component (Level 3).
NOTE: C4InterFlow does not yet support Class (Level 4) Level of Details.
Image source: www.c4model.com
Below are example of C4 diagrams auto-generated by C4InterFlow CLI for a Basket API Software System of the E-Shop sample .NET application .
Context (Level 1) | Container (Level 2) | Component (Level 3) |
---|---|---|
C4InterFlow can draw diagrams which include various number of Interfaces, covering different sub-sets of Application Architecture landscape. The size of such sub-set can be expressed with the concept of Scope. At the moment the following Scopes are supported:
- All Software Systems - all Interfaces of all Software Systems and their Containers and Components
- Namespace - all Interfaces of all Software Systems in a particular Namespace and its Sub-Namespaces and their Containers and Components
- Software System - all Interfaces of a Software System
- Software System Interface - a single Software System Interface
- Container - all Interfaces of a Container
- Container Interface - a single Container Interface
- Component - all Interfaces of a Component
- Component Interface - a single Component Interface
- Business Process - all Interfaces used in the Flows of all Activities of a Business Process
C4InterFlow can generate the following diagrams Types:
- C4 Static - a C4 Model Diagram of a specific Scope and at a specific Level Of Details (all Scopes and all Levels of Details are supported), where each "line" has "Uses" label indicating a dependency of a source (from) Structure on a destination (to) Structure
- C4 - a C4 Model Diagram of a specific Scope and at a specific Level Of Details (all Scopes and all Levels of Details are supported), where each "line" has one or many labels that correspond to the labels of one or many Interfaces of a destination (to) Structure used by the source (from) Structure
-
C4 Sequence - a Plant UML Sequence diagram (styled like all other C4 diagrams) that can be generated for the following Scopes:
- Software System Interface
- Container Interface
- Component Interface
- Business Process
-
Sequence - a Plant UML Sequence diagram that can be generated for the following Scopes:
- Software System Interface
- Container Interface
- Component Interface
- Business Process
The table below summarises diagram Types supported for different Scopes and Level of Details
Scope / Level of Details | Context | Container | Component |
---|---|---|---|
All Software Systems | C4 Static C4 |
C4 Static C4 |
C4 Static C4 |
Namespace | C4 Static C4 |
C4 Static C4 |
C4 Static C4 |
Software System | C4 Static C4 |
C4 Static C4 |
C4 Static C4 |
Software System Interface | C4 Static C4 Sequence |
||
Container | C4 Static C4 |
C4 Static C4 |
|
Container Interface | C4 Static C4 Sequence |
C4 Static C4 Sequence |
|
Component | C4 Static C4 |
||
Component Interface | C4 Static C4 Sequence |
C4 Static C4 Sequence |
C4 Static C4 Sequence |
Business Process | C4 Static C4 Sequence |
C4 Static C4 Sequence |
C4 Static C4 Sequence |
Both C# and YAML AaC can be queried using JSON Path-like syntax. Below are just some Use Cases and Examples of how AaC can be queried:
When using C4InterFlow CLI to generate the diagrams you need to provide a list of Interfaces, which you'd like to be examined for a given Draw Diagrams command execution. You can list all interfaces by their full paths, but that can result in a lengthy command. You can use a *
wildcard to indicate that you want to discover all Interfaces at specific location in AaC. Consider the following examples of query expressions:
DotNetEShop.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.*
This will select all Interfaces of RedisBasketRepository
Component of Data
Container of BasketApi
Software System in DotNetEShop
Namespace.
DotNetEShop.SoftwareSystems.BasketApi.Containers.Data.Components.*.Interfaces.*
This will select all Interfaces of all Components of Data
Container of BasketApi
Software System in DotNetEShop
Namespace.
DotNetEShop.SoftwareSystems.BasketApi.Containers.*.Components.*.Interfaces.*
This will select all Interfaces of all Components of all Container of BasketApi
Software System in DotNetEShop
Namespace.
DotNetEShop.SoftwareSystems.*.Containers.*.Components.*.Interfaces.*
This will select all Interfaces of all Components of all Containers of all Software Systems in DotNetEShop
Namespace.
DotNetEShop.SoftwareSystems.*.Containers.*.Interfaces.*
This will select all Interfaces of all Containers of all Software Systems in DotNetEShop
Namespace.
DotNetEShop.SoftwareSystems.*.Interfaces.*
This will select all Interfaces of Software Systems in DotNetEShop
Namespace.
Home CLI Samples Q&A How‐to guides Quick‐starts Tutorials
Note: This document is subject to change. Users are encouraged to check back regularly for updates.