Przewodnik po składni modelu C4 w PlantUML

Co to jest diagram modelu C4?

Rozszerzenie diagram modelu C4 to hierarchiczny, czteropoziomowy ramowy model architektury zaprojektowany do dokumentowania architektury oprogramowania z różnym stopniem szczegółowości. Stworzony przez Simona Browna, model C4 unika nieprecyzyjnych pól i linii, strukturalizując mapy systemów w cztery wyraźne poziomy abstrakcji: Zasięg (zasięg na poziomie systemu), Pojemnik (aplikacje i magazyny danych), Składnik (moduły wewnętrzne), oraz Kod (realizacje na poziomie klas).

Aby skutecznie zaimplementować ten model w tekście, inżynierowie używają oficjalnej biblioteki rozszerzeń C4-PlantUML rozszerzenia biblioteki standardowej. Ta biblioteka zastępuje surowe kształty UML specjalnymi makrami, które automatycznie wstrzykują różne kolory, kształty i pola metadanych dla użytkowników, systemów i baz danych. Dzięki VPasCode, możesz czysto zdefiniować te zagnieżdżone środowiska w kodzie. Silnik układu dynamicznie kieruje wektory połączeń i skaluje pola tekstowe, nie zruinowując geometrii układu.

Podstawowy przewodnik składniowy: elementy i konstrukcje

Tworzenie poprawnego modelu C4 przy użyciu PlantUML opiera się na importowaniu odpowiednich plików bibliotek, wybieraniu makr strukturalnych, ustalaniu granic oraz używaniu specjalistycznych połączeń relacyjnych.

1. Importowanie plików biblioteki standardowej C4

Rozszerzenie C4-PlantUML rozszerzenie jest podzielone na pojedyncze pliki, które bezpośrednio odpowiadają poszczególnym poziomom modelu abstrakcji. Aby uniknąć spowolnienia wydajności lub błędów kompilatora, powinieneś importować tylko ten konkretny warstwowy plik, na który jest skierowany twój diagram:

@startuml
' Dołącz wymagany plik warstwy C4
!include <C4/C4_Context>
' Użyj C4_Container lub C4_Component dla głębszych map architektonicznych

2. Deklarowanie podstawowych aktorów i systemów (poziom kontekstu)

Na poziomie kontekstu systemu, modelujesz komponenty wewnętrzne, zależności zewnętrzne oraz ludzkich użytkowników końcowych. Biblioteka standardowa oferuje specjalne makra, które przyjmują identyfikator, etykietę wizualną oraz opcjonalny opis:

  • Osoba(id, "Etykieta", "Opis") — Reprezentuje profil użytkownika lub aktora systemu.
  • System(id, "Etykieta", "Opis") — Reprezentuje podstawowy wewnętrzny ekosystem aplikacji lub usługi oprogramowania.
  • System_Ext(id, "Etykieta", "Opis") — Reprezentuje system zewnętrzny lub zależność od interfejsu API firm trzecich (wyświetlany w jasno zdefiniowanej paletcie szarości).
@startuml C4_Elements
!include <C4/C4_Context>
Person(customer, "Klient bankowy", "Klient z kontem osobistym")
System(banking_sys, "Główny system bankowy", "Zarządza transakcjami finansowymi")
System_Ext(mail_sys, "Usługa e-mail", "Wewnętrzny bramka powiadomień SMTP")

3. Rozpraszanie granic (poziomy kontenera i komponentu)

Gdy głębiej analizujesz warstwę kontenera, modelujesz aplikacje internetowe, mikroserwisy i bazy danych. Możesz izolować te elementy wewnętrzne w wyraźnym logicznym polu granicznym, używającSystem_Boundary() makra otoczki:

!include <C4/C4_Container>

System_Boundary(c1, "Ekosystem systemu e-handlu") {
    Container(web_app, "Aplikacja jednostronicowa", "React & TypeScript", "Dostarcza funkcje użytkownika poprzez przeglądarkę")
    ContainerDb(database, "Baza danych relacyjna", "PostgreSQL", "Przechowuje profile użytkowników i historie księgowości")
}

4. Mapowanie relacji technicznych

Zamiast polegać na podstawowych linii przerywanych, C4 wykorzystuje jasno zdefiniowane makra komunikacji w formacieRel(From_ID, To_ID, "Etykieta", "Technologia"). Dzięki temu Twoje mapy architektury są bardzo czytelne, ponieważ wymusza się, by każda połączenie wyraźnie określało swoje przeznaczenie i podstawowy protokół transportowy (np. HTTPS, gRPC lub AMQP):

!include <C4/C4_Container>

Person(customer, "Klient bankowy", "Klient z kontem osobistym")
System(banking_sys, "Główny system bankowy", "Zarządza transakcjami finansowymi")
System_Ext(mail_sys, "Usługa e-mail", "Wewnętrzny bramka powiadomień SMTP")

System_Boundary(c1, "Ekosystem systemu e-handlu") {
    Container(web_app, "Aplikacja jednostronicowa", "React & TypeScript", "Dostarcza funkcje użytkownika poprzez przeglądarkę")
    ContainerDb(database, "Baza danych relacyjna", "PostgreSQL", "Przechowuje profile użytkowników i historie księgowości")
}
Rel(customer, web_app, "Wykorzystuje funkcje sklepu poprzez", "HTTPS")
Rel(web_app, database, "Odczytuje i zapisuje dane transakcyjne poprzez", "SQL/TCP")

