UML: مخططات الفئات والكائنات

من مخطط الأصناف إلى قاعدة البيانات والكود

18 دقيقة الدرس 9 من 10

من مخطط الأصناف إلى قاعدة البيانات والكود

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

لماذا يهم التحويل؟

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

القاعدة الأولى — كل صنف يصبح جدولًا

يتحول كل صنف ملموس في المخطط إلى جدول. يصبح اسم الصنف اسمًا للجدول (عادةً بصيغة الجمع في التطبيق). وكل خاصية تصبح عمودًا، ويُحوَّل نوع UML إلى نوع قاعدة بيانات:

  • StringVARCHAR
  • IntegerINT
  • BooleanTINYINT(1) أو BOOLEAN
  • Date / DateTimeDATE / DATETIME
  • DecimalDECIMAL(p,s)

يحصل كل جدول أيضًا على مفتاح رئيسي بديل (id) ما لم يحدد النموذج مفتاحًا طبيعيًا. في الكود، يصبح الصنف ملفًا يحوي حقولًا خاصة ومناهج قراءة/كتابة.

القاعدة الثانية — الارتباطات تصبح مفاتيح خارجية

تحدد التعددية في الارتباط موضع المفتاح الخارجي بدقة:

  • واحد إلى كثير (1 → 0..*) — يُوضع المفتاح الخارجي في جانب الكثير. مثلًا: Order ينتمي إلى Customer واحد، فيضاف عمود customer_id إلى جدول orders.
  • واحد إلى واحد (1 → 0..1) — يُوضع المفتاح الخارجي في الجانب الأضعف أو الاختياري، مع قيد UNIQUE.
  • كثير إلى كثير (* → *) — يستلزم جدول وسيط يحمل مفتاحين خارجيين ومفتاحًا رئيسيًا خاصًا.

في الكود، يصبح ارتباط واحد-إلى-كثير حقل مجموعة على جانب الواحد (مثل List<Order> orders) وحقل مرجعي على جانب الكثير (مثل Customer customer).

القاعدة الثالثة — التجميع والتركيب

يُعامَل التجميع معاملة الارتباط العادي في قاعدة البيانات — مفتاح خارجي في جانب الجزء أو جدول وسيط للكثير-إلى-كثير. أما التركيب فيعبّر عن ملكية أقوى: لا يوجد الجزء بدون الكل. في قاعدة البيانات، أضف ON DELETE CASCADE إلى المفتاح الخارجي حتى تُحذف الأجزاء تلقائيًا عند حذف الكل.

Class Diagram to Database and Code mapping for an online store Class Diagram Customer + id : Integer + name : String + email : String + placeOrder() : Order 1 0..* Order + id : Integer + date : DateTime + total : Decimal + confirm() : void + cancel() : void * * OrderItem + quantity : Integer + unitPrice : Decimal Product + id : Integer + name : String + price : Decimal + stock : Integer + getDetails() : String maps to Database Tables customers 🔑 id INT PK AUTO_INCREMENT name VARCHAR(255) email VARCHAR(255) UNIQUE created_at DATETIME orders 🔑 id INT PK 🔗 customer_id INT FK date DATETIME total DECIMAL(10,2) status VARCHAR(20) order_items 🔗 order_id INT FK 🔗 product_id INT FK quantity INT unit_price DECIMAL(10,2) 🔑 = مفتاح رئيسي 🔗 = مفتاح خارجي
مخطط أصناف متجر إلكتروني (يسار) مُحوَّل إلى جداول قاعدة بيانات علائقية (يمين). يتحول ارتباط الكثير-إلى-كثير بين Order وProduct إلى جدول وسيط order_items.

القاعدة الرابعة — استراتيجيات تعيين الوراثة

للوراثة ثلاث استراتيجيات شائعة في قواعد البيانات العلائقية:

  1. وراثة الجدول الواحد (STI) — جدول واحد لكامل التسلسل الهرمي مع عمود تمييز type. بسيطة لكنها تهدر مساحة بسبب الأعمدة الفارغة.
  2. وراثة الجدول لكل صنف (CTI) — جدول لكل صنف في التسلسل؛ المفتاح الرئيسي لجدول الصنف الفرعي هو أيضًا مفتاح خارجي إلى الجدول الأصلي. مُعيَّر لكن يتطلب JOINs.
  3. وراثة الجدول الملموس — جدول لكل صنف ورقي فقط مع تكرار خصائص الأصل. قراءة سريعة لكن بتكرار بيانات.
