ฟรี · ไม่ต้องสมัคร · รองรับไฟล์ .mmd

ตัวแก้ไขไดอะแกรมคลาส Mermaid

ไดอะแกรมคลาสแสดงชนิดข้อมูลและความสัมพันธ์ระหว่างกัน ว่าอะไรบรรจุอะไร อะไรสืบทอดจากอะไร และอะไรขึ้นกับอะไร เหมาะเมื่อแก่นของเรื่องคือรูปร่างของโค้ด เช่น แบบจำลองโดเมน อินเทอร์เฟซสำหรับส่วนขยาย หรือต้นไม้การสืบทอด ถ้าคุณอยากแสดงสิ่งที่เกิดขึ้นตอนทำงานจริง ไม่ใช่ว่าชนิดข้อมูลประกอบกันอย่างไร ให้ใช้ไดอะแกรมลำดับ

แบบจำลองโดเมนของการชำระเงิน

ความสัมพันธ์สามแบบในไดอะแกรมเดียว คือองค์ประกอบสำหรับส่วนที่อยู่ไม่ได้เมื่อไม่มีทั้งหมด การสืบทอดสำหรับลำดับชั้นของวิธีชำระเงิน และการเชื่อมโยงธรรมดาที่มีพหุภาพ สังเกตว่าตัวระบุของทุกคลาสเป็นอักษรละติน ส่วนชื่อที่แสดงอยู่ในวงเล็บเหลี่ยมเป็นภาษาไทย วิธีนี้ทำให้ตัวระบุถูกต้องและยังคงเห็นภาษาไทยบนจอ

classDiagram
    class Order["คำสั่งซื้อ"] {
        +String เลขที่
        +OrderStatus สถานะ
        +Money ยอดรวม()
        +void เพิ่มรายการ(Product สินค้า, int จำนวน)
    }
    class OrderLine["รายการสินค้า"] {
        +Product สินค้า
        +int จำนวน
        +Money มูลค่า()
    }
    class PaymentMethod["วิธีชำระเงิน"] {
        <<abstract>>
        +อนุมัติ(Money ยอดเงิน) bool
    }
    class QrPayment["พร้อมเพย์"] {
        +String เลขอ้างอิง
        +อนุมัติ(Money ยอดเงิน) bool
    }
    class CardPayment["บัตรเครดิต"] {
        +String สี่ตัวท้าย
        +อนุมัติ(Money ยอดเงิน) bool
    }
    class CashOnDelivery["เก็บเงินปลายทาง"] {
        +Money ค่าธรรมเนียม
        +อนุมัติ(Money ยอดเงิน) bool
    }

    Order "1" *-- "1..*" OrderLine : ประกอบด้วย
    Order --> PaymentMethod : ชำระด้วย
    PaymentMethod <|-- QrPayment
    PaymentMethod <|-- CardPayment
    PaymentMethod <|-- CashOnDelivery
เปิดสิ่งนี้ในตัวแก้ไข
โฆษณา

ตัวอย่างพร้อมคำอธิบาย

1. คลาสเดียว

`+` คือสาธารณะ `-` คือส่วนตัว และ `#` คือป้องกัน สมาชิกที่มีวงเล็บจะถูกวาดเป็นเมท็อด ถ้าไม่มีวงเล็บก็เป็นฟิลด์

classDiagram
    class User["ผู้ใช้"] {
        +String อีเมล
        -String รหัสผ่านที่แฮชแล้ว
        +bool ตรวจสอบ(String ค่าที่กรอก)
    }
เปิดในตัวแก้ไข

2. การสืบทอดและอินเทอร์เฟซ

`<|--` คือการสืบทอด อ่านว่า «ตัวทางขวาขยายตัวทางซ้าย» ส่วนคำกำกับ `<<interface>>` เป็นเพียงป้าย ไม่ใช่พฤติกรรม แต่มันคือสิ่งที่ตัดสินว่าไดอะแกรมอ่านง่ายหรือไม่

classDiagram
    class Repository["รีพอซิทอรี"] {
        <<interface>>
        +ค้นหา(String รหัส) Entity
        +บันทึก(Entity รายการ) void
    }
    class PostgresRepository["รีพอซิทอรี Postgres"] {
        -Connection การเชื่อมต่อ
        +ค้นหา(String รหัส) Entity
        +บันทึก(Entity รายการ) void
    }
    class MemoryRepository["รีพอซิทอรีในหน่วยความจำ"] {
        -Map ที่เก็บ
        +ค้นหา(String รหัส) Entity
        +บันทึก(Entity รายการ) void
    }
    Repository <|.. PostgresRepository
    Repository <|.. MemoryRepository