Najlepsze praktyki dla czytelnych architektur C4

  • Nigdy nie mieszać poziomów abstrakcji: Zachowaj skupienie diagramów na jednym poziomie. Nie mieszkaj szczegółowych wewnętrznych komponentów oprogramowania w mapie kontekstu systemu na wysokim poziomie. Jeśli system staje się zbyt złożony, rozdziel go na osobny, dedykowany diagram poziomu kontenera.
  • Jasno określ technologie: Zawsze korzystaj z czwartego parametru w swoichRel() makrach, aby wyraźnie określić dokładną technologię lub protokół używany (np."JSON/HTTPS" lub "JDBC"). Dzięki temu zespół ma kluczowy kontekst implementacyjny na pierwszy rzut oka.
  • Wykorzystaj zastępowania układu kierunkowego: Jeśli komponenty zaczynają się nieporządnie nakładać, użyj makr relacji kierunkowych (takich jak Rel_D() dla dół, Rel_R() dla prawo, lub Rel_L() dla lewo) w celu ręcznego wyrównania przepływu architektonicznego.

Przykłady PlantUML C4 z rzeczywistego świata

Przykład 1: Układ kontekstu systemu na wysokim poziomie (poziom 1)

Ten funkcjonalny szkic modeluje standardowy diagram kontekstu systemu poziomu 1, szczegółowo opisując sposób, w jaki klient interakcjonuje z aplikacją internetowego bankowości oraz jej zależnościami zewnętrznymi.

@startuml
!include <C4/C4_Context>

tytuł Diagram kontekstu systemu dla systemu bankowości internetowej

Osoba(klient, "Klient bankowości osobistej", "Klient banku posiadający konta osobiste.")
System(system_bankowy, "System bankowości internetowej", "Umożliwia klientom przeglądanie informacji finansowych i przeprowadzanie przelewów.")
System_Zew(system_mailowy, "System poczty e-mail", "Wewnętrzny klaster serwerów pocztowych korporacyjnych SendGrid.")

Rel(klient, system_bankowy, "Używa panelu online przez")
Rel_P(system_bankowy, system_mailowy, "Wysyła ostrzeżenia i kody weryfikacyjne przy użyciu", "SMTP")
@enduml

Analiza składni: Ten diagram skupia się wyłącznie na wysokim poziomie szczegółowości. Makro System_Zew automatycznie stosuje profil koloru szarego do usługi poczty e-mail, wizualnie oddzielając system główny od zależności zewnętrznych. Makro Rel_P zmusza silnik układu do umieszczenia węzła poczty bezpośrednio po prawej stronie bloku systemu bankowego.

Przykład 2: Głęboka analiza topologii kontenerów mikroserwisów (poziom 2)

Ten zaawansowany szkic przedsiębiorstwa rozkłada system na jego składające się aplikacje kontenerów i izolowane magazyny danych, pokazując, jak ruch internetowy przepływa przez bramę interfejsu API do mikroserwisów backendowych.

@startuml
!include <C4/C4_Container>

tytuł Diagram kontenerów dla bramy portalu płatności

Osoba(sprzedawca, "Partner internetowy", "Integruje punkty końcowe płatności platformy na swoich stronach internetowych.")

Granica_Systemu(ekosystem_bramy, "Ekosystem bramy płatności") {
    Kontener(brama_api, "Proxy routingu API", "Nginx", "Przechwytuje pochodzące połączenia, obsługuje limity szybkości i równoważy węzły.")
    Kontener(usługa_auth, "Mikroserwis tożsamości", "Go & OAuth2", "Weryfikuje tokeny i zakresy API deweloperów.")
    Kontener(usługa_txn, "Dziennik transakcji", "Java Spring Boot", "Przetwarza płatności i zarządza kontami w dzienniku.")
    KontenerDb(dziennik_db, "Magazyn danych dziennika", "CockroachDB", "Implementuje rozproszone schematy tabel zgodne z ACID.")
}

' Przepływ ruchu płynnie przebiega przez wewnętrzne cele kontenerów
Rel(sprzedawca, brama_api, "Wysyła dane płatności przez", "HTTPS/JSON")
Rel_D(brama_api, usługa_auth, "Weryfikuje przychodzące tokeny przez", "gRPC")
Rel_D(brama_api, usługa_txn, "Przekazuje działania zakupowe do", "gRPC")
Rel_P(usługa_txn, dziennik_db, "Trwa trwałość wpisów dziennika przez", "SQL/TLS")
@enduml

Rozbicie składni: Korzystając z System_Boundary makro otoczki, wewnętrzne składniki są czysto grupowane razem wewnątrz jasno zdefiniowanego pudełka granicznego. Specjalistyczne makro ContainerDb makro renderuje magazyn danych za pomocą wyraźnego ikony cylindra bazy danych, co jasno pokazuje podział między środowiskami obliczeniowymi a warstwami trwałego przechowywania danych.

Przewijanie do góry