Model C4, czyli cztery kroki do udokumentowania architektury oprogramowania

Czy można zobrazować i jednocześnie udokumentować architekturę oprogramowania w zaledwie czterech krokach? Zgodnie z założeniami modelu C4, większość systemów można przedstawić za pomocą maksymalnie czterech diagramów w sposób na tyle szczegółowy, że umożliwi on implementację architektury systemowej przez zespoły programistyczne.

W FIS-SST postanowiliśmy sprawdzić powyższe założenia, wdrażając podejście C4 w ramach prac nad zupełnie nową aplikacją, tworzoną przez zespół R&D. W artykule tym prezentujemy zarówno zasady dokumentowania architektury, jak i szczegółowy przykład użycia C4 w praktyce, krok po kroku.

Na czym polega tworzenie architektury sytemu według metodyki C4?

Twórcą metodyki C4 jest Simon Brown – zaproponował on czterostopniowy model dokumentowania architektury, ukierunkowany na odbiorcę. Model ten charakteryzuje podejście dość przejrzyste, z niewieloma zasadami oraz elementami semantycznymi, jakie powinny być stosowane podczas tworzenia architektury systemu. Ze względu na wyżej wskazane cechy, podejście takie harmonizuje ze zwinnymi metodykami tworzenia oprogramowania.

Istotnym elementem tego modelu jest wspomniane nastawienie na odbiorcę. Dla przykładu, managera lub klienta nie interesuje podział modelowanego systemu na środowiska, czy fizyczne maszyny, na których zostaną zainstalowane komponenty systemu. Ważnymi dla nich elementami będą funkcjonalność systemu oraz jego współdziałanie z otoczeniem zewnętrznym. Z kolei zupełnie innymi elementami architektury zainteresowane będą zespoły programistyczne. I tu z pomocą przychodzi metodyka C4, która wykorzystuje cztery rodzaje diagramów o różnych poziomach abstrakcji, a mianowicie:

  • Diagram kontekstu systemowego (Context)
  • Diagram kontenerów (Container)
  • Diagram komponentów (Component)
  • Diagram klas (Class)

Diagramy te na różnym poziomie abstrakcji pozwalają przedstawić statyczną strukturę systemu oraz sposób, w jaki jego elementy ze sobą i otoczeniem współdziałają. Poziomy te można porównać do zoomu w mapach. Wraz ze zwiększeniem stopnia powiększenia, pojawiają się nowe, bardziej szczegółowe, informacje dotyczące wybranego skrawka mapy. Analogia ta znajduje swoje odzwierciedlenie w oprogramowaniu, gdzie im niższy poziom, tym informacje są bogatsze w szczegóły.

Diagramy te są opcjonalne i w zależności od wielkości i złożoności systemu, niektóre ich rodzaje nie zawsze są celowe. Obowiązuje ogólna zasada: jeżeli nie zidentyfikowałeś osoby, która by była zainteresowana informacjami zawartymi na danym poziomie, to nie twórz diagramu tego poziomu.

Bardzo ważnym aspektem, wpływającym na akceptowalność diagramów tworzonych w metodyce C4, jest ich czytelność wywodząca się z przejrzystej różnorodności semantycznych elementów jakimi metodyka C4 się posiłkuje. Zastosowanie uniwersalnej i uprzednio uzgodnionej notacji, pozwala w łatwy i intuicyjny sposób przedstawić złożoność modelowanego systemu. Mianowicie, każdy element diagramu powinien posiadać nazwę, oznaczony typ (jak np. „osoba”, „system”, „kontener”, czy też „komponent”) oraz krótki opis pełnionej funkcji.

Poziom 1 – Kontekst Systemu

Punktem wyjściowym do tworzenia architektury jest kontekst, w jakim dany system działa. Diagram tego poziomu zawiera informacje dotyczące architektury systemu charakteryzujące się dużym poziomem abstrakcji (tzw. widok z lotu ptaka, czy też big picture). Na poziomie tym przedstawiony jest modelowany system, będący centralnym elementem diagramu, a także jego interakcje z zewnętrznymi aktorami lub systemami. Stosowane technologie bądź protokoły nie interesują odbiorcy diagramu, którym zazwyczaj jest zarząd bądź klient. Diagram przedstawiający kontekst systemu powinien być zrozumiały i znany każdemu uczestnikowi przedsięwzięcia.

Poziom 2 – Diagram Kontenerów

