-
-
Notifications
You must be signed in to change notification settings - Fork 19
Home

C4InterFlow is a comprehensive Application Architecture focused toolchain designed for anyone in an organisation, who wants to either contribute to (or just to explore) the Application Architecture documentation.
Software Engineers and Architects can contribute by populating an Architecture Catalogue and by generating (or writing manually) Architecture as Code (AaC).
Product Owners, QA and any other team members, may want to explore the Application Architecture by browsing various automatically generated diagrams (e.g. C4, Sequence etc.) as well as by querying Application Architecture (e.g. to find dependencies).
Architects and Product Owners can contribute by adding Business Processes to the Architecture Catalogue or by writing Business Processes as Code manually.
Operations team members can explore the Business Processes by browsing various automatically generated diagrams
C4InterFlow offers versatile capabilities including:
- Manual creation of Architecture as Code in C# or YAML
- Automatic generation of Architecture as Code in C# or YAML from .NET (C#) source code or from Excel/CSV Architecture Catalogue
- NOTE: Automatic generation of Architecture as Code is also possible from the source code in other languages as well as from Infrastructure as Code (IaC)
- Generation of C4 Model and Sequence diagrams of various scopes (e.g. all Software Systems, Software System, Container, Interface(s), Business Process etc.) and at different levels of details (e.g. Context, Container and Component)
- Diagrams can be generated in a variety of formats including Plant UML (.puml), SVG, PNG and Markdown (.md files with embedded PNG diagrams)
- With a bit of additional custom automation, these diagrams can be published to other platforms e.g. GitHub Pages, Confluence etc.
- Advanced querying of Architecture as Code, with support for JSON Path-like syntax, to uncover dependencies or to perform any other AaC analysis
- Custom diagram generation based on query results
-
Business Process description through Activities and Interfaces utilisation
- Manual writing of Business Process as Code in C# or YAML
- Adding and editing Business Processes via the Excel/CSV Architecture Catalogue
- Automatic generation of Business Process as Code in C# or YAML from Excel/CSV Architecture Catalogue
- Command Line Interface (CLI) used for automating AaC generation, AaC querying and diagrams generation


These concepts are borrowed from C4 Model created by Simon Brown.

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# or in YAML. 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# and YAML
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace dotnet.eShop.Architecture.SoftwareSystems
{
public partial class BasketApi : ISoftwareSystemInstance
{
private static readonly string ALIAS = "dotnet.eShop.Architecture.SoftwareSystems.BasketApi";
public static SoftwareSystem Instance => new SoftwareSystem(ALIAS, "Basket Api")
{
Description = "",
Boundary = Boundary.Internal
};
public partial class Containers
{
}
public partial class Interfaces
{
}
}
}dotnet:
eShop:
Architecture:
SoftwareSystems:
BasketApi:
Label: Basket Api
Boundary: Internal
Description: ''
Containers: {}
Interfaces: {}// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace dotnet.eShop.Architecture.SoftwareSystems
{
public partial class BasketApi
{
public partial class Containers
{
public partial class Grpc : IContainerInstance
{
private static readonly string ALIAS = "dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc";
public static Container Instance => new Container(dotnet.eShop.Architecture.SoftwareSystems.BasketApi.ALIAS, ALIAS, "Grpc")
{
ContainerType = ContainerType.Api,
Description = "",
Technology = "",
Boundary = Boundary.Internal
};
public partial class Components
{
}
public partial class Interfaces
{
}
public partial class Entities
{
}
}
}
}
}dotnet:
eShop:
Architecture:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Label: Grpc
Description: ''
ContainerType: Api
Boundary: Internal
Technology: ''
Components: {}
Interfaces: {}
Entities: {}
// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace dotnet.eShop.Architecture.SoftwareSystems
{
public partial class BasketApi
{
public partial class Containers
{
public partial class Grpc
{
public partial class Components
{
public partial class BasketService : IComponentInstance
{
private static readonly string ALIAS = "dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService";
public static Component Instance => new Component(dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc.ALIAS, ALIAS, "Basket Service")
{
ComponentType = ComponentType.None,
Description = "",
Technology = ""
};
public partial class Interfaces
{
}
}
}
}
}
}
}dotnet:
eShop:
Architecture:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Components:
BasketService:
Label: Basket Service
ComponentType: None
Description: ''
Technology: ''
Interfaces: {}// <auto-generated/>
using C4InterFlow.Structures;
using C4InterFlow.Structures.Interfaces;
namespace dotnet.eShop.Architecture.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
{
private static readonly string ALIAS = "dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.Interfaces.GetBasket";
public static Interface Instance => new Interface(dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.ALIAS, ALIAS, "Get Basket")
{
Description = "",
Path = "",
IsPrivate = false,
Protocol = "",
Flow = new Flow(ALIAS)
.Use("dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.GetBasketAsync")
.If(@"data is not null")
.Use("dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Grpc.Components.BasketService.Interfaces.MapToCustomerBasketResponse")
.EndIf(),
Input = "",
InputTemplate = "",
Output = "",
OutputTemplate = ""
};
}
}
}
}
}
}
}
}dotnet:
eShop:
Architecture:
SoftwareSystems:
BasketApi:
Containers:
Grpc:
Components:
BasketService:
Interfaces:
GetBasket:
Label: Get Basket
Description: ''
Path: ''
IsPrivate: false
Protocol: ''
Flow:
Flows:
- Type: Use
Expression: dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.GetBasketAsync
- Type: If
Expression: data is not null
Flows:
- Type: Use
Expression: dotnet.eShop.Architecture.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.

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:
- Software Systems - all Interfaces of all Software Systems 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
-
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 |
|---|---|---|---|
| Software Systems | 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:
dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Data.Components.RedisBasketRepository.Interfaces.*This will select all Interfaces of RedisBasketRepository Component of Data Container of BasketApi Software System in dotnet.eShop.Architecture Namespace.
dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.Data.Components.*.Interfaces.*This will select all Interfaces of all Components of Data Container of BasketApi Software System in dotnet.eShop.Architecture Namespace.
dotnet.eShop.Architecture.SoftwareSystems.BasketApi.Containers.*.Components.*.Interfaces.*This will select all Interfaces of all Components of all Container of BasketApi Software System in dotnet.eShop.Architecture Namespace.
dotnet.eShop.Architecture.SoftwareSystems.*.Containers.*.Components.*.Interfaces.*This will select all Interfaces of all Components of all Containers of all Software Systems in dotnet.eShop.Architecture Namespace.
dotnet.eShop.Architecture.SoftwareSystems.*.Containers.*.Interfaces.*This will select all Interfaces of all Containers of all Software Systems in dotnet.eShop.Architecture Namespace.
dotnet.eShop.Architecture.SoftwareSystems.*.Interfaces.*This will select all Interfaces of Software Systems in dotnet.eShop.Architecture Namespace.
- Java PlantUML .jar (embedded within the project).
- Choose a strategy for Architecture as Code generation.
- Get your teams to own their Architecture by expressing it in YAML or C# code
- Use automation to bring AaC from multiple Repos into a centralised Architecture Repo and use it to generate diagrams for the whole Enterprise.
- Utilize a set of CLI capabilities via C4InterFlow CLI App
- Expose CLI capabilities via your own C# Console Application.
- It's a good way of extending it with custom commands.
- For help or to report issues, please raise GitHub issues.
- Adhere to .NET coding standards.
- Work on approved issues only.
- Submit contributions via Pull Requests for review.
- Inspired by the C4 Model, C4-PlantUML project, and c4sharp project.
Note: This document is subject to change. Users are encouraged to check back regularly for updates.