الفرق بين المراجعتين لصفحة: «Refactoring/replace data value with object»

من موسوعة حسوب
طلا ملخص تعديل
ط مراجعة وتدقيق.
 
(مراجعة متوسطة واحدة بواسطة مستخدم واحد آخر غير معروضة)
سطر 10: سطر 10:
==== قبل إعادة التصميم ====
==== قبل إعادة التصميم ====
يحتوي الصنف <code>Order</code> على الحقل <code>customer</code> الذي يحتوي بيانات نصيّة (من النوع <code>String</code>) كما هو واضح في مخطط الأصناف الآتي:
يحتوي الصنف <code>Order</code> على الحقل <code>customer</code> الذي يحتوي بيانات نصيّة (من النوع <code>String</code>) كما هو واضح في مخطط الأصناف الآتي:
[[ملف:Replace-Data-Value-with-Object-Before.png|بديل=الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.|بدون|إطار|الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.]]
[[ملف:Replace-Data-Value-with-Object-Before.png|بديل=الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.|بدون|الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة.|تصغير|200x200بك]]


==== بعد إعادة التصميم ====
==== بعد إعادة التصميم ====
أصبح هنالك صنفٌ جديدٍ باسم <code>Customer</code> لتخزين بيانات الحقل السابق (الحقل <code>customer</code>) باسم <code>name</code> ويرتبط الصنفان بعلاقة has a (أي بمجرد وجود كائن <code>Order</code> فلا بد من وجود كائن <code>Customer</code> له)، فيصبح المخطط بالشكل:
أصبح هنالك صنفٌ جديدٍ باسم <code>Customer</code> لتخزين بيانات الحقل السابق (الحقل <code>customer</code>) باسم <code>name</code> ويرتبط الصنفان بعلاقة has a (أي بمجرد وجود كائن <code>Order</code> فلا بد من وجود كائن <code>Customer</code> له)، فيصبح المخطط بالشكل:
[[ملف:Replace-Data-Value-with-Object-After.png|بديل=مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).|بدون|إطار|مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).]]
[[ملف:Replace-Data-Value-with-Object-After.png|بديل=مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).|بدون|مخطط يوضح كيفية ارتباط الصنفين Customer و Order بعلاقة has a (أي بمجرد وجود كائن Order فلا بد من وجود كائن Customer له).|تصغير|400x400بك]]


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


== فوائد تطبيق الحل ==
== فوائد تطبيق الحل ==
سطر 23: سطر 23:


== آلية الحل ==
== آلية الحل ==
قبل البدء بأيّة خطوة من خطوات الحل يجب التأكُّد أولًا من عدم وجود مرجعيّات مباشرة (direct references) لهذا الحقل (field) من داخل الصنف (class) ذاته، فإن وُجِدت فيكمن الحل بتقنية التغليف الداخليّ للحقل (Self Field Encapsulation) لإخفائه في الصنف الأصليّ، وإن لم يكن كذلك فخطوات تقنية الحل الحاليّة هي:
قبل البدء بأيّة خطوة من خطوات الحل يجب التأكُّد أولًا من عدم وجود مرجعيّات مباشرة (direct references) لهذا الحقل (field) من داخل الصنف (class) ذاته، فإن وُجِدت فيكمن الحل بتقنية [[Refactoring/self encapsulate field|التغليف الداخليّ للحقل]] (Self Field Encapsulation) لإخفائه في الصنف الأصليّ، وإن لم يكن كذلك فخطوات تقنية الحل الحاليّة هي:
# إنشاء صنفٍ جديدٍ ونسخ الحقل وتابع وصوله <code>getter</code> إليه، ثمَّ إنشاء بانٍ (constructor) يقبل قيمة هذا الحقل كمعاملٍ (parameter) له، ويجب ألّا يحتوي الصنف على تابع <code>setter</code> لأنّ ذلك يعني إنشاء كائنٍ بالقيمة الجديدة كلما استُدعي التابع من الصنف الأصليّ.
# إنشاء صنفٍ جديدٍ ونسخ الحقل وتابع وصوله <code>getter</code> إليه، ثمَّ إنشاء بانٍ (constructor) يقبل قيمة هذا الحقل كمعاملٍ (parameter) له، ويجب ألّا يحتوي الصنف على تابع <code>setter</code> لأنّ ذلك يعني إنشاء كائنٍ بالقيمة الجديدة كلما استُدعي التابع من الصنف الأصليّ.
# تغيير نوع الحقل (field type) في الصنف الأصليّ ليصبح من نوع الصنف الجديد.
# تغيير نوع الحقل (field type) في الصنف الأصليّ ليصبح من نوع الصنف الجديد.
سطر 30: سطر 30:


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


== انظر أيضًا ==
== انظر أيضًا ==
سطر 38: سطر 38:
* [https://refactoring.guru/replace-data-value-with-object صفحة توثيق تبديل قيم البيانات إلى كائنات في موقع refactoring.guru.]
* [https://refactoring.guru/replace-data-value-with-object صفحة توثيق تبديل قيم البيانات إلى كائنات في موقع refactoring.guru.]
[[تصنيف:Refactoring]]
[[تصنيف:Refactoring]]
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Refactoring Organizing Data]]

المراجعة الحالية بتاريخ 09:43، 2 مارس 2019

المشكلة

وجود حقلٍ (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) أو ...إلخ.

انظر أيضًا

مصادر