Mert Özen Her Satırda Daha İleri
Yazılım Tasarımı UML ve Modeling — #17

Mermaid ve Structurizr DSL: Markdown İçinde Diyagram, Model Tabanlı C4 ve Hangisini Seçmeli?

Mert Özen 7 Kas 2026 15 dk 5 görüntülenme
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.

17-mermaid-vs-structurizr-tr.png

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.

17-one-model-many-views-tr.png

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:

KriterPlantUMLMermaidStructurizr DSL
Notasyon kapsamıUML'in neredeyse tamamı, C4-PlantUML, Chen ERClass, sequence, state, ER, C4, beta use case ve architectureC4 view'ları (system landscape, context, container, component, dynamic, deployment)
Render ortamıJava + Graphviz, yerel jar ya da kendi sunucunTarayıcı; GitHub ve Azure DevOps Markdown'ında doğrudanlocal (tarayıcıda), Docker, export
Model tutarlılığıHer diyagram ayrı metinHer diyagram ayrı metinTek 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 otomatikautolayout ve tarayıcıda elle sürükleme
CI doğrulaması--check-syntax, exit 200mmdc, exit 1validate, exit 1
Öğrenme eğrisiOrta, diyagram türü başına söz dizimiDüşük, ama türler arası tutarsızOrta, 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.