Skip to content
Slava Vedernikov edited this page Jul 9, 2024 · 39 revisions
C4 InterFlow - Logo
C4InterFlow = C4 Model + Interfaces + Flows

What is C4InterFlow?

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.

Concepts

Structural concepts

C4InterFlow Metamodel

C4InterFlow - Metamodel

Person, Software System, Container and Component

These concepts are borrowed from C4 Model created by Simon Brown. C4 Model - Abstractions Image source: www.c4model.com

Interface and Flow

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.

Business Process, Activity and Actor

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.

Architecture as Code (AaC) Domain Specific Language (DSL)

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

Software System

C#

// <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
        {
        }
    }
}

YAML

dotnet:
  eShop:
    Architecture:
      SoftwareSystems:
        BasketApi:
          Label: Basket Api
          Boundary: Internal
          Description: ''
          Containers: {}
          Interfaces: {}

JSON

{
    "dotnet": {
        "eShop": {
            "Architecture": {
                "SoftwareSystems": {
                    "BasketApi": {
                        "Label": "Basket Api",
                        "Boundary": "Internal",
                        "Description": "",
                        "Containers": {},
                        "Interfaces": {}
                    }
                }
            }
        }
    }
}

Container

C#

// <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
                {
                }
            }
        }
    }
}

YAML

dotnet:
  eShop:
    Architecture:
      SoftwareSystems:
        BasketApi:
          Containers:
            Grpc:
              Label: Grpc
              Description: ''
              ContainerType: Api
              Boundary: Internal
              Technology: ''
              Components: {}
              Interfaces: {}
              Entities: {}

JSON

{
    "dotnet": {
        "eShop": {
            "Architecture": {
                "SoftwareSystems": {
                    "BasketApi": {
                        "Containers": {
                            "Grpc": {
                                "Label": "Grpc",
                                "Description": "",
                                "ContainerType": "Api",
                                "Boundary": "Internal",
                                "Technology": "",
                                "Components": {},
                                "Interfaces": {},
                                "Entities": {}
                            }
                        }
                    }
                }
            }
        }
    }
}

Component

C#

// <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
                        {
                        }
                    }
                }
            }
        }
    }
}

YAML

dotnet:
  eShop:
    Architecture:
      SoftwareSystems:
        BasketApi:
          Containers:
            Grpc:
              Components:
                BasketService:
                  Label: Basket Service
                  ComponentType: None
                  Description: ''
                  Technology: ''
                  Interfaces: {}

JSON

{
    "dotnet": {
        "eShop": {
            "Architecture": {
                "SoftwareSystems": {
                    "BasketApi": {
                        "Containers": {
                            "Grpc": {
                                "Components": {
                                    "BasketService": {
                                        "Label": "Basket Service",
                                        "ComponentType": "None",
                                        "Description": "",
                                        "Technology": "",
                                        "Interfaces": {}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Component Interface

C#

// <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 = ""
                                };
                            }
                        }
                    }
                }
            }
        }
    }
}

YAML

dotnet:
  eShop:
    Architecture:
      SoftwareSystems:
        BasketApi:
          Containers:
            Grpc:
              Components:
                BasketService:
                  Interfaces:
                    GetBasket:
                      Label: Get Basket
                      Description: ''
                      Path: ''
                      IsPrivate: false
                      Protocol: ''
                      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: ''

JSON

{
    "dotnet": {
        "eShop": {
            "Architecture": {
                "SoftwareSystems": {
                    "BasketApi": {
                        "Containers": {
                            "Grpc": {
                                "Components": {
                                    "BasketService": {
                                        "Interfaces": {
                                            "GetBasket": {
                                                "Label": "Get Basket",
                                                "Description": "",
                                                "Path": "",
                                                "IsPrivate": false,
                                                "Protocol": "",
                                                "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": ""
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Visualisation

Diagram Level of Details

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.

C4 Model - Levels Image source: www.c4model.com

Examples

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)
C4 InterFlow - Diagrams Type - C4 C4 InterFlow - Diagrams Type - C4 C4 InterFlow - Diagrams Type - C4

Diagram Scope

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

Diagram Type

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 InterFlow - Diagrams Type - C4 Static

  • 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 InterFlow - Diagrams Type - C4

  • 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

C4 InterFlow - Diagrams Type - Sequence

  • Sequence - a Plant UML Sequence diagram that can be generated for the following Scopes:
    • Software System Interface
    • Container Interface
    • Component Interface
    • Business Process

C4 InterFlow - Diagrams Type - Sequence

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

Querying Architecture as Code

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:

Generating diagrams

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:

Example 1

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.

Example 2

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.

Example 3

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.

Example 4

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.

Example 5

dotnet.eShop.Architecture.SoftwareSystems.*.Containers.*.Interfaces.*

This will select all Interfaces of all Containers of all Software Systems in dotnet.eShop.Architecture Namespace.

Example 6

dotnet.eShop.Architecture.SoftwareSystems.*.Interfaces.*

This will select all Interfaces of Software Systems in dotnet.eShop.Architecture Namespace.


Note: This document is subject to change. Users are encouraged to check back regularly for updates.

Clone this wiki locally