Mermaid ve Structurizr DSL: Markdown İçinde Diyagram, Model Tabanlı C4 ve Hangisini Seçmeli?
Mermaid, GitHub ve Azure DevOps Markdown'ında doğrudan render edilen hızlı diyagramlar için, Structurizr DSL ise tek bir modelden tutarlı C4 view'ları türetmek için doğru araçtır. Bu yazıda serinin diyagramlarını Mermaid'e çevirip söz dizimi tuzaklarını gerçek çıktılarla gösteriyor, aynı container diyagramını Structurizr ile çiziyor ve PlantUML, Mermaid ve Structurizr'i karşılaştırıyoruz.
Sürüm notu: Bu yazıdaki diyagramlar UML (Unified Modeling Language) 2.5.1 ve C4 (Context, Containers, Components, Code) notasyonuyla, Mermaid 12.3.0 (komut satırı aracı Mermaid CLI (Command-Line Interface) 12.2.0) ve Structurizr 2026.10.26 ile render edilmiştir; serinin C# kodları .NET 10 ile denenmiştir.
Önce Tahmin Et: Bu Diyagramda Kaç State Var?
Önceki yazıda PlantUML'e çevirdiğimiz izin talebi state machine'ini bu kez Mermaid'le, doğrudan bir README'nin içine yazıyorsun. Approved durumunun entry davranışı iki işten oluşuyor: bakiyeyi düşmek ve takvime kayıt eklemek. PlantUML'de iki işi noktalı virgülle ayırmıştık, burada da öyle yapıyorsun:
stateDiagram-v2
[*] --> Draft
Draft --> PendingManagerApproval: Submit [hasEnoughBalance]
PendingManagerApproval --> Approved: Approve [hasEnoughBalance]
Approved: Approved
Approved: entry / deductBalance; addCalendarEntry
Approved --> Cancelled: Cancel [!leaveStarted || byHrSpecialist] / refundBalance
Mermaid CLI bu dosyayı hatasız render ediyor, exit code 0. Diyagramda kaç kutu görürsün? Approved kutusunun içinde entry satırı tam olarak nasıl yazar? Cevabı söz dizimi sınırları bölümünde vereceğiz; ipucu, hatasız render edilen her diyagram doğru diyagram değildir.
Mermaid: Markdown'ın İçinde Diyagram
Mermaid, JavaScript ile yazılmış, metinden diyagram üreten bir kütüphane. PlantUML'den farkı nerede render edildiği: Mermaid tarayıcıda çalışır ve bu yüzden platformlar onu doğrudan Markdown render'ına gömebilir. GitHub 2022'den beri mermaid dilli fenced code block'ları diyagram olarak gösteriyor; issue'larda, PR (pull request) açıklamalarında, wiki'de ve repo'daki .md dosyalarında. Bir README'ye eklemek bu kadar:
# Leave module
States of a leave request:
```mermaid
stateDiagram-v2
[*] --> Draft
Draft --> PendingManagerApproval: Submit [hasEnoughBalance]
```
Ayrı bir build adımı, resim dosyası ya da CI (Continuous Integration) job'ı yok; diyagram kodla aynı commit'te değişir ve GitHub onu sayfayı açtığında çizer. Bedeli, render'ın GitHub'ın kullandığı Mermaid sürümüne bağlı olması. GitHub dokümantasyonu bunun için bir yol gösteriyor: içine sadece info yazılmış bir mermaid bloğu, kullanılan sürümü basar. Yeni bir söz dizimini (örneğin 12.0 ile gelen use case diyagramını) README'ye koymadan önce bu kontrolü yap.
Azure DevOps'ta durum biraz farklı. Microsoft Learn'deki Markdown rehberi wiki sayfalarında hem ::: mermaid container söz dizimini hem de standart fenced block'u destekliyor, ama desteklenen diyagram türlerini açıkça listeliyor: sequence, Gantt, flowchart, class, state, user journey, pie, requirement, gitgraph, ER (Entity-Relationship) ve timeline. C4 ve use case listede yok ve rehber "sınırlı söz dizimi desteği" uyarısı yapıyor. Ekip Azure DevOps wiki'sindeyse diyagram türünü buna göre seç.
Yerelde iki araç yeter. Visual Studio Code'un (VS Code) yerleşik Markdown önizlemesi Mermaid çizmez; "Markdown Preview Mermaid Support" eklentisi bu boşluğu doldurur. Komut satırında ise Mermaid CLI'ın mmdc komutu, Chrome tabanlı headless bir tarayıcıyla SVG (Scalable Vector Graphics) ya da PNG (Portable Network Graphics) üretir ve bir Markdown dosyasının içindeki bütün mermaid bloklarını tek seferde render edebilir:
npm install --save-dev @mermaid-js/mermaid-cli@12.2.0
# Tek diyagram
npx mmdc -i states.mmd -o states.svg
# Markdown'daki bütün mermaid bloklarını render et (hata varsa exit code 1)
npx mmdc -i README.md -o out/README.md
Found 2 mermaid charts in Markdown input
✅ ./README-2.svg
✅ ./README-1.svg
✅ out/README.md
Bu ikinci kullanım CI için değerli: GitHub'a güvenmeden önce README'deki diyagramların parse edildiğini kendi pipeline'ında doğrulayabilirsin.
Serinin Diyagramları Mermaid'de
Class diagram. Visibility işaretleri (+, -, #, ~) UML'deki gibi; tip adı attribute'tan önce yazılır, enumeration bir stereotype'tır, *-- composition, --> association, ..> dependency'dir:
classDiagram
direction LR
class LeaveRequest {
+DateRange Period
+int WorkingDays
+string? Reason
+LeaveStatus Status
+Submit(int workingDays, DateTimeOffset now) void
+Approve(Employee approver, string? comment, DateTimeOffset now) void
+Cancel(DateOnly today) void
}
class Approval {
+ApprovalStep Step
+ApprovalDecision Decision
+DateTimeOffset DecidedAt
}
class LeaveStatus {
<<enumeration>>
Draft
PendingManagerApproval
PendingDirectorApproval
Approved
Rejected
Cancelled
}
class Employee {
+string EmployeeNumber
+string FullName
}
LeaveRequest "1" *-- "0..2" Approval : approvals
Approval "0..*" --> "1" Employee : approver
LeaveRequest "0..*" --> "1" Employee : requester
LeaveRequest ..> LeaveStatus
Sequence diagram. Mermaid'de dolu ok başlı senkron mesaj ->>, kesikli reply -->>; activation bar'ı + ve - son ekleriyle ya da activate/deactivate satırlarıyla açıp kapatırsın:
sequenceDiagram
autonumber
actor Employee
participant Form as LeaveRequestFormComponent
participant Api as HrPortal.Api
participant Svc as LeaveRequestService
participant Bal as IBalanceService
Employee->>Form: Submit
Form->>+Api: POST /leave-requests/42/submit
Api->>+Svc: SubmitAsync(42)
Svc->>Bal: HasEnoughBalanceAsync(E-1001, ANNUAL, 5)
Bal-->>Svc: true (remaining 8)
alt enough balance
Svc-->>Api: PendingManagerApproval
Api-->>Form: 200 OK
else insufficient balance
Svc-->>Api: BalanceExceeded
Api-->>Form: 422 ProblemDetails
end
deactivate Svc
deactivate Api
State diagram (stateDiagram-v2). Composite state, choice ve entry davranışları destekleniyor; noktalı virgülün neden #59; olarak yazıldığını birazdan göreceğiz:
stateDiagram-v2
[*] --> Draft
Draft --> PendingManagerApproval: Submit [hasEnoughBalance]
state "Pending Approval" as PendingApproval {
state afterManager <<choice>>
PendingManagerApproval: PendingManagerApproval
PendingManagerApproval: entry / notifyManager
PendingDirectorApproval: PendingDirectorApproval
PendingDirectorApproval: entry / notifyDirector
PendingManagerApproval --> afterManager: Approve [hasEnoughBalance]
afterManager --> PendingDirectorApproval: [requiresDirectorApproval]
}
afterManager --> Approved: [else]
PendingDirectorApproval --> Approved: Approve [hasEnoughBalance]
PendingApproval --> Rejected: Reject [hasComment] / recordApproval
PendingApproval --> Cancelled: Cancel
Approved: Approved
Approved: entry / deductBalance#59; addCalendarEntry
Approved --> Cancelled: Cancel [!leaveStarted || byHrSpecialist] / refundBalance
ER diagram'ın Mermaid hali bir önceki yazının konusuydu; erDiagram'ı Entity Framework Core (EF Core) modelinden ürettiğimiz generator'ı orada yazdık. Mermaid 12.0 ile beta olarak gelen use case diyagramı da artık var; anahtar kelimesi usecase-beta ve dokümantasyon söz diziminin geriye uyumsuz değişebileceğini söylüyor:
usecase-beta
direction LR
actor Employee
actor Manager
actor Director
actor HR("HR Specialist")
systemBoundary "HR Portal - Leave"
UC01("UC-01 Request Leave")
UC02("UC-02 Decide on Leave Request")
UC03("UC-03 Cancel Leave Request")
CheckBalance("Check Balance")
AttachReport("Attach Medical Report")
end
Director --|> Manager
Employee -- UC01
Employee -- UC03
Manager -- UC02
HR -- UC03
UC01 ..> : include CheckBalance
UC02 ..> : include CheckBalance
AttachReport ..> : extend UC01
note for AttachReport "condition: leave type = SICK"
Bütün bloklar mmdc ile hatasız render ediliyor. Use case çıktısında iki şey dikkatimi çekti: «include» ve «extend» okları UML'deki açık ok başı yerine dolu ok başıyla çiziliyor ve use case'in içinde extension point bölmesi yok. Beta diyagram iş görüyor ama notasyon titizliği PlantUML'in gerisinde.
Mermaid'de C4 ve Yerleşim Sorunu
Mermaid'in C4 söz dizimi bilerek C4-PlantUML'e benzetilmiş; Person, Container, ContainerDb, Rel macro'ları aynı. Bir önceki yazının container diyagramının Mermaid hali:
C4Container
title HR Portal - containers
Person(employee, "Employee", "Requests leave")
Person(manager, "Manager", "Approves or rejects")
System_Boundary(hr, "HR Portal") {
Container(web, "Web App", "Angular 22", "Single-page app")
Container(api, "HrPortal.Api", "ASP.NET Core, .NET 10", "Leave, Payroll, Notification modules")
ContainerDb(db, "HR Database", "SQL Server", "Requests, balances, approvals")
ContainerQueue(broker, "Message Broker", "Azure Service Bus", "leave-events topic")
Container(worker, "HrPortal.Worker", ".NET 10 worker", "Notifications and reminders")
}
System_Ext(calendar, "Calendar System", "Corporate calendar")
System_Ext(mail, "E-mail Server", "SMTP relay")
Rel(employee, web, "Submits leave requests", "HTTPS")
Rel(manager, web, "Approves or rejects", "HTTPS")
Rel(web, api, "Calls", "JSON/HTTPS")
Rel(api, db, "Reads and writes", "EF Core")
Rel(api, broker, "Publishes events", "AMQP")
Rel(broker, worker, "Delivers events", "AMQP")
Rel(api, calendar, "Adds leave entries", "HTTPS")
Rel(worker, mail, "Sends e-mails", "SMTP")
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
Benzerlik burada bitiyor. Mermaid'in C4 dokümantasyonu yerleşimin tam otomatik bir algoritmayla yapılmadığını, şekillerin deklarasyon sırasına göre satırlara dizildiğini açıkça yazıyor. UpdateLayoutConfig satır başına kaç şekil olacağını değiştirir, o kadar. Sonuç aşağıdaki figürün solunda: dış sistemler kişilerin altına, sistem sınırının üstüne düşüyor, ilişki etiketleri sınır başlığıyla çakışıyor. Aynı modelin Structurizr'deki hali sağda.

C4-PlantUML'de yerleşimi düzeltmek için kullanılan Lay_R gibi ipuçları Mermaid'de yok ve dokümantasyon bunları eklemeyi planlamadığını söylüyor. PlantUML alışkanlığıyla yazarsan gerçek hata şu:
Error: Lexical error on line 5. Unrecognized text.
..., api, "Calls") Lay_R(web, api)
----------------------^
Mermaid'in bir de architecture-beta diyagramı var (11.1'den beri); cloud servislerini ikonlarla çizmek için tasarlanmış, ama C4'ün eleman tipleri ve notation kuralları onda yok. Mimari dokümantasyon için C4 söz dizimini, sunum için architecture'ı düşün.
Mermaid'in Söz Dizimi Sınırları
Açılıştaki soruya dönelim. Mermaid'in state diagram'ında noktalı virgül bir statement ayırıcıdır. Approved: entry / deductBalance; addCalendarEntry satırı iki statement olarak okunuyor: Approved için "entry / deductBalance" açıklaması ve tek başına addCalendarEntry adında yeni bir state. Render'da diyagramın tepesinde iki yetim kutu belirdi: biri addCalendarEntry, diğeri içinde sadece ; yazan bir kutu. Hata mesajı yok, exit code 0. Çözüm Mermaid'in entity code'u: #59; noktalı virgül karakterini metin olarak yazar ve kutu "entry / deductBalance; addCalendarEntry" olarak çizilir.
Bu küçük örnek Mermaid'le çalışmanın genel kuralını gösteriyor: söz dizimi diyagram türüne göre değişir ve her türün kendi ayrılmış karakterleri var. Use case dokümantasyonu, örneğin, --, -->, ..> gibi dizileri etiket içinde kullanamayacağını ve "First\nSecond" yazımının satır kırmadığını, ters eğik çizgiyi metin olarak bıraktığını ayrıca listeliyor. PlantUML'den kopyala-yapıştır en sık hata kaynağı. İkinci sınır sürüm: GitHub'ın, Azure DevOps'un ve senin yerel mmdc'nin Mermaid sürümleri farklı olabilir; yerelde render edilen beta bir diyagramı daha eski bir sürüm tanımaz ve diyagram yerine hata gösterir. Üçüncü sınır notasyon: Mermaid'in class diagram'ında association class için, sequence diagram'ında found/lost message için doğrudan bir söz dizimi yok. Seride anlattığımız her UML ayrıntısını Mermaid'de arama; sorunun cevabı için gereken kadarını kullan.
Structurizr DSL: Bir Model, Çok View
PlantUML ve Mermaid'de her diyagram ayrı bir metindir. Context diyagramındaki HR Portal kutusu ile container diyagramındaki sistem sınırı iki farklı dosyada iki kez yazılır; birinde adı değişirse diğeri eski kalır. Simon Brown'ın Structurizr DSL'i (Domain-Specific Language) bu sorunu tersine çevirir: önce modeli yazarsın, diyagramlar o modelden türetilen view'lardır.
workspace "HR Portal" "Leave module architecture" {
!identifiers hierarchical
model {
employee = person "Employee" "Requests leave and tracks its status."
manager = person "Manager" "Approves or rejects leave requests."
hrSpecialist = person "HR Specialist" "Manages leave policies and balances."
calendar = softwareSystem "Calendar System" "Corporate calendar." "External"
mail = softwareSystem "E-mail Server" "SMTP relay for notification e-mails." "External"
hrPortal = softwareSystem "HR Portal" "Employee self-service HR system." {
web = container "Web App" "Single-page app for employees, managers and HR." "Angular 22" "Browser"
api = container "HrPortal.Api" "Leave, Payroll and Notification modules (modular monolith)." "ASP.NET Core, .NET 10"
db = container "HR Database" "Leave requests, balances, approvals." "SQL Server" "Database"
cache = container "Cache" "Public holidays and lookup data." "Redis" "Database"
broker = container "Message Broker" "leave-events topic: LeaveRequestApproved etc." "Azure Service Bus" "Queue"
worker = container "HrPortal.Worker" "Sends notifications and approval reminders." ".NET 10 worker"
}
employee -> hrPortal.web "Creates and submits leave requests" "HTTPS"
manager -> hrPortal.web "Approves or rejects requests" "HTTPS"
hrSpecialist -> hrPortal.web "Defines leave types and holidays" "HTTPS"
hrPortal.web -> hrPortal.api "Calls" "JSON/HTTPS"
hrPortal.api -> hrPortal.db "Reads from and writes to" "EF Core / TDS"
hrPortal.api -> hrPortal.cache "Caches holidays in" "RESP"
hrPortal.api -> hrPortal.broker "Publishes events to" "AMQP"
hrPortal.broker -> hrPortal.worker "Delivers events to" "AMQP"
hrPortal.api -> calendar "Adds and removes leave entries" "HTTPS"
hrPortal.worker -> mail "Sends e-mails via" "SMTP"
}
views {
systemContext hrPortal "Context" {
include *
autolayout lr
}
container hrPortal "Containers" {
include *
autolayout lr
}
styles {
element "Element" {
color #ffffff
}
element "Person" {
shape person
background #08427b
}
element "Software System" {
background #1168bd
}
element "Container" {
background #438dd5
}
element "External" {
background #999999
}
element "Database" {
shape cylinder
}
element "Queue" {
shape pipe
}
element "Browser" {
shape webbrowser
}
}
}
}
model bloğu elemanları ve ilişkileri tanımlar; views bloğu hangi view'un hangi elemanları göstereceğini seçer. systemContext hrPortal view'u include * ile HR Portal'ı ve onunla doğrudan ilişkili kişi ve sistemleri gösterir; container'lardan haberi yoktur. container hrPortal view'u aynı modelden container'ları çizer. İlişkiler yukarı doğru toplanır: employee -> hrPortal.web ilişkisi context view'da otomatik olarak Employee → HR Portal olarak görünür, ayrıca yazmazsın. !identifiers hierarchical iç içe elemanlara hrPortal.api gibi noktalı adla erişmeyi sağlar; styles bloğundaki tag'ler (Database, Queue, External) şekil ve rengi belirler.

