مجاني · بدون تسجيل · يدعم ملفات ‎.mmd

محرر مخططات الأصناف بـ Mermaid

يبيّن مخطط الأصناف الأنواعَ وعلاقاتِ بعضها ببعض: ما الذي يحتوي ماذا، وما الذي يرث عمّن، وما الذي يعتمد على ماذا. يناسبك حين يكون الجوهر شكلَ الشيفرة — نموذج مجال، واجهة توسعة، شجرة وراثة. أما إن أردت إظهار ما يجري وقت التشغيل لا كيف تتلاءم الأنواع، فاستعمل مخطط التسلسل.

نموذج مجال الدفع

ثلاثة أنواع من العلاقات في مخطط واحد: التركيب للأجزاء التي لا تبقى بعد الكل، والوراثة لتسلسل وسائل الدفع، وارتباط عادي بتعدّدية. والمعنى تحمله الأسهم أساسًا؛ أما مستطيلات الأصناف فتكاد تكون تابعًا.

classDiagram
    class طلب {
        +String رقم
        +حالةالطلب حالة
        +مبلغ الإجمالي()
        +void أضفسطرًا(منتج م, int كمية)
    }
    class سطرالطلب {
        +منتج المنتج
        +int الكمية
        +مبلغ القيمة()
    }
    class وسيلةالدفع {
        <<abstract>>
        +فوّض(مبلغ القيمة) bool
    }
    class بطاقة {
        +String آخرأربعة
        +فوّض(مبلغ القيمة) bool
    }
    class حوالة {
        +String آيبان
        +فوّض(مبلغ القيمة) bool
    }
    class دفععندالاستلام {
        +مبلغ رسمالتحصيل
        +فوّض(مبلغ القيمة) bool
    }

    طلب "1" *-- "1..*" سطرالطلب : يحتوي
    طلب --> وسيلةالدفع : يُدفع بـ
    وسيلةالدفع <|-- بطاقة
    وسيلةالدفع <|-- حوالة
    وسيلةالدفع <|-- دفععندالاستلام
افتح هذا في المحرر
إعلان

أمثلة مشروحة

١. صنف واحد

الرمز `+` يعني عامًا، و`-` خاصًا، و`#` محميًا. والعضو الذي فيه قوسان يُرسم دالة؛ وبدونهما يكون حقلًا.

classDiagram
    class مستخدم {
        +String بريد
        -String بصمةكلمةالمرور
        +bool تحقق(String مرشح)
    }
افتح في المحرر

٢. الوراثة والواجهات

الرمز `<|--` وراثة، ويُقرأ «الذي على اليمين يوسّع الذي على اليسار». والتعليق `<<interface>>` تسمية لا سلوك، لكنه هو ما يحدد وضوح المخطط.

classDiagram
    class مستودع {
        <<interface>>
        +جد(String معرف) كيان
        +احفظ(كيان ك) void
    }
    class مستودعPostgres {
        -اتصال الاتصال
        +جد(String معرف) كيان
        +احفظ(كيان ك) void
    }
    class مستودعذاكرة {
        -Map التخزين
        +جد(String معرف) كيان
        +احفظ(كيان ك) void
    }
    مستودع <|.. مستودعPostgres
    مستودع <|.. مستودعذاكرة
افتح في المحرر

٣. التركيب في مقابل التجميع

الفرق يتعلق بمدة الحياة. فالمعيّن الممتلئ (`*--`) يعني أن الجزء يزول مع الكل: احذف الفاتورة تختفِ سطورها. والمعيّن الفارغ (`o--`) يعني أن الجزء قائم بذاته.

classDiagram
    class فاتورة {
        +String رقم
    }
    class سطرفاتورة {
        +String بيان
    }
    class عميل {
        +String الاسمالتجاري
    }
    فاتورة "1" *-- "1..*" سطرفاتورة : تتكون من
    عميل "1" o-- "0..*" فاتورة : صدرت له
افتح في المحرر

٤. الأنواع العامة

علامات المدّة تعطي وسائط الأنواع: `مستودع~مستخدم~`. والتداخل يعمل كذلك، وهو لازم أحيانًا ونادرًا ما يكون فكرة جيدة. والحروف العربية تعمل داخل النوع العام دون عائق.

classDiagram
    class مستودع~T~ {
        +جد(String معرف) T
        +الكل() List~T~
    }
    class مخبأ~K, V~ {
        +خذ(K مفتاح) V
        +ضع(K مفتاح, V قيمة) void
    }
    class مستودعالمستخدمين {
        +جدبالبريد(String بريد) مستخدم
    }
    مستودع~مستخدم~ <|-- مستودعالمستخدمين
افتح في المحرر

٥. الملاحظات والاتجاه

الوسم `direction LR` يخطّط المخطط من اليسار إلى اليمين، وهو ما يخدم شجرة الوراثة عادةً أكثر من التخطيط الافتراضي. والملاحظة هي الموضع الصحيح للقيد الذي لا يتسع له مستطيل الصنف.

classDiagram
    direction LR
    class مخزنالأحداث {
        +ألحق(حدث ح) void
        +أعدالتشغيل(String تيار) List~حدث~
    }
    class لقطة {
        +int إصدار
        +byte[] محتوى
    }
    مخزنالأحداث --> لقطة : يكتب كل 100 حدث
    note for مخزنالأحداث "إلحاق فقط. لا تُعدّل الأحداث ولا تُحذف أبدًا."
افتح في المحرر

ملخص صياغة مخطط الأصناف

أسهم العلاقات تستحق الحفظ: فهي التي تميّز مخطط الأصناف عن رسم مستطيلات وخطوط، وتُقرأ من الرأس إلى الخلف، وهو ما يضلّل مدة طويلة.

الصياغةالمعنى
classDiagramيفتح المخطط. حساس لحالة الأحرف.
class اسم { ... }صنف بأعضائه. والقوس المعقوف المُغلِق في سطر مستقل.
+عضوعام.
-عضوخاص.
#عضومحمي.
+دالة(نوع وسيط) نوعالإرجاعدالة — والقوسان هما ما يجعلانها كذلك.
<<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 مستودع~T~وسيط نوع عام.
note for A "نص"ملاحظة ملحقة بصنف.
direction LRيغيّر اتجاه التخطيط.
إعلان

الأخطاء التي تُفسد مخطط الأصناف

أُعيد إنتاجها على Mermaid 11.12.2. ومخطط الأصناف من الأنواع الأكثر تسامحًا بين الستة، ولذلك يُرسم نصف هذه الأخطاء بهدوء ويعطيك الصورة الخاطئة.

ما تراه

Parse error ينتهي بـ: got 'EOF_IN_STRUCT'

لماذا

جسم صنف فُتح بـ `{` ولم يُغلق قط. وهنا يفيد اسم الرمز فعلًا: فهو يقول إن الملف انتهى ونحن ما زلنا داخل صنف.

الحل

أغلق القوس المعقوف في سطر مستقل.

خطأ
classDiagram
    class طلب {
        +String رقم
صحيح
classDiagram
    class طلب {
        +String رقم
    }

ما تراه

Parse error ينتهي بـ: got 'ANNOTATION_END'

لماذا

سهم من مخطط التسلسل استُعمل في مخطط أصناف. فالرمز `->>` لا يعني هنا شيئًا، ويتوغل فيه المحلل بما يكفي ليعيد اسم رمز مضلِّلًا.

الحل

استعمل علاقات مخطط الأصناف: `-->` للارتباط، و`<|--` للوراثة، و`*--` للتركيب.

خطأ
classDiagram
    طلب ->> عميل
صحيح
classDiagram
    طلب --> عميل : يخص

ما تراه

No diagram type detected matching given configuration

لماذا

حالة أحرف خاطئة في الكلمة المفتاحية. فـ `classdiagram` ليست `classDiagram`.

الحل

حرف D كبير.

خطأ
classdiagram
    class طلب
صحيح
classDiagram
    class طلب

ما تراه

السهم يشير إلى الجهة المعاكسة لما أردت

لماذا

أسهم العلاقات تُقرأ من الرأس إلى الخلف. فـ `A <|-- B` تعني أن B يرث من A لا العكس. وإن كتبتها معكوسة رُسمت رغم ذلك — إلا أنها الآن تزعم أن الصنف الأساس يوسّع صنفه الفرعي.

الحل

اقرأها هكذا: «الطرف البعيد يوسّع الطرف ذا الرأس». وضع الأب على يسار `<|--`.

خطأ
classDiagram
    بطاقة <|-- وسيلةالدفع
صحيح
classDiagram
    وسيلةالدفع <|-- بطاقة

ما تراه

يظهر حقل في موضع توقعت فيه دالة

لماذا

القوسان هما الشيء الوحيد الذي يميّز الدالة عن الحقل. فـ `+احفظ` حقل اسمه احفظ؛ و`+احفظ()` دالة. وكلا الشكلين صحيح، فلا شيء ينبّه.

الحل

أضف القوسين، ثم نوع الإرجاع بعدهما إن أردت رؤيته.

خطأ
classDiagram
    class مستودع {
        +احفظ
        +جد
    }
صحيح
classDiagram
    class مستودع {
        +احفظ(كيان ك) void
        +جد(String معرف) كيان
    }

ما تراه

التركيب والتجميع يبدوان للوهلة الأولى متطابقين ويقولان عكس بعضهما

لماذا

الرمزان `*--` و`o--` يفترقان بمحرف واحد، وهما يرمّزان فرقًا معنويًا حقيقيًا: أيبقى الجزء بعد الكل أم لا. واستعمال الخطأ منهما ينتج مخططًا صحيحًا شكلًا وكاذبًا على مجالك.

الحل

معيّن ممتلئ `*--` حين يؤدي حذف الأب إلى حذف الابن. وفارغ `o--` حين لا يؤدي.

خطأ
classDiagram
    طلب o-- سطرالطلب : يحتوي
صحيح
classDiagram
    طلب *-- سطرالطلب : يحتوي

ملاحظات على الرسم

مقيس على Mermaid 11.12.2، وهي النسخة التي يستعملها هذا الموقع.

ينمو إلى أعلى أسرع من أي نوع آخر هنا

قِيس على أصناف بعضوين لكل صنف مربوطة بالوراثة: ثلاثة أصناف تعطي إطارًا يقارب 176×548، وأربعون صنفًا تعطي 180×7726، أي نحو 194 بكسل ارتفاعًا لكل صنف — وهو أشد نمو في الأنواع الستة على هذا الموقع. ومخطط بأربعين صنفًا يتجاوز سبعة آلاف بكسل ارتفاعًا ولا ينفع صورةً واحدة. و`direction LR` يساعد، لكن فوق خمسة عشر صنفًا تقريبًا يكون الحل الصادق تقسيمَ المخطط بحسب حدود المجال.

الأسماء العربية تعمل أسماءَ أصناف ودوال

جُرّب: `class طلب` يُرسم، و`+String رقم` يظهر حقلًا، و`+مبلغ الإجمالي()` تنتقل إلى خانة الدوال كما ينبغي — أي إن القوسين يعملان مع الأسماء العربية تمامًا كما مع اللاتينية. والقيد الوحيد هو المسافة داخل اسم الصنف نفسه، لأنه معرّف: فـ `سطر الطلب` لا يصلح ويجب وصله `سطرالطلب`. أما تسمية العلاقة بعد النقطتين فنص حر، فتُكتب `: يُدفع بـ` بمسافاتها كاملة.

عدد الأعضاء لا يكاد يؤثر في العرض

العرض يحدده أطولُ توقيع لعضو واحد لا عددُ الأعضاء. فالصنف ذو العشرين حقلًا القصيرة ليس أعرض من ذي الثلاثة. بعبارة أخرى: كن سخيًا مع الأعضاء وشحيحًا مع الأصناف، وهو عكس ما تمليه الغريزة تمامًا. وفي العربية تخرج التواقيع أضيق منها في الإنجليزية، فيميل العرض إلى أن يكون أقل مما تتوقعه من مثال إنجليزي.

الأنواع العامة تستعمل علامة المدّة ولذلك تبعة

الصيغة `مستودع~T~` كُتبت هكذا لأن الأقواس الزاوية تتعارض مع HTML في التسميات. ويتبع ذلك أيضًا أن علامة مدّة حقيقية داخل اسم صنف أو عضو ستُقرأ بداية وسيط نوع. وهذا نادر، لكنه حين يقع يربك إرباكًا لا يستهان به.

التسميات HTML، فتصدير PNG يعيد الرسم

تُرسم تسميات الأصناف داخل `<foreignObject>` في ملف SVG، وترفض المتصفحات تحويل ذلك إلى صورة نقطية على لوحة canvas. وكان تصدير PNG في هذا الموقع يفشل بصمت ويعيد ملف SVG؛ أما الآن فيعيد رسم المخطط أولًا بتسميات نصية SVG صِرفة. فيخرج الـ PNG صحيحًا وبحجمه الكامل، بتنضيد يختلف قليلًا عما على الشاشة.

متى يكون مخطط آخر أنسب

إن كنت توثّق قاعدة بيانات لا نظام أنواع، فاستعمل مخطط الكيانات. والتمييز مهم: فمخططات الأصناف تنمذج السلوك والوراثة، وهما ليسا في الجداول، ومخططات الكيانات تنمذج المفاتيح والتعدّديات نمذجة متقنة، وهو ما تمرّ عليه مخططات الأصناف مرور الكرام.

وإن كان المخطط في معظمه مستطيلات موصولة بـ `-->` بلا أعضاء، فأنت ترسم معمارية لا مخطط أصناف. ومخطط تدفق بمجموعات فرعية سيبدو أفضل ويزعم أقل.

وإن كانت قائمة الأصناف تولد من الشيفرة، ففكّر إن كان ينبغي أن يولد المخطط منها كذلك. فمخطط أصناف يُصان يدويًا لقاعدة شيفرة تتغير أسبوعيًا يصير غير صادق خلال شهر، والمخطط الخاطئ أغلى من غياب المخطط.

أنواع المخططات الأخرى

بقلم Dominik Malsch · آخر تحديث:

افتح المحرر ←