เปิดในตัวแก้ไข

3. องค์ประกอบเทียบกับการรวมกลุ่ม

ความต่างอยู่ที่อายุการอยู่รอด ข้าวหลามตัดทึบ (`*--`) หมายความว่าส่วนย่อยหายไปพร้อมทั้งหมด ลบใบกำกับภาษีแล้วรายการในนั้นก็หายไปด้วย ส่วนข้าวหลามตัดโปร่ง (`o--`) หมายความว่าส่วนย่อยอยู่ได้ด้วยตัวเอง

classDiagram
    class Invoice["ใบกำกับภาษี"] {
        +String เลขที่
    }
    class InvoiceLine["รายการในใบกำกับ"] {
        +String รายละเอียด
    }
    class Customer["ลูกค้า"] {
        +String ชื่อบริษัท
    }
    Invoice "1" *-- "1..*" InvoiceLine : ประกอบด้วย
    Customer "1" o-- "0..*" Invoice : ได้รับ
เปิดในตัวแก้ไข

4. ชนิดข้อมูลแบบเจเนอริก

เครื่องหมายตัวหนอนใช้กำหนดพารามิเตอร์ของชนิดข้อมูล เช่น `Repository~User~` การซ้อนกันก็ทำได้ ซึ่งบางครั้งจำเป็นและไม่ค่อยเป็นความคิดที่ดีนัก

classDiagram
    class Repository~T~ {
        +ค้นหา(String รหัส) T
        +ทั้งหมด() List~T~
    }
    class Cache~K, V~ {
        +ดึง(K คีย์) V
        +ใส่(K คีย์, V ค่า) void
    }
    class UserRepository["รีพอซิทอรีผู้ใช้"] {
        +ค้นหาด้วยอีเมล(String อีเมล) User
    }
    Repository~User~ <|-- UserRepository
เปิดในตัวแก้ไข

5. หมายเหตุและทิศทาง

`direction LR` จัดวางไดอะแกรมจากซ้ายไปขวา ซึ่งมักเข้ากับต้นไม้การสืบทอดได้ดีกว่าการจัดวางตั้งต้น ส่วนหมายเหตุคือที่ที่เหมาะสำหรับข้อจำกัดที่ใส่ลงในกล่องคลาสไม่ได้

classDiagram
    direction LR
    class EventStore["ที่เก็บเหตุการณ์"] {
        +เพิ่ม(Event เหตุการณ์) void
        +เล่นซ้ำ(String สาย) List~Event~
    }
    class Snapshot["ภาพสแนปช็อต"] {
        +int รุ่น
        +byte[] เนื้อหา
    }
    EventStore --> Snapshot : เขียนทุก 100 เหตุการณ์
    note for EventStore "เพิ่มได้อย่างเดียว เหตุการณ์จะไม่ถูกแก้ไขหรือลบ"
เปิดในตัวแก้ไข

สรุปไวยากรณ์ไดอะแกรมคลาส

ลูกศรความสัมพันธ์คุ้มค่าที่จะจำ เพราะมันคือสิ่งที่แยกไดอะแกรมคลาสออกจากภาพกล่องต่อเส้น และมันอ่านจากหัวลูกศรย้อนกลับ ซึ่งทำให้เข้าใจผิดอยู่นาน