structurizr local, validate ve export
Structurizr bugün tek bir dağıtım olarak geliyor: Java 21 isteyen structurizr.war ya da structurizr/structurizr Docker image'ı, alt komutlarıyla. Eskiden Structurizr Lite diye ayrı dağıtılan araç artık local komutu; dokümantasyona göre server dışındaki bütün komutlar ücretsiz, server ise hazır binary'lerle kullanıldığında lisans istiyor. Yerelde çalıştırmak:
# workspace.dsl'in bulunduğu klasörü data directory olarak ver
java -jar structurizr.war local ./structurizr
# Docker ile
docker run -it --rm -p 8080:8080 -v "$PWD/structurizr:/usr/local/structurizr" structurizr/structurizr local
http://localhost:8080 adresinde diyagramlar tarayıcıda çizilir, autolayout yerleşimi hesaplar, kutuları elle sürükleyip yerleşimi kaydedebilirsin; DSL'i değiştirip sayfayı yenilediğinde model yeniden okunur. Figürdeki sağ panel bu ekranın görüntüsü.
CI için iki komut önemli. validate modeli parse eder ve bilinmeyen bir elemana referans gibi hataları yakalar. hrPortal.worker yerine hrPortal.workr yazılmış bir DSL'in gerçek çıktısı (yol kısaltıldı):
ERROR com.structurizr.command.ValidateCommand -- The source element "hrPortal.workr" does not exist at line 31 of .../workspace.dsl: hrPortal.workr -> mail "Sends e-mails via" "SMTP"
Exit code 1. Aynı yazım hatasını diğer araçlarda da denedim. Mermaid 12.3'ün C4 parser'ı Rel(workr, mail, ...) satırını "references an unknown shape or boundary" hatasıyla reddetti. C4-PlantUML ise exit code 0 ile render etti ve diyagrama workr adında yeni bir eleman çizdi; yazım hatası sessizce diyagrama girdi. Structurizr'in farkı, kontrolün tek bir diyagramda değil modelde yapılması: eleman bir kez tanımlanır ve her view aynı tanımı kullanır. export ise view'ları başka formatlara döker:
java -jar structurizr.war validate -workspace workspace.dsl
java -jar structurizr.war export -workspace workspace.dsl -format plantuml/c4plantuml -output out
java -jar structurizr.war export -workspace workspace.dsl -format mermaid -output out
Her view için bir dosya çıkar: structurizr-Context.puml, structurizr-Containers.puml, structurizr-Context.mmd, structurizr-Containers.mmd. İkisini de render ettim, ikisi de çalışıyor, ama içeriklerine bakmakta fayda var. Mermaid export'u C4 söz dizimini değil, HTML (HyperText Markup Language) etiketli bir graph LR flowchart'ını üretiyor; C4-PlantUML export'unda ise "External" tag'i C4-PlantUML'in System_Ext macro'suna değil düz System'e dönüşüyor, yani dış sistem ayrımı yalnız renkte kalıyor. Export bir köprüdür; asıl çıktı local ya da Structurizr'in kendi renderer'ıdır.
Hangisini Seçmeli?
Üç aracı aynı İzin modülü üzerinde kullandıktan sonra karşılaştırma:
| Kriter | PlantUML | Mermaid | Structurizr DSL |
|---|---|---|---|
| Notasyon kapsamı | UML'in neredeyse tamamı, C4-PlantUML, Chen ER | Class, sequence, state, ER, C4, beta use case ve architecture | C4 view'ları (system landscape, context, container, component, dynamic, deployment) |
| Render ortamı | Java + Graphviz, yerel jar ya da kendi sunucun | Tarayıcı; GitHub ve Azure DevOps Markdown'ında doğrudan | local (tarayıcıda), Docker, export |
| Model tutarlılığı | Her diyagram ayrı metin | Her diyagram ayrı metin | Tek model, view'lar türetilir; validate referansları kontrol eder |
| Yerleşim kontrolü | Graphviz otomatik, gizli ok ve yön ipuçları | C4'te deklarasyon sırası; diğerlerinde otomatik | autolayout ve tarayıcıda elle sürükleme |
| CI doğrulaması | --check-syntax, exit 200 | mmdc, exit 1 | validate, exit 1 |
| Öğrenme eğrisi | Orta, diyagram türü başına söz dizimi | Düşük, ama türler arası tutarsız | Orta, model ve view kavramı |
Benim kuralım şöyle. Repo'daki README ve PR açıklamaları için Mermaid: sürtünmesiz, herkes görüyor, küçük sequence ve state diyagramlarına yetiyor. UML'in titizliği gereken detay diyagramları (use case, class, composite state, combined fragment) için PlantUML. Birden fazla seviyede tutarlı kalması gereken mimari dokümantasyon, yani C4'ün bütün seviyeleri için Structurizr. Üçünü aynı repo'da kullanmak çelişki değil; her biri farklı bir soruya cevap veriyor. Mimari kararları bu diyagramlarla birlikte belgelemek ise ilerideki Architecture Decision'lar serisinin konusu.
LLM'e Diyagram Ürettirirken Doğrulama
Bir LLM'e (Large Language Model) "bu requirement'tan sequence diagram çiz" demek bugün sıradan bir iş, ve metin tabanlı diyagramın bir avantajı daha var: LLM'in çıktısını doğrudan doğrulayabilirsin. Üç katmanlı bir kontrol öneriyorum.
Birincisi söz dizimi. Çıktıyı mmdc, plantuml --check-syntax ya da structurizr validate'ten geçir; exit code sıfır değilse diyagram yok sayılır. Yukarıdaki Lay_R hatası tam bu katmanda yakalanıyor, ve iki aracın söz dizimini karıştırmak bu tür hataların tipik kaynağı. İkincisi anlam. Noktalı virgül örneğinde gördüğümüz gibi exit code 0 olan bir diyagram da yanlış olabilir; render'a bakmadan PR'a girmesin. Üçüncüsü gerçeklik: diyagramdaki adlar ve ilişkiler kodla tutarlı mı? Burada en güçlü araç, koddan üretilebilen diyagramları üretmek. ER diagram yazısında yazdığımız generator'ın çıktısıyla LLM'in çizdiği ER'yi karşılaştırmak, uydurulmuş bir kolonu ya da yanlış bir cardinality'yi saniyeler içinde gösterir. Structurizr'in validate'i de modelde olmayan elemanı reddettiği için bu katmanın bir parçasını otomatik yapar.
Pratik bir prompt kuralı da ekleyeyim: LLM'e serideki isim sözlüğünü (CASE dosyamızdaki LeaveRequest, Approval, HrPortal.Api gibi) ve hedef aracın sürümünü ver, "yalnız bu isimleri kullan" de. Sonra yine de yukarıdaki üç katmandan geçir.
Sık Düşülen Tuzaklar
Hatasız render'ı doğruluk sanmak. Noktalı virgül örneği: Mermaid iki yetim kutu çizdi ve sustu. Diyagram türünün ayrılmış karakterlerini bil, render'a bak.
GitHub'daki Mermaid sürümünü varsaymak. Yerelde 12.3 ile çizdiğin usecase-beta diyagramı, platform daha eski bir sürüm kullanıyorsa render edilmez. info bloğuyla kontrol et; beta diyagramları kalıcı dokümantasyona koyma.
Mermaid C4'ünü büyük diyagramlarda kullanmak. Deklarasyon sırasına dayalı yerleşim, beş-altı kutuyu geçince okunmaz oluyor. Büyük C4 diyagramı için C4-PlantUML ya da Structurizr.
Structurizr export'unu asıl çıktı sanmak. Mermaid export'u flowchart, C4-PlantUML export'u dış sistem ayrımını kaybediyor; export'tan gelen dosyayı elle düzenlersen modelle bağı kopar.
Aynı diyagramı üç araçta tutmak. Bir diyagramın tek bir kaynağı olsun. README'de Mermaid ile özet, docs/diagrams altında PlantUML ile detay tutacaksan ikisinin farklı sorulara cevap verdiğinden emin ol; aynı soruya iki kaynak, iki farklı cevap demektir.
Küçük Bir Deneme
★☆☆ İçinde sadece info yazan bir mermaid bloğunu bir GitHub issue'suna yapıştır ve GitHub'ın kullandığı Mermaid sürümünü not et. Yazıdaki usecase-beta diyagramı o sürümde render ediliyor mu?
★★☆ Structurizr modeline, 13. yazıdaki production topolojisini anlatan bir deploymentEnvironment "Production" ekle (Azure Container Apps, Azure SQL Database, Azure Service Bus) ve bir deployment view'u tanımla. validate ile kontrol et, local'da aç ve container view'da hiçbir şeyi değiştirmeden yeni bir diyagram elde ettiğini doğrula.
★★★ Bir LLM'e docs/requirements.md içeriğini ve isim sözlüğünü verip "talebi iptal et" (UC-03) senaryosunun sequence diagram'ını Mermaid'de ürettir. Çıktıyı yazıdaki üç katmandan geçir: mmdc exit code'u, render'ın gözle kontrolü ve kodla karşılaştırma (LeaveRequestService.CancelAsync gerçekte hangi sırayla ne çağırıyor?). Bulduğun her farkı kategorisiyle listele.
Serinin son yazısında bütün bu parçaları birleştiriyoruz: İzin modülünü requirement metninden use case'e, domain modelden sequence ve state machine'e, ER'den C4'e ve oradan çalışan bir .NET 10 API (Application Programming Interface), EF Core ve Angular koduna tek bir akışta taşıyacak, sonra "yarım gün izin" requirement'ı geldiğinde hangi diyagramların değiştiğini git diff'iyle göreceğiz.