Inheritance mapped to Class Table Inheritance (CTI) database strategy Class Diagram (Inheritance) «abstract» Payment + id : Integer + amount : Decimal + process() : Boolean CardPayment + cardNumber : String + expiry : String CashPayment + receivedAmount : Decimal + changeGiven : Decimal CTI strategy Database (CTI) payments 🔑 id INT PK amount DECIMAL(10,2) type VARCHAR(20) card_payments 🔗 id INT PK+FK → payments card_number VARCHAR(20) expiry VARCHAR(7) cash_pmts 🔗 id FK received change CTI: كل صنف فرعي له جدوله الخاص. المفتاح الرئيسي للجدول الفرعي هو أيضًا مفتاح خارجي للجدول الأصلي.
تسلسل وراثة Payment مُحوَّل باستراتيجية CTI: جدول لكل صنف، والمفتاح الرئيسي في الجداول الفرعية يعمل أيضًا مفتاحًا خارجيًا نحو جدول payments الأصلي.

القاعدة الخامسة — أصناف الارتباط تصبح جداول وسيطة

عندما تحمل علاقة كثير-إلى-كثير خصائص خاصة (صنف ارتباط)، تصبح تلك الخصائص أعمدة في الجدول الوسيط. في المثال السابق، يحمل OrderItem خصائص quantity وunitPrice: تصبح هذه أعمدة في جدول order_items إلى جانب المفتاحين الخارجيين.

القاعدة السادسة — الأصناف المجردة والواجهات

لا تحصل الأصناف المجردة على جدول خاص بها في استراتيجية الجدول الملموس، لكنها تحصل على جدول في CTI. أما الواجهات فلا تقابلها أي بنية في قاعدة البيانات — فهي مفهوم كودي خالص. في الكود، تصبح الأصناف المجردة تعريفات abstract class وتصبح الواجهات تعريفات interface بتواقيع مناهج بدون جسم تنفيذي.

مثال على هيكل الكود

الترجمة إلى كود بنفس القدر من الانتظام. تأمل صنف Order من المتجر الإلكتروني. يبدو الهيكل الأساسي المشتق من مخطط الأصناف هكذا:

// Java-style skeleton derived from the class diagram public class Order { private int id; private Customer customer; // association → reference field private List<OrderItem> items; // composition → collection private LocalDateTime date; private BigDecimal total; private String status; public Order(Customer customer) { this.customer = customer; this.items = new ArrayList<>(); this.date = LocalDateTime.now(); this.status = "PENDING"; } public void confirm() { this.status = "CONFIRMED"; } public void cancel() { this.status = "CANCELLED"; } public BigDecimal getTotal() { return this.total; } }

لاحظ كيف يصبح كل وصف UML حقلًا خاصًا، وكل ارتباط حقل مرجع أو مجموعة، وكل عملية UML منهجًا. يفرض المُنشئ الارتباط الإلزامي: لا طلب بدون زبون.

نصيحة للمحلل — قف عند الحدود. دورك كمحلل أنظمة هو إنتاج مخطط أصناف صحيح ومكتمل. المطورون يملكون خطوة توليد الكود. لكن معرفة قواعد التحويل تساعدك على اكتشاف الأخطاء مبكرًا: إذا تعذّر تحويل مخططك إلى جداول بشكل نظيف، فالنموذج نفسه قد يحوي خللًا — تعددية مفقودة أو ارتباط في غير مكانه أو صنف زائد.
أسماء متسقة أمر بالغ الأهمية. استخدم PascalCase لأسماء الأصناف وcamelCase للخصائص والعمليات في UML. عند توليد الجداول، حوّل إلى snake_case (مثل OrderItemorder_items). تجنب التسمية التعسفية بين النموذج والتنفيذ.
لا تُفرد التركيب إلى خصائص منفردة. من الأخطاء الشائعة تمثيل الجزء المُركَّب (مثل Address داخل Customer) كمجموعة حقول نصية في الصنف الأصلي. هذا يكسر التطبيع ويخفي البنية. نمذجه كصنف مستقل، ثم قرر في قاعدة البيانات هل يستحق جدولًا خاصًا أم تُدمج أعمدته في الجدول الأصلي — لكن اجعل ذلك قرارًا واعيًا.

قائمة مراجعة: من مخطط الأصناف إلى قاعدة البيانات

  1. كل صنف ملموس ← جدول واحد.
  2. كل خاصية ← عمود واحد بالنوع SQL الصحيح.
  3. ارتباط واحد-إلى-كثير ← مفتاح خارجي في جدول جانب الكثير.
  4. ارتباط كثير-إلى-كثير (بصنف ارتباط أو بدونه) ← جدول وسيط بمفتاحين خارجيين.
  5. التركيب ← أضف ON DELETE CASCADE للمفتاح الخارجي.
  6. الوراثة ← اختر STI أو CTI أو جدول ملموس وطبّق بالتزام.
  7. الأصناف المجردة ← جدول فقط في CTI (يحمل الأعمدة المشتركة).
  8. الواجهات ← لا جدول، لا أعمدة — كود فحسب.

بهذه القواعد في يدك، يمكنك تسليم مطوّر مخططَ أصناف وورقة قرارات التحويل، ليتمكن من بناء قاعدة بيانات وبنية كود صحيحة دون تخمين. هذه الدقة هي سمة المحلل الاحترافي.