الفرق بين المراجعتين ل"Refactoring/introduce local extension"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط
ط (مراجعة وتدقيق.)
 
سطر 9: سطر 9:
  
 
==== قبل إعادة التصميم ====
 
==== قبل إعادة التصميم ====
يعتمد صنف العميل (ClientClass) على الصنف المساعد Date ولكنّه بحاجة إلى بعض التوابع غير الموجودة فيه (كتابع الحصول على اليوم التالي مثلًا):
+
يعتمد صنف العميل <code>ClientClass</code> على الصنف المساعد <code>Date</code> ولكنّه بحاجة إلى بعض التوابع غير الموجودة فيه (كتابع الحصول على اليوم التالي مثلًا):
[[ملف:Introduce-Local-Extension-Before.png|بديل=الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date.|بدون|إطار|الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date.]]
+
[[ملف:Introduce-Local-Extension-Before.png|بديل=الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date.|بدون|الصنف العميل <code>ClientClass</code> الذي يعتمد على الصنف المساعد Date.|تصغير]]
  
 
==== بعد إعادة التصميم ====
 
==== بعد إعادة التصميم ====
 
أصبح هنالك صنف جديد باسم <code>MfDate</code> يُعَدُّ صنفًا (subclass) فرعيًا  للصنف المساعد <code>Date</code> يحتوي التوابع اللازمة، كما في المخطط:
 
أصبح هنالك صنف جديد باسم <code>MfDate</code> يُعَدُّ صنفًا (subclass) فرعيًا  للصنف المساعد <code>Date</code> يحتوي التوابع اللازمة، كما في المخطط:
[[ملف:Introduce-Local-Extension-After.png|بديل=الصنف MfDate الفرعي للصنف المساعد Date.|بدون|إطار|الصنف MfDate الفرعي للصنف المساعد Date.]]
+
[[ملف:Introduce-Local-Extension-After.png|بديل=الصنف MfDate الفرعي للصنف المساعد Date.|بدون|الصنف <code>MfDate</code> الفرعي للصنف المساعد <code>Date</code>.|تصغير]]
  
 
== لم إعادة التصميم؟ ==
 
== لم إعادة التصميم؟ ==
سطر 38: سطر 38:
 
* [https://refactoring.guru/introduce-local-extension صفحة توثيق تعريف الإضافات المحليّة في موقع refactoring.guru.]
 
* [https://refactoring.guru/introduce-local-extension صفحة توثيق تعريف الإضافات المحليّة في موقع refactoring.guru.]
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring]]
 +
[[تصنيف:Refactoring Techniques]]
 +
[[تصنيف:Refactoring Moving Features between Objects]]

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

المشكلة

الحاجة إلى بعض التوابع (methods) غير الموجودة في الصنف المساعد (utility class)، ومن غير الممكن إضافتها إلى ذلك الصنف.

الحل

إنشاء صنفٍ (class) جديدٍ يحتوي التوابع اللازمة، وجعله كصنف تغليفٍ (wrapper) للصنف المساعد أو كصنفٍ فرعيٍّ (subclass) له.

مثال

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

يعتمد صنف العميل ClientClass على الصنف المساعد Date ولكنّه بحاجة إلى بعض التوابع غير الموجودة فيه (كتابع الحصول على اليوم التالي مثلًا):

الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date.
الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date.

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

أصبح هنالك صنف جديد باسم MfDate يُعَدُّ صنفًا (subclass) فرعيًا  للصنف المساعد Date يحتوي التوابع اللازمة، كما في المخطط:

الصنف MfDate الفرعي للصنف المساعد Date.
الصنف MfDate الفرعي للصنف المساعد Date.

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

ما الأسوء من أن تحتاج تابعًا في الصنف فلا تجده؟! ألا تستطيع إضافته! (بسبب وجوده في مكتبةٍ لا تملك صلاحية التعديل على مكوناتها مثلًا)، وإليك الحل:

  1. إنشاء صنفٍ فرعيّ (subclass) من الصنف المساعد، يحتوي على التوابع التي تحتاجها من بعد أن يرِث (inherit) كافّة التوابع والحقول (fields) الأخرى من صنفه الأعلى (وهو الصنف المساعد الأساسيّ)، وهذه الطريقة من أسهل الطرق إلا أنّها قد تصبح مستحيلةً بوجود المعامل final للصنف المساعد ممّا يمنع الوراثة منه.
  2. إنشاء صنف تغليفٍ (wrapper class) يحتوي على كافّة التوابع اللازمة وينتقل (delegate) عند الضرورة إلى الكائن المأخوذ من الصنف المساعد (utility class object)، وهذه الطريقة أصعب قليلًا بسبب الحاجة إلى شيفرةٍ للربط ما بين صنف التغليف وكائن الصنف المساعد (utility class object)، بالإضافة إلى عددٍ كبيرٍ من التوابع لتوفير الانتقال (delegation)، والتي تُعَدُّ بمثابة واجهةٍ عامةٍ (public interface) للصنف المساعد.

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

التقليل من الشيفرة الموجودة في صنف العميل (client class)، والتي قد لا تتعلَّق أصلًا بمهامه الفعليّة (هدفها فقط الحصول على ما لا يحتويه الصنف المساعد)، وبإضافة صنفٍ جديدٍ (إما صنف تغليفٍ أو صنف فرعيّ) لاحتواء تلك التوابع ستصبح مكوِّنات البرنامج أكثر ترابطًا ومتاحةً لإعادة الاستخدام المتكرِّر (reusability).

آلية الحل

  1. إنشاء صنفٍ إضافيٍّ وبهذا تكون أمام خيارين: الأول: جعله صنفًا فرعيًا للصنف المساعد (utility class) بإنشاء علاقة وراثة (inheritance). الثاني: جعله صنف تغليفٍ ولا بُدَّ حينها من تخصيص حقلٍ (field) فيه لتخزين كائن الصنف المساعد الذي سيكون الانتقال (delegation) إليه، وستحتاج كذلك إلى إضافة توابع عامّة (public methods) تتوافق مع التوابع الأساسية في الصنف المساعد، يحتوي كلٌّ منها على انتقال (delegation) إلى التابع الأصلي المماثل له في كائن الصنف المساعد.
  2. إنشاء بانٍ (constructor) لهذا الصنف يستخدم نفس معاملات (parameters) الباني الأساسيِّ للصنف المساعد (utility class).
  3. إنشاء بانٍ بديل يقبل معاملًا واحدًا فقط وهو كائن الصنف الأساسيّ، وهذا سيساعد على تعويض الصنف الأصليّ بكائن إضافي (extension).
  4. إنشاء توابع إضافيّة (extension methods) في الصنف، ونقل كافة التوابع الدخيلة (foreign methods) من الأصناف الأخرى إلى هذا الصنف، أو من الممكن حذف التوابع الدخيلة إن كانت تكرِّر مهامًا موجودةً في التوابع الإضافيّة.
  5. تبديل استخدام الصنف المساعد إلى استخدام الصنف الإضافي في كل موضعٍ يحتاجه.

انظر أيضًا

مصادر