تبديل قيم البيانات إلى كائنات (Replace Data Values with Objects)

من موسوعة حسوب

المشكلة

وجود حقلٍ (field) مٌخصَّص للبيانات في صنفٍ (class) ما (أو في عددٍ من الأصناف)، ولهذا الحقل بياناته وسلوكه (behaviour) المرتبط به.

الحل

إنشاء صنفٍ جديدٍ ليُوضَع فيه الحقل (field) بالإضافة إلى سلوكه المرتبط به، وتخزين كائنٍ (object) من هذا الصنف الجديد في الصنف الأصليّ للحقل.

مثال

قبل إعادة التصميم

يحتوي الصنف Order على الحقل customer الذي يحتوي بيانات نصيّة (من النوع String) كما هو واضح في مخطط الأصناف الآتي:

الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.
الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.

بعد إعادة التصميم

أصبح هنالك صنفٌ جديدٍ باسم Customer لتخزين بيانات الحقل السابق (الحقل customer) باسم name ويرتبط الصنفان بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له)، فيصبح المخطط بالشكل:

مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).
مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).

لم إعادة التصميم؟

تُعَدُّ هذه التقنية حالةً خاصة من تقنية استخراج الصنف (Extract Class) وتختلفان بالسبب وراء إعادة التصميم (refactoring)؛ ففي استخراج الصنف، هنالك صنفٌ وحيدٌ مسؤولٌ عن عدّة مهامٍ تُوزَّع عبر إعادة التصميم على الأصناف الأخرى، أما في حالة تحويل قيم البيانات إلى كائنٍ (object) من صنفٍ جديدٍ فهنالك حقلٌ أساسيّ (primitive field) يحتوي على بيانات عدديّة أو نصيّة أو …إلخ. ولم يعد التعامل معه أمرًا بسيطًا بسبب تطوير البرنامج وازدياد تعقيده، إذ أصبح لهذا الحقل بياناته وسلوكه المرتبط به، كما وقد تتكرَّر هذه المجموعة من «الحقل وارتباطاته» في عدّة أصنافٍ أخرى وبإعادة التصميم ستحدُّ من تكرار الشيفرة بلا جدوى، وبهذا يكون من الأفضل إفرادُ حقل البيانات (مع كافّة ما يرتبط به) في صنفٍ خاصٍّ به وإنشاء كائنٍ ينوب عنه في صنفه الأصليّ.

فوائد تطبيق الحل

تحسين الارتباط (relatedness) داخل الأصناف، إذ تُوضَع البيانات في صنفٍ واحدٍ مع كلِّ ما يتعلَّق بها من عمليات.

آلية الحل

قبل البدء بأيّة خطوة من خطوات الحل يجب التأكُّد أولًا من عدم وجود مرجعيّات مباشرة (direct references) لهذا الحقل (field) من داخل الصنف (class) ذاته، فإن وُجِدت فيكمن الحل بتقنية التغليف الداخليّ للحقل (Self Field Encapsulation) لإخفائه في الصنف الأصليّ، وإن لم يكن كذلك فخطوات تقنية الحل الحاليّة هي:

  1. إنشاء صنفٍ جديدٍ ونسخ الحقل وتابع وصوله getter إليه، ثمَّ إنشاء بانٍ (constructor) يقبل قيمة هذا الحقل كمعاملٍ (parameter) له، ويجب ألّا يحتوي الصنف على تابع setter لأنّ ذلك يعني إنشاء كائنٍ بالقيمة الجديدة كلما استُدعي التابع من الصنف الأصليّ.
  2. تغيير نوع الحقل (field type) في الصنف الأصليّ ليصبح من نوع الصنف الجديد.
  3. استدعاء التابع getter للكائن (object) المعبِّر عن الحقل من داخل التابع getter في الصنف الأصليّ.
  4. إنشاء كائنٍ بالقيمة الجديدة داخل التابع setter، وقد تحتاج إلى إنشاء كائنٍ جديدٍ أيضًا في الباني (constructor) إن كان هنالك قيمٌ أوليّة (initial values) تُسند إلى الحقل سابقًا.

ما الخطوة التالية؟

يُستحسَن تطبيق تقنية الحل بتغيير القيمة إلى مرجعيّة (Change Value to Reference) على الحقل الذي يحتوي الكائن من بعد تطبيق تقنية الحل السابقة، وذلك لضمان وجود مرجعيّةٍ إلى كائنٍ واحدٍ فقط متناسبٍ مع القيمة بدلًا من تحزين العشرات من الكائنات لحفظ قيمة واحدة! وغالبًا ما تُستخدَم هذه التقنية للحصول على كائنٍ برمجيٍّ واحدٍ يقابل كلَّ كائنٍ على أرض الواقع (مستخدِمٍ أو طلبٍ أو مستندٍ أو ...إلخ.)، ولن تكون هذه التقنية نافعةً للكائنات مثل التاريخ (date) أو العملة (money) أو المجالات (ranges) أو ...إلخ.

انظر أيضًا

مصادر