ไวยากรณ์ความหมาย
classDiagramเปิดไดอะแกรม แยกตัวพิมพ์ใหญ่เล็ก
class Name["ชื่อ"] { ... }ตัวระบุอักษรละตินพร้อมชื่อภาษาไทยที่แสดงบนจอ สำหรับภาษาไทยควรใช้รูปแบบนี้เสมอ
class Name { ... }คลาสพร้อมสมาชิก วงเล็บปีกกาปิดอยู่บรรทัดของตัวเอง
+สมาชิกสาธารณะ
-สมาชิกส่วนตัว
#สมาชิกป้องกัน
+เมท็อด(Type arg) ReturnTypeเมท็อด สิ่งที่ทำให้เป็นเมท็อดคือวงเล็บ
<<interface>> / <<abstract>>สเตอริโอไทป์ เขียนบรรทัดแรกภายในคลาส
A <|-- Bการสืบทอด B ขยาย A
A <|.. Bการนำไปใช้จริง B ทำตามอินเทอร์เฟซ A
A *-- Bองค์ประกอบ B อยู่ไม่ได้เมื่อไม่มี A
A o-- Bการรวมกลุ่ม B อยู่ได้โดยไม่มี A
A --> Bการเชื่อมโยงที่มีทิศทาง
A ..> Bการพึ่งพา A ใช้ B แต่ไม่ได้เก็บไว้
A "1" --> "0..*" B : ป้ายกำกับพหุภาพทั้งสองฝั่งพร้อมป้ายกำกับความสัมพันธ์
class Repo~T~พารามิเตอร์ชนิดข้อมูลแบบเจเนอริก
note for A "ข้อความ"หมายเหตุที่ผูกกับคลาสหนึ่ง
direction LRเปลี่ยนทิศทางการจัดวาง
โฆษณา

ข้อผิดพลาดที่ทำให้ไดอะแกรมคลาสพัง

สร้างซ้ำบน Mermaid 11.12.2 ไดอะแกรมคลาสเป็นหนึ่งในประเภทที่ผ่อนปรนกว่าเพื่อน ครึ่งหนึ่งของข้อผิดพลาดเหล่านี้จึงแสดงผลออกมาเงียบ ๆ และยื่นภาพที่ผิดให้คุณ

สิ่งที่คุณเห็น

Lexical error on line N. Unrecognized text.

ทำไม

ชื่อคลาสเขียนด้วยอักษรไทย ชื่อคลาสก็เป็นตัวระบุเช่นกัน และเหมือนตัวระบุโหนดของผังงาน อักษรไทยถูกปฏิเสธที่นี่ วัดแล้ว `class คำสั่งซื้อ` ล้มด้วยข้อผิดพลาดนี้

วิธีแก้

ให้ตัวระบุเป็นอักษรละตินแล้วใส่ชื่อที่แสดงไว้ในวงเล็บเหลี่ยม เช่น `class Order["คำสั่งซื้อ"]` ทดสอบแล้วว่าใช้ได้ ตัวระบุภายในยังเป็น `Order` และบนจอแสดงว่า `คำสั่งซื้อ` ส่วนชื่อสมาชิกยังเป็นภาษาไทยได้ เพราะไม่ใช่ตัวระบุ

ผิด
classDiagram
    class คำสั่งซื้อ {
        +String เลขที่
    }
ถูก
classDiagram
    class Order["คำสั่งซื้อ"] {
        +String เลขที่
    }

สิ่งที่คุณเห็น

Parse error ที่ลงท้ายด้วย: got 'EOF_IN_STRUCT'

ทำไม

ตัวคลาสเปิดด้วย `{` แล้วไม่เคยปิด คราวนี้ชื่อโทเคนช่วยได้จริง มันบอกว่าไฟล์จบลงขณะที่เรายังอยู่ภายในคลาส

วิธีแก้

ปิดวงเล็บปีกกาบนบรรทัดของตัวเอง

ผิด
classDiagram
    class Order["คำสั่งซื้อ"] {
        +String เลขที่
ถูก
classDiagram
    class Order["คำสั่งซื้อ"] {
        +String เลขที่
    }

สิ่งที่คุณเห็น

Parse error ที่ลงท้ายด้วย: got 'ANNOTATION_END'

ทำไม

ใช้ลูกศรของไดอะแกรมลำดับในไดอะแกรมคลาส `->>` ไม่มีความหมายที่นี่ และตัวแจงเดินเข้าไปลึกพอที่จะคืนชื่อโทเคนที่ชวนให้เข้าใจผิด

วิธีแก้

ใช้ความสัมพันธ์ของไดอะแกรมคลาส คือ `-->` สำหรับการเชื่อมโยง `<|--` สำหรับการสืบทอด และ `*--` สำหรับองค์ประกอบ

ผิด
classDiagram
    Order ->> Customer
ถูก
classDiagram
    Order --> Customer : เป็นของ

สิ่งที่คุณเห็น

ลูกศรชี้ไปคนละทางกับที่คุณตั้งใจ

ทำไม

ลูกศรความสัมพันธ์อ่านจากหัวลูกศรย้อนกลับ `A <|-- B` หมายความว่า B สืบทอดจาก A ไม่ใช่ตรงกันข้าม เขียนกลับด้านก็ยังแสดงผลได้ เพียงแต่ตอนนี้มันอ้างว่าคลาสฐานไปขยายคลาสลูกของตัวเอง

วิธีแก้

อ่านว่า «ปลายที่อยู่ไกลขยายปลายที่มีหัวลูกศร» แล้ววางคลาสแม่ไว้ทางซ้ายของ `<|--`

ผิด
classDiagram
    CardPayment <|-- PaymentMethod
ถูก
classDiagram
    PaymentMethod <|-- CardPayment

สิ่งที่คุณเห็น

มีฟิลด์โผล่มาในที่ที่คุณคาดว่าจะเป็นเมท็อด

ทำไม

วงเล็บคือสิ่งเดียวที่แยกเมท็อดออกจากฟิลด์ `+บันทึก` คือฟิลด์ชื่อบันทึก ส่วน `+บันทึก()` คือเมท็อด ทั้งสองรูปแบบถูกต้อง จึงไม่มีอะไรเตือน

วิธีแก้

เติมวงเล็บเข้าไป แล้วตามด้วยชนิดข้อมูลที่คืนค่าถ้าอยากให้เห็น

ผิด
classDiagram
    class Repo {
        +บันทึก
        +ค้นหา
    }
ถูก
classDiagram
    class Repo {
        +บันทึก(Entity รายการ) void
        +ค้นหา(String รหัส) Entity
    }

สิ่งที่คุณเห็น

องค์ประกอบกับการรวมกลุ่มดูเหมือนกันเมื่อมองผ่าน ๆ แต่บอกตรงกันข้าม

ทำไม

`*--` กับ `o--` ต่างกันอักขระเดียว และทั้งคู่เข้ารหัสความต่างเชิงความหมายที่มีอยู่จริง คือส่วนย่อยอยู่รอดหลังทั้งหมดหายไปหรือไม่ การใช้ผิดตัวให้ไดอะแกรมที่ถูกต้องตามรูปแบบแต่เป็นเท็จต่อโดเมนของคุณ

วิธีแก้

ข้าวหลามตัดทึบ `*--` เมื่อลบตัวแม่แล้วตัวลูกหายไปด้วย ส่วนโปร่ง `o--` เมื่อไม่หาย

ผิด
classDiagram
    Order o-- OrderLine : ประกอบด้วย
ถูก
classDiagram
    Order *-- OrderLine : ประกอบด้วย

หมายเหตุเรื่องการแสดงผล

วัดบน Mermaid 11.12.2 ซึ่งเป็นรุ่นที่เว็บนี้ใช้

ชื่อในวงเล็บเหลี่ยมคือทางออกที่แท้จริงของไดอะแกรมคลาสภาษาไทย

นี่คือสิ่งที่มีประโยชน์ที่สุดในหน้านี้ `class คำสั่งซื้อ` ล้มเพราะชื่อคลาสเป็นตัวระบุและอักษรไทยไม่ผ่านตรงนั้น แต่ `class Order["คำสั่งซื้อ"]` ทดสอบแล้วและใช้ได้ ตัวระบุที่ออกมาคือ `classId-Order` ขณะที่บนจอแสดงคำว่า `คำสั่งซื้อ` และที่ดีกว่านั้นคือความสัมพันธ์ระหว่างคลาสที่ตั้งชื่อแบบนี้ก็ทำงานได้ตามปกติ ทดสอบ `<|--` ระหว่างคลาสสองตัวที่ใช้วงเล็บเหลี่ยมแล้วแสดงผลถูกต้อง แปลว่าไดอะแกรมคลาสภาษาไทยไม่จำเป็นต้องโชว์อักษรละตินให้ผู้อ่านเห็นเลย

ชื่อสมาชิกไม่ใช่ตัวระบุ จึงเป็นภาษาไทยได้

ข้อจำกัดอยู่ที่ชื่อคลาสเท่านั้น ชื่อสมาชิก ชื่อพารามิเตอร์ และชื่อชนิดข้อมูลที่คืนค่า ถูกปฏิบัติเหมือนป้ายกำกับ ทั้ง `+String เลขที่` และ `+Money ยอดรวม()` แสดงผลตรงตามที่เขียน และวงเล็บก็ยังทำหน้าที่เปลี่ยนให้เป็นเมท็อดได้เหมือนกับชื่อภาษาอังกฤษ ผลคือข้อความส่วนใหญ่ในไดอะแกรมเป็นภาษาไทยได้ เหลือเพียงตัวระบุภายในของคลาสที่เป็นอักษรละติน

มันโตขึ้นด้านบนเร็วกว่าทุกประเภทที่นี่

วัดจากคลาสที่มีสมาชิกละสองตัวและผูกกันด้วยการสืบทอด สามคลาสให้ viewBox ราว 176×548 ส่วนสี่สิบคลาสให้ 180×7726 คือราว 194 พิกเซลต่อคลาส ซึ่งเป็นอัตราที่ชันที่สุดในหกประเภทของเว็บนี้ ไดอะแกรมสี่สิบคลาสสูงเกินเจ็ดพันพิกเซลและใช้เป็นภาพเดียวไม่ได้ `direction LR` ช่วยได้ แต่เกินราวสิบห้าคลาสไปแล้ว ทางออกที่ซื่อตรงคือแบ่งไดอะแกรมตามขอบเขตของโดเมน

จำนวนสมาชิกแทบไม่มีผลต่อความกว้าง

ความกว้างถูกกำหนดโดยลายเซ็นที่ยาวที่สุดของสมาชิกตัวเดียว ไม่ใช่จำนวนสมาชิก คลาสที่มีฟิลด์สั้น ๆ ยี่สิบตัวไม่ได้กว้างกว่าคลาสที่มีสามตัว พูดอีกอย่างคือใจกว้างกับสมาชิกได้ แต่ต้องตระหนี่กับคลาส ซึ่งตรงข้ามกับสัญชาตญาณพอดี

ป้ายกำกับเป็น HTML การส่งออก PNG จึงวาดใหม่

ป้ายกำกับของคลาสถูกวาดภายใน `<foreignObject>` ในไฟล์ SVG และเบราว์เซอร์ปฏิเสธที่จะแปลงมันเป็นภาพแรสเตอร์บนแคนวาส การส่งออก PNG ของเว็บนี้เคยล้มเหลวอย่างเงียบ ๆ และคืนไฟล์ SVG ตอนนี้มันวาดไดอะแกรมใหม่ด้วยป้ายกำกับข้อความ SVG ล้วนก่อน ไฟล์ PNG จึงออกมาถูกต้องและเต็มขนาด โดยการจัดวางตัวอักษรต่างจากบนจอเล็กน้อย

เมื่อใดควรใช้ไดอะแกรมประเภทอื่น

ถ้าคุณกำลังทำเอกสารของฐานข้อมูล ไม่ใช่ระบบชนิดข้อมูล ให้ใช้ไดอะแกรม ER ความต่างนี้สำคัญ เพราะไดอะแกรมคลาสจำลองพฤติกรรมและการสืบทอดซึ่งตารางไม่มี ส่วนไดอะแกรม ER จำลองคีย์และพหุภาพได้เรียบร้อย ซึ่งไดอะแกรมคลาสผ่านไปแบบผิวเผิน

ถ้าไดอะแกรมส่วนใหญ่เป็นกล่องที่ต่อกันด้วย `-->` และไม่มีสมาชิกเลย แสดงว่าคุณกำลังวาดสถาปัตยกรรม ไม่ใช่ไดอะแกรมคลาส ผังงานที่มีกลุ่มย่อยจะดูดีกว่าและอ้างสิ่งต่าง ๆ น้อยกว่า

และถ้ารายชื่อคลาสเกิดขึ้นจากโค้ด ลองพิจารณาว่าไดอะแกรมควรเกิดจากที่เดียวกันหรือไม่ ไดอะแกรมคลาสที่ดูแลด้วยมือสำหรับฐานโค้ดที่เปลี่ยนทุกสัปดาห์จะกลายเป็นเท็จภายในหนึ่งเดือน และไดอะแกรมที่ผิดมีราคาแพงกว่าการไม่มีไดอะแกรมเลย

ไดอะแกรมประเภทอื่น

เขียนโดย Dominik Malsch · อัปเดตล่าสุด:

เปิดตัวแก้ไข →