Wchodząc w głąb systemu uwidacznia się niższy poziom abstrakcji – struktura systemu oparta o kontenery, które odwzorowują rozkład odpowiedzialności elementów systemu realizujących procesy biznesowe. Kontenerem może być osobno uruchamiana bądź instalowana jednostka, wykonująca kod lub zapisująca dane.
Często poziom ten jest nazywany „architekturą wdrożeniową” – opisuje jak wdrażamy system, z jakich elementów się on składa i na jakich elementach infrastruktury będzie instalowany. Typowymi elementami występującymi na tym poziomie abstrakcji są aplikacje mobilne, aplikacje webowe, bazy danych, czy kolejki systemowe. Co więcej, aspekty techniczne – jak typ magazynu danych czy protokoły użyte w komunikacji pomiędzy kontenerami – są nieodzowną częścią tego poziomu. Diagram zawiera również systemy zewnętrzne, widoczne na poprzednim poziomie, ilustrując komunikację kontenerów z otoczeniem (światem zewnętrznym). Głównym odbiorcą tego diagramu jest szeroko rozumiany DevOps – osoby odpowiadające za rozwój, utrzymanie lub zapewnienie jakości systemu – oraz architekci i programiści.

Poziom 3 – Komponenty

Na tym poziomie architektury staramy się przedstawić wnętrze pojedynczego kontenera składającego się z komponentów. A czym tak właściwie jest komponent? W IT jest to bardzo wieloznaczne pojęcie, które różne osoby rozumieją w zupełnie inny sposób. W podejściu C4 komponent odzwierciedla „prawdziwą abstrakcję” na poziomie kodu, czyli zgrupowanie kodu mające wspólną bazę, znaczenie czy funkcjonalność. Osobom znającym metodykę Domain-Driven Design nie obce powinno być pojęcie „bounded context”, które bardzo dobrze odzwierciedla pojęcie komponentu w kontekście C4. Na tym poziomie widoczne są aspekty technologiczne odnoszące się do implementacji komponentu, czyli użyty framework, czy język programowania.

Poziom 4 – Klasy

Pojedyncze klasy są tematem najniższego poziomu architektury C4. Zidentyfikowane w poprzednim kroku komponenty posiadają wewnętrzną strukturę, którą można rozłożyć na klasy lub inne artefakty. Modelując duże i złożone systemy, komponenty mogą być tak dużą jednostką architektoniczną, że na tym poziomie uwypukla się architektura aplikacji – rozkład na warstwy lub inne style architektoniczne.

Zważywszy na fakt, że grupą docelową tego poziomu są programiści i architekci, czyli osoby operujące na kodzie, poziom ten można zwizualizować za pomocą diagramu klas, który jest składową języka UML. Krok ten jest opcjonalny i ze względu na dużą dynamikę zawartych w nim artefaktów diagram powinien być tworzony przy użyciu narzędzi (np. IDE) i tylko gdy zaistnieje uzasadniona jego potrzeba.

Cztery diagramy, czyli C4 w praktyce

Mamy nadzieję wykroczyć poza standardowe, czysto teoretyczne przykłady dokumentowania architektury, prezentując faktycznie wykorzystane w praktyce diagramy, które stworzyliśmy na potrzeby aplikacji projektowanej w FIS-SST. Model C4 wykorzystaliśmy do udokumentowania architektury nowopowstającej aplikacji opartej na mikroserwisach (roboczo nazwanej „Food Ordering”). Wyniki poszczególnych etapów naszej pracy przedstawiamy poniżej.

Krok 1: Kontekst Systemu

Najpierw zdefiniowaliśmy kontekst systemu – poziom najbardziej ogólny, jako elementy którego wskazaliśmy użytkownika, aplikację Food Ordering oraz dwa systemy zewnętrzne (Notifier i Identity Provider), z którymi aplikacja będzie się komunikować.

Diagram: Poziom 1 – Kontekst Systemu

Jak widać na zamieszczonym diagramie, każdy z elementów zawiera krótki opis funkcji, jaką pełni w systemie. Od razu wiadomo zatem, za co odpowiedzialny jest np. Notifier, a także z jakimi elementami systemu jest bezpośrednio związany.

Krok 2: Kontenery

Kolejnym krokiem było stworzenie diagramu przedstawiającego kontenery, rozumiane jako jednostki deploymentu. Z racji na wykorzystanie w naszej aplikacji mikroserwisów, diagram obrazujący kontenery okazał się najbardziej obszernym i rozbudowanym. Przedstawia on bowiem nie tylko wszystkie mikroserwisy, ale również pozostałe istotne elementy infrastruktury, jak bazy danych czy szyny wymiany danych, wraz z istniejącymi zależnościami i wymienianymi wiadomościami. Na tym poziomie szczegółowości wskazaliśmy też które mikroserwisy komunikują się z systemami zewnętrznymi. Czytając diagram, z łatwością zidentyfikować można granice systemu.

Z racji na dużą szczegółowość diagramu, przedstawiamy go poniżej w dwóch wersjach – widoku ogólnego i widoku szczegółowego (będącego zbliżeniem wyłącznie na aplikację Food Ordering).

Diagram: Poziom 2 – Kontenery – widok ogólny
Diagram: Poziom 2 – Kontenery – widok szczegółowy

Krok 3: Komponenty

Diagram przedstawiający komponenty ukazuje z jakich elementów składają się wyodrębnione we wcześniejszym kroku kontenery. Pozwala również na wskazanie wysokopoziomowych zależności między komponentami, co może być szczególnie przydatne w architekturze opartej o mikroserwisy. Postanowiliśmy zagłębić się w komponent „User Microservice”, jako jeden z bardziej złożonych elementów aplikacji. Nie charakteryzowaliśmy innych komponentów, gdyż doszliśmy do wniosku, że będą one miały podobną – często prostszą – strukturę.

W naszej aplikacji wykorzystany zostanie framework Spring (m.in. Spring Boot i Spring Cloud). W związku z powyższym na diagramie tego poziomu zawarliśmy elementy związane z wybraną technologią  – kontrolery, serwisy i repozytoria – oraz powiązania między nimi. Zidentyfikowaliśmy również inne komponenty systemu, jak Event Listener nasłuchujący na zdarzenia przychodzące z Message Busa, czy Time Schedulera realizującego logikę biznesową w wyznaczonych interwałach czasowych.

Diagram: Poziom 3: Komponenty – diagram mikroserwisu „User”

A co z czwartym krokiem?

Powyższe przykłady odnoszą się do trzech z czterech dostępnych w metodyce C4 poziomów – ostatni z nich, poziom przedstawienia klas, często wskazywany jest jako opcjonalny. Uznaliśmy, że dla naszej aplikacji, będącej jeszcze w fazie planowania i projektowania, krok ten jest na chwilę obecną zbędny. Co więcej, diagram klas jest najbardziej podatny na zmiany wynikające z dynamiki rozwoju projektów.

I tu pojawia się pytanie – jak model C4 poradzi sobie z dynamicznym rozwojem oprogramowania? Wytwarzanie oprogramowania jest procesem żywym wiążącym się z nieprzerwanym wprowadzaniem zmian, także i tych wysokopoziomowych. Diagram klas jest tym elementem modelu C4, który zmieniać będzie się najczęściej. Wskazanym może być zatem wykorzystanie odpowiednich narzędzi, dostępnych chociażby w ramach IDE, pozwalającym generować schematy klas i zależności między nimi. Również diagram komponentów – chociaż w mniejszym stopniu – jest podatny na zmiany, w szczególności w przypadku architektury wykorzystującej mikroserwisy. Natomiast diagram kontenerów i diagram kontekstu systemu, z racji na wyższy poziom abstrakcji, wymagać będą znacznie rzadszych zmian.

Podsumowanie

Jedną z wytycznych metodyki C4 jest uzgodnienie w zespole wspólnego zestawu abstrakcyjnych pojęć używanych do dokumentowania architektury oprogramowania, co zwiększa spójność i przejrzystość komunikacji. Co istotne, w ramach C4 używamy prostych, często samodefiniujących się diagramów i jednej, określonej notacji. A zatem wdrażając metodykę C4 korzystamy z tego samego zestawu abstrakcji i tej samej notacji  na każdym poziomie szczegółowości, w komunikacji z każdym możliwym odbiorcą – zarządem spółki, klientem, zespołem DevOps, czy też zespołami programistów i testerów.

Zastosowanie modelu C4 nie wyklucza użycia innych sposobów dokumentowania architektury oprogramowania. Wręcz przeciwnie, model ten jest w pełni kompatybilny np. z szablonem Arc42 i może również zostać uzupełniony o notację UML.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *