UP | HOME
جناوي

السيد مذهل
mr. fantastic

طالب هندسة برمجيات - مهتم بالرسوميات والهندسة الصوتية

Software engineering student - interested in graphics and audio engineering

أستخدام PlantUML لتسهيل رسم مخططات هندسة البرمجيات
نشر في Sep 23, 2020 بقلم السيد مذهل.

ملاحظة هامة: هذه المقالة لا تشرح معاني وعناصر المخططات وأنما تفترض معرفة القارئ بها وبأساسيات هندسة البرمجيات.

في هذه المقالة سوف أوضح طريقة أستخدام PlantUML لرسم مخططات هندسة البرمجيات وبالأخص الـ UML1, 2 وبرنامج أو صيغة PlantUML تشمل أغلب مخططات UML والمخططات الغير مشمولة هي غالباً مشتقة من أبرز المخططات (Use case, sequence, class, deployment) فيمكن محاكاتها وإيضاً هناك صيغة أخرى مدعومة مثل:

ملاحظة: مخطط وصف قواعد البيانات أو Entity Relationship diagram (ERM) يتسخدم طريقة غير طريقة تشن chen المشهورة فهذا الشيء الوحيد الذي ينقصني في PlantUML

ما هو بلانت يو أم إيل PlantUML

لا يمكن القول بأنه برنامج تعديل ورسم مخططات رسومي فطريقة PlantUML تعتمد على أن تكتب وصف مخطط بملف نصي ومن ثمة تحوله إلى رسم (صورة, صيغة متجهات, pdf, إلخ) وقد يبدو هذا غريباً للوهلة الإولى ولكن أذكر نحن كمبرمجين أو مهندسين برمجيات أو طلاب حالياً لا يمكن أن نمضى قدر جيد من الوقت ضمن مجالنا دون أن نتعلم كتابة صفحات الأنترنت والويب بأستعمال HTML, CSS, javascript فلا داعي للأستغراب أو التشكيك بفعالية الطريقة بالإخص لإي أكاديمي يستخدم لاتخ (LaTeX) لإعداد أوراقه العلمية.

وإيضاً يمكن القول بأن PlantUML لغة برمجيات خاصة لمجالها (Domain Specific Language - DSL) أو صيغة وصفية أو ما شاكل ذلك ولذا أود أن أشير إلى البدائل الرسومية:

  • برنامج ArgoUML (وهو برنامج نمذجة - Modeling - وليس رسم لأنه يستطيع تحويل الرسم لشفرة مصدرية والتجوال وأستعراض النماذج على عكس PlantUML).
  • برنامج Libre Office Draw (وهو برنامج رسم مخططات عام).
  • برنامج Dia (وهو برنامج رسم بواجهة رسومية).
  • لمزيد من البرامج يرجى الإطلاع على هذه القائمة المطولة من ويكيبيديا.

لماذا PlantUML

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

ما يقدمه PlantUML هو الحل ولكن وجب التنويه بأن الخوارزمية التي ترتب العناصر ليست ذكيةً جداً فقد تحتاج لبعض التعديلات حتى تحصل على النتيجة المطلوبة.

التثبيت

بأن هذا البرامج هو برنامج مكتوب بلغة الجافا فبلإمكان تشغيله على إي جهاز يشغل Java Virtual Machine وروابط التثبيت ظاهرة على الموقع الرسمي ولا حاجة لتثبيت إي برنامج أخر يكفي إي محرر نصوص بسيط ولكن حتى نحصل التلوين والتدقيق اللغوي يمكننا تثبيت إضافات مساعدة مثل إضافة plantuml-mode لبرنامج إيماكس وكل برنامج أخر لديه إضافة مشابهة.

بالإضافة لما سبق يمكن الأستغناء عن تثبيت البرنامج وأستعمال الخدمة عبر المتصفح دون تثبيت.

2020/11/05 تحديث: بأعتبار عدم أستخدامي لنظام ويندوز أو ماك لاحظت بعد تجربة أن البرنامج يتتطلب تثبيت Graphviz معه وهو غالباً يأتي بالتوزيعات الجناوية لأنه متتطلب لبرنامج جيمب الشهير وكذلك العديد من البرامج مع العلم عند تثبيته بوندوز يجب تفعيل خيار المتغير PATH$ للجميع عند التثبيت وبعدها يمكنك تشغيل PlantUML عبر الضغط على ملف jar.

الأساسيات

ملاحظة: الأمثلة ستكون باللغة العربية للتوضيح فقط لأنه بأرض الواقع دوماً يتم أستخدام اللغة الأنجليزية

أسهل مثال هو لرسم مخطط وصف سلسلة الأحداث التي تحدث بعمليات البرنامج أو ما يسمى sequence diagram وهو أكثرها ترتيباً

@startuml

' علامتين startuml@ و enduml@ ضروريتين لكل مخطط UML
' نعم علامة ' تبدأ تعليق لسطر واحد

مستخدم -> متجر

/'
        إيضاح طريقة
        أستخدام تعليقات الأسطر
        المتعددة
'/

@enduml

بعد أن تحفظ هذا المثال في ملف نصي بصيغة puml. تشغل هذا الأمر في سطر الأوامر حتى نحول الملف إلى صورة:

plantuml eg1.puml

eg1.png

أو يمكنك تشغيل PlantUML بدون إي خيارات فيعمل بالواجهة الرسومية ويحول كل ملف puml. إلى صورة ويسمح لك إيضاً بتغيير المجلد الحالي:

plantuml

gui.gif

شكل 2: صورة متحركة - كيفية أستخدام الواجهة الرسومية

كما يمكنك تحويل المخططات لصيغة غير الـ png مثل svg:

plantuml -tsvg

أو teps- -tpdf -ttext- … إلخ.

لمعرفة بقية الخيارات يمكنك الإطلاع على خيار المساعدة:

plantuml -h

ولكن ربما هذا المخطط غير مألوف نوعاً ما فهناك صندوقان من الأعلى والأسفل وليس واحد فقط بالأعلى لذلك يمكننا تغيير أعدادات PlantUML الإفتراضية ونكمل التعرف على صيغته بهذا المثال:

@startuml

' هذا لإزالة الصندوق السفلي
hide footbox

/' 
        كما رأينا بالمثال السابق يمكننا أستخدام المتغيرات
        بدون تعريفها للوهلة الأولى ولكن بتعريفها يمكننا
        إضفاء بعض الخصائص عليها
'/

actor مستخدم

مستخدم -> متجر

' من بعد ربط طرفين الأستدعاء يمكن أستخدام شارة : لوضع إي تعليق
' على المسار الممتد بين العنصرين
متجر -> مخزن : أسحب (سلعة, عدد)

@enduml

eg2.png

ومن هنا يسعنا الأنتقال لنوع أخر من مخططات UML مع العلم أن لا حاجة لتحديد نوع المخطط لأن PlantUML يتعرف تلقائياً على نوع المخطط من العناصر التي تستخدمها وإيضاً هنالك خصائص مشتركة بين المخططات مثل صناديق التعليقات (comment boxes) وبعض أنواع الأسهم التي تشترك بعض المخططات فيها ولكن أحياناً بعض الخصائص في مخطط لا توجد بأخر فلا يمكن أستخدام صنف (Class) في مخطط حالات الأستخدام (Use Case diagram).

لنأخذ مثالاً بسيطً على مخطط حالات الأستخدام:

@startuml

' غير أتجاه ترتيب العناصر في المخطط
left to right direction

/'
 ' بهذه الطريقة يمكننا وضع أسم طويل
 ' وبه مسافات على المتغير وفي حالتنا هو الممثل
'/
actor "مشتري" as user
actor "مدير" as admin

' هنا سيتم حصر حالات الأستخدام داخل نطاق النظام
package متجر {

        ' وهكذا يتم تعريف الحالات
        usecase "أطلب" as uc1
        usecase "إدفع" as uc2
        usecase "أضف سلعة" as uc3

        }

' هنا سوف نباشر العمل على الروابط
user --- uc1

' علاقة ضمنية
uc1 .> uc2 : <<Inlcude>>

' أنتبه للترتيب وعدد رموز - المضافة
' هذا سيجعل الممثل يذهب لليسار ويجعل طول المسار أطول
uc3 ------ admin

' هذا أحد أشكال تعريف صندوق تعليق والأتجاه محدد
' هناك عدة أشكال لتعريف صندوق التعليقات وهذا ذو الأسطر المتعددة
note top of admin
                المقصود بالمدير هو
                مدير الموقع وليس
                مدير المتجر بحد ذاته
end note

@enduml

eg3.png

مثال على مخطط الأصناف (Class diagram):

@startuml

class animal as "حيوان" {
        + +الأطراف : int
        + +الدم : string
        + +العمر : int
        }

class gnu as "نو" {
        + +حوافر : int
}

class grass as "عشب" {
        + +سعرات : double
        + +تناول (int) : void
}

' علاقة وراثة
gnu -u-|> animal
' u == up

gnu "1"-r-"0..*" grass : "      يتناول          "
' r == right

@enduml

eg4.png

بالمثال السابق كان بالإمكان ترك أمر للترتيب التلقائي ولكن قمت بأدخال بعض الترتيبات

للمزيد من الأمثلة يرجى يرجى قراءة الشروحات الرسمية فهي نقطة أنطلاق جيدة ويمكن رؤية رابط لكل مخطط على الصفحة الرئيسية ولمعرفة كل الخيارات يمكن النظر بالدليل الرسمي.

قوالب جاهزة

مخطط التركيب (Deployment diagram) ذو المراحل الثلاث (Three-Tier):

@startuml

skinparam componentStyle uml1

node عميل #99c1f1 {
        [نقال]
        [متصفح]
}

node خادم #99c1f1 {
        [نمط] -d- [متحكم]
        [عرض] -u- [متحكم]
}

node "قاعدة بيانات" #99c1f1 {
        Database "\nقاعدة البيانات\n\n" as db
}

[متصفح] -- [عرض] : <<HTTP/S>>
[نقال] -- [متحكم] : <<HTTP/S>>
[نمط] -- db : <<JDB>>


@enduml

eg5.png

المعمارية المرجعية لتطبيقات الهاتف النقال (Mobile Application Reference Architecture):

@startuml

skinparam rectangleShadowing false
skinparam rectangleBorderStyle dashed
skinparam componentStyle uml1

node "                                          عميل                                            " as Client #99c1f1 {
        component "                       متصفح                       " as browser
}

node "خادم" as Server #99c1f1 {

        together {
        rectangle "(من طبقة العرض)" as one{
                        [الواجهة الرسومية] - [عمليات الواجهة الرسومية]
        }
        rectangle "(من طبقة العمليات)" as BL {
                        [واجهة التطبيق] -d- [خوارزميات\nالمعالجة]
                        [واجهة التطبيق] -d- [عناصر\nالعملية]
                        [واجهة التطبيق] -d- [مسار\nالعمليات]
        }

        rectangle "(من طبقة البيانات)" as DL {
                        [الوصول\nلقواعد البيانات] - [الأدوات\nالمساعدة]
                        [الأدوات\nالمساعدة] - [عامل\nالخدمات]
        }
        }

'       together {
        rectangle "القطاع المشترك" as two {
                [الأمان] -d- [إدارة العمليات]
                [إدارة العمليات] -d- [التواصل]

        }
'       }
}

node " " as db #99c1f1 {
        Database "\nمستودع بيانات\n"
}

node "أنظمة خارجية\nكنظام الخدمات البنكية\nوالدفع" as ext #99c1f1

browser -d- [الواجهة الرسومية]

[عمليات الواجهة الرسومية] -d- [واجهة التطبيق]

[الأدوات\nالمساعدة] -up- [عناصر\nالعملية]
[الأدوات\nالمساعدة] -up- [خوارزميات\nالمعالجة]
[الأدوات\nالمساعدة] -up- [مسار\nالعمليات]

[عامل\nالخدمات] -d- ext
[الوصول\nلقواعد البيانات] -d- db

one -[hidden]- two

@enduml

eg6.png

مخطط الوحدات (Modules diagram):

@startuml

skinparam rectangleShadowing false
skinparam rectangleBorderStyle dashed
skinparam componentStyle uml1

together {

rectangle "جانب العميل" as cs {
        package "العرض" as pcs {
                package "واجهة عرض المتجر" 
                package "واجهة عرض الإدارة" 
                package "واجهة متابعة الطلابات" 
        }
}

rectangle "جانب الخادم" as ss {
        package "وحدة المعالجة" as bss {
                package "متحكم المتجر"
                package "متحكم الإدارة"
                package "متحكم الطلابات"
        }

        package "البيانات" as dss {
                package "نمط السلع"
                package "نمط المستخدمين"
                package "نمط الطلابات"
        }
}

bss <.u.. pcs
dss <.u.. bss

}

@enduml

eg7.png

مثال موسع لمخطط وصف سلسلة الأحداث (Sequence diagram):

@startuml

hide footbox

' Model entity
' View boundary
' Controller control

actor "المستخدم" as user
actor "نظام خارجي" as ext

boundary متجر as ov <<عرض>>
control متجر as oc <<متحكم>>
entity متجر as om <<نمط>>


hnote over ext
        مجرد تعليق وضع هنا
        دون إي هدف يذكر
end note


oc -> om : سجل الطلب

oc -> ov : إشارة



note over ov
        تعليق من نوع أخر وضع
        في عمود واجهة عرض
        صنف المتجر فقط هكذا
end note




user -> oc : تأكيد ()

oc -> ext : إشارة مجدداً

ext -> ext : كعك

user -> ov : إنهاء الطلب

ov -> oc : إغلاق ($رقم)

@enduml

eg8.png

نصيحة إضافية

عند رسم أو نمذجة مخطط حالات الأستخدام (Use case diagram) فسوف يقوم تلقائياً بوضع الحالات أو العناصر بشكل عمودي واحدة تلو الأخرى لذلك يمكن وضعهم تحت مجاميع ورصهم أفقياً بهذه الحيلة:

@startuml

left to right direction

actor "تاجر" as boc
actor "إدارة الموقع" as admin
actor "نظام خارجي" as ext
actor "مستخدم" as con


package نظام {
        together {
                usecase "UC-1: شيءٌ ما" as uc1
                usecase "UC-2: شيءٌ ما" as uc2
                usecase "UC-3: شيءٌ ما" as uc3
                usecase "UC-4: شيءٌ ما" as uc4
                usecase "UC-12: شيءٌ ما" as uc12
                usecase "UC-5: شيءٌ ما" as uc5
                usecase "UC-10: شيءٌ ما" as uc10

                }
        together {
                usecase "UC-7: شيءٌ ما" as uc7
                usecase "UC-8: شيءٌ ما" as uc8
                usecase "UC-9: شيءٌ ما" as uc9
                usecase "UC-6: شيءٌ ما" as uc6
                usecase "UC-13: شيءٌ ما" as uc13
                usecase "UC-11: شيءٌ ما" as uc11
                }
}

uc1 -[hidden]- uc7

boc -- uc1
boc -- uc2
boc -- uc3
boc -- uc4
boc -- uc5
boc -- uc10
boc -- uc11
boc -- uc13

admin -- uc7
admin -|> boc

uc6 -- ext      

uc8 -- con
uc9 -- con

uc4 <. uc12 : <<extends>>

@enduml

eg9.png

وكما يمكنك إيضاً تضمين المخطط داخل الشفرة المصدرية ضمن تعليق و PlantUML سوف يتعرف عليه لأن يبدأ ب @startuml وينتهي بــ @enduml من ما يتيح لك أستخدامه مع مولدات الوثائق (Documentation generators) مثل GtkDoc و JavaDoc و Doxygen وغيرها من المولدات وهذا مثال لتضمين المخطط السابق داخل شفرة مصدرية للغة البرمجة سي (C programming language):

/*
  @startuml

  left to right direction

  actor "تاجر" as boc
  actor "إدارة الموقع" as admin
  actor "نظام خارجي" as ext
  actor "مستخدم" as con


  package نظام {
  together {
  usecase "UC-1: شيءٌ ما" as uc1
  usecase "UC-2: شيءٌ ما" as uc2
  usecase "UC-3: شيءٌ ما" as uc3
  usecase "UC-4: شيءٌ ما" as uc4
  usecase "UC-12: شيءٌ ما" as uc12
  usecase "UC-5: شيءٌ ما" as uc5
  usecase "UC-10: شيءٌ ما" as uc10

  }
  together {
  usecase "UC-7: شيءٌ ما" as uc7
  usecase "UC-8: شيءٌ ما" as uc8
  usecase "UC-9: شيءٌ ما" as uc9
  usecase "UC-6: شيءٌ ما" as uc6
  usecase "UC-13: شيءٌ ما" as uc13
  usecase "UC-11: شيءٌ ما" as uc11
  }
  }

  uc1 -[hidden]- uc7

  boc -- uc1
  boc -- uc2
  boc -- uc3
  boc -- uc4
  boc -- uc5
  boc -- uc10
  boc -- uc11
  boc -- uc13

  admin -- uc7
  admin -|> boc

  uc6 -- ext    

  uc8 -- con
  uc9 -- con

  uc4 <. uc12 : <<extends>>

  @enduml
*/
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  printf("Happy, Hacking\n");
  return 0;
}

برامج مماثلة

  • برنامج GraphViz (برنامج طريقته مشابهة لـ PlantUML وبالحقيقة مستخدم داخلياً من PlantUML ولكنه عام وغير مخصص للـ UML).
  • برنامج ditaa (يقوم بتحويل النصوص الفنية -ASCII ART- إلى صور ويمكن أستخدامه مع artist-mode الخاص بإيماكس).

comments . التعليقات

الهوامش:

2

لغة النمذجة الموحدة ويكيبيديا