software-architecture-models

The C4 model

This page is in full attributed to the original author of the C4-model, Simon Brown. It is a brief recap of the C4-model in a format that complies with the approach in this material. All formulations are copied and remixed from the original text from the C4 Model.

Core concepts

A software system is made up of one or more containers (applications and data stores), each of which contains one or more components, which in turn are implemented by one or more code elements (classes, interfaces, objects, functions, etc). And people may use the software systems that we build.

More formally, we can define it as this:

Relationships between the concepts

By putting together the definitions from the previous section we can rephrase it with an emphasis on the relationships between the concepts.

The following diagram depicts the relationships between the core concepts using one-to-many relationships “–<” and many-to-many relationships “>–<”.

                            usage
        Software System  >---------<  Person
             |
composition  |
            / \
          Container
             |
composition  |
            / \
          Component
             |
composition  |
            / \
        Code Element

It is worth noticing the following:

Another way to depict the above is shown here:

Notation

The C4-model is notation-agnostic in theory. It is clearly stated on the C4 Model that the focus of the model is on the concepts and that notation can be selected freely.

In reality, the notation of C4 in many organizations follows the conventions established on the C4 Model website which is summarized here:

The following provides some realistic examples of how the notation can be applied in different kinds of diagrams. It should be clear how one can zoom in and out of various details.

Elaboration of core concepts

In real terms, a Container is something like:

A Container is essentially a context or boundary inside which some code is executed or some data is stored. And each container is a separately deployable/runnable thing or runtime environment, typically (but not always) running in its own process space. Because of this, communication between containers typically takes the form of an inter-process communication.

If you’re using a language like Java or C#, the simplest way to think of a Component is that it’s a collection of implementation classes behind an interface. Aspects such as how those components are packaged (e.g. one component vs many components per JAR file, DLL, shared library, etc) is a separate and orthogonal concern.