الفرق بين المراجعتين ل"Refactoring/extract subclass"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: استخراج الأصناف الفرعية (Extract Subclass)}}</noinclude> == المشكلة == يكون للصنف ميزات تستعم...')
 
ط (مراجعة وتدقيق.)
 
سطر 9: سطر 9:
  
 
==== قبل إعادة التصميم ====
 
==== قبل إعادة التصميم ====
[[ملف:Extract Subclass - Before.png|بديل=يكون للصنف ميزات تستعمل فقط في حالات معينة.|بدون|تصغير|يكون للصنف ميزات تستعمل فقط في حالات معينة.]]
+
يراد استعمال الصنف <code>Job</code> - بالإضافة إلى استعماله الطبيعي أيضًا - في حالات مخصصة فقط:[[ملف:Extract Subclass - Before.png|بديل=يكون للصنف ميزات تستعمل فقط في حالات معينة.|بدون|تصغير|يكون للصنف ميزات تستعمل فقط في حالات معينة.]]
  
 
==== بعد إعادة التصميم ====
 
==== بعد إعادة التصميم ====
[[ملف:Extract Subclass - After.png|بديل=إنشاء صنف فرعي واستخدامه في هذه الحالات.|بدون|تصغير|إنشاء صنف فرعي واستخدامه في هذه الحالات.]]
+
إنشاء الصنف الفرعي <code>Labor</code> الذي سيخصص لحالات الاستعمال النادرة تلك من الصنف <code>Job</code>:[[ملف:Extract Subclass - After.png|بديل=إنشاء صنف فرعي واستخدامه في هذه الحالات.|بدون|تصغير|إنشاء صنف فرعي واستخدامه في هذه الحالات.]]
  
 
== لم إعادة التصميم؟ ==
 
== لم إعادة التصميم؟ ==
سطر 22: سطر 22:
  
 
== مساوئ تطبيق الحل ==
 
== مساوئ تطبيق الحل ==
* على الرغم من ما يبدو عليه من بساطة، يمكن أن يؤدي التوريث إلى طريق مسدود إذا كان عليك فصل عدة تسلسلات هرمية مختلفة للصنف. إذا وُجِد على سبيل المثال الصنف <code>كلاب</code> وله سلوك مختلف اعتمادا على حجم وفراء الكلاب، يمكن استنباط اثنين من التسلسلات الهرمية:
+
* على الرغم من ما يبدو عليه من بساطة، يمكن أن يؤدي التوريث إلى طريق مسدود إذا كان عليك فصل عدة تسلسلات هرمية مختلفة للصنف. إذا وُجِد على سبيل المثال الصنف <code>Dogs</code> وله سلوكًا مختلفًا اعتمادًا على حجم وفراء الكلاب، يمكن استنباط اثنين من التسلسلات الهرمية:
** بحسب الحجم: <code>كبير</code> و <code>متوسط</code> و <code>صغير</code>
+
** بحسب الحجم: <code>Large</code> و <code>Medium</code> و <code>Small</code>
** بحسب الفراء: <code>ناعم</code> و <code>أشعث</code>
+
** بحسب الفراء: <code>Smooth</code> و <code>Shaggy</code>
كل شيء سيكون على ما يرام، إلا أن المشاكل سوف تتفاقم حالما تحتاج إلى إنشاء صنف كلب يكون <code>كبير</code> و <code>ناعم</code> على حد سواء، إذ يمكنك إنشاء كائن من صنفٍ واحدٍ فقط. ومع ذلك، يمكنك تجنب هذه المشكلة باستخدام التركيب بدلا من الميراث (انظر نمط [[Refactoring/strategy|الاستراتيجية]]). وبعبارة أخرى، سيكون للصنف كلاب حقلين مكونين، الحجم والفراء. ستقوم بتركيب العناصر المكونة من الأصناف اللازمة إلى هذه الحقول. حتى تتمكن من إنشاء كلب لديه <code>حجم_كبير</code> و<code>فراء_أشعث</code>.
+
كل شيء سيكون على ما يرام، إلا أن المشاكل سوف تتفاقم حالما تحتاج إلى إنشاء صنف كلب يكون <code>Large</code> و <code>Smooth</code> على حد سواء، إذ يمكنك إنشاء كائن من صنفٍ واحدٍ فقط. ومع ذلك، يمكنك تجنب هذه المشكلة باستخدام التركيب بدلًا من الميراث (انظر نمط [[Design Patterns/strategy|الاستراتيجية]]). وبعبارة أخرى، سيكون للصنف <code>Dog</code> حقلين مكونين، الحجم والفراء. ستقوم بتركيب العناصر المكونة من الأصناف اللازمة إلى هذه الحقول. حتى تتمكن من إنشاء كلب <code>Dog</code> لديه حجم كبير <code>LargeSize</code> وفراء أشعث <code>ShaggyFur</code>.
  
 
== آلية الحل ==
 
== آلية الحل ==
# أنشئ صنف فرعي جديدة من الصنف المعني.
+
# أنشئ صنفًا فرعيًّا جديدًا من الصنف المعني.
# إذا كنت بحاجة إلى بيانات إضافية لإنشاء كائنات من صنفٍ فرعي، أنشئ مُنشِئ واضف المعاملات اللازمة إليه. لا تنسى استدعاء تطبيق أصل المُنشئ.
+
# إذا كنت بحاجة إلى بيانات إضافية لإنشاء كائنات من صنفٍ فرعي، أنشئ بانيًّا وأضف المعاملات اللازمة إليه. لا تنسَ استدعاء تطبيق أصل الباني.
# ابحث عن كل استدعاءات مُنشئ الصنف الأصل. عندما تكون وظيفة الصنف الفرعي ضرورية، يستعاض عن المُنشئ الأصل بالمُنشئ الفرعي.
+
# ابحث عن كل استدعاءات باني الصنف الأصل. عندما تكون وظيفة الصنف الفرعي ضرورية، يستعاض عن الباني الأصل بالباني الفرعي.
 
# انقل التوابع والحقول الضرورية من الصنف الأصل إلى الصنف الفرعي. قم بهذا من خلال [[Refactoring/push down method|دفع التابع لأسفل]] و<nowiki/>[[Refactoring/push down field|دفع الحقل لأسفل]]. من الأسهل البدء بنقل التوابع أولًا. وبهذه الطريقة، تظل الحقول متاحة طوال العملية بأكملها: من الصنف الأصل قبيل الانتقال، ومن الصنف الفرعي نفسه بعد اكتمال النقل.
 
# انقل التوابع والحقول الضرورية من الصنف الأصل إلى الصنف الفرعي. قم بهذا من خلال [[Refactoring/push down method|دفع التابع لأسفل]] و<nowiki/>[[Refactoring/push down field|دفع الحقل لأسفل]]. من الأسهل البدء بنقل التوابع أولًا. وبهذه الطريقة، تظل الحقول متاحة طوال العملية بأكملها: من الصنف الأصل قبيل الانتقال، ومن الصنف الفرعي نفسه بعد اكتمال النقل.
# بعد أن يكون الصنف الفرعي جاهزًا، ابحث عن كل الحقول القديمة التي تحكمت في اختيار الوظيفة. احذف هذه الحقول باستخدام التعدديّة الشكليّة لتحل محل جميع العوامل التي استخدمت فيها الحقول. مثال بسيط: في صنف السيارات، يوجد الحقل <code>هي_سيارة_كهربية</code>، واعتمادًا عليه، في تابع <code>التزود_بالوقود()</code> تكون السيارة إما مزودة بالمحروقات أو مشحونة بالكهرباء. بعد إعادة التصميم، يحذف الحقل <code>هي_سيارة_كهربية</code> وسيكون للصنفين السيارات و<code>سيارة_كهربية</code> التطبيقات الخاصة بهما في تابع <code>التزود_بالوقود()</code>.
+
# بعد أن يكون الصنف الفرعي جاهزًا، ابحث عن كل الحقول القديمة التي تحكمت في اختيار الوظيفة. احذف هذه الحقول باستخدام التعدديّة الشكليّة لتحل محل جميع العوامل التي استخدمت فيها الحقول. مثال بسيط: في صنف السيارات، يوجد الحقل <code>isElectricCar</code>، واعتمادًا عليه، في التابع <code>()refuel</code>، تكون السيارة إما مزودة بالمحروقات أو مشحونة بالكهرباء. بعد إعادة التصميم، يحذف الحقل <code>isElectricCar</code> وسيكون للصنفين <code>Car</code> و <code>ElectricCar</code> التطبيقات الخاصة بهما في تابع <code>()refuel</code>.
  
 
== انظر أيضًا ==
 
== انظر أيضًا ==
سطر 42: سطر 42:
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring Techniques]]
 
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Dealing with Generalization]]
+
[[تصنيف:Refactoring Dealing with Generalization]]

المراجعة الحالية بتاريخ 09:56، 26 فبراير 2019

المشكلة

يكون للصنف ميزات تستعمل فقط في حالات معينة.

الحل

إنشاء صنف فرعي واستخدامه في هذه الحالات.

مثال

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

يراد استعمال الصنف Job - بالإضافة إلى استعماله الطبيعي أيضًا - في حالات مخصصة فقط:

يكون للصنف ميزات تستعمل فقط في حالات معينة.
يكون للصنف ميزات تستعمل فقط في حالات معينة.

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

إنشاء الصنف الفرعي Labor الذي سيخصص لحالات الاستعمال النادرة تلك من الصنف Job:

إنشاء صنف فرعي واستخدامه في هذه الحالات.
إنشاء صنف فرعي واستخدامه في هذه الحالات.

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

يحتوي الصنف الرئيسي على توابع وحقول لتطبيق حالة نادرة معينة لاستخدام الصنف. وفي حين أن الحالة نادرة الحدوث، يكون الصنف مسؤولًا عنها وسيكون من الخطأ نقل جميع الحقول والتوابع المرتبطة بها إلى صنفٍ منفصلٍ تمامًا. لكن يمكن نقلهم إلى صنف فرعي، وهو ما سنفعله بمساعدة تقنية إعادة التصميم هذه.

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

  • إنشاء صنف فرعي بسرعة وسهولة.
  • إمكانية إنشاء عدة أصناف فرعية منفصلة إذا كان الصنف الرئيسي ينجز حاليًا أكثر من مثل هذه الحالة الخاصة.

مساوئ تطبيق الحل

  • على الرغم من ما يبدو عليه من بساطة، يمكن أن يؤدي التوريث إلى طريق مسدود إذا كان عليك فصل عدة تسلسلات هرمية مختلفة للصنف. إذا وُجِد على سبيل المثال الصنف Dogs وله سلوكًا مختلفًا اعتمادًا على حجم وفراء الكلاب، يمكن استنباط اثنين من التسلسلات الهرمية:
    • بحسب الحجم: Large و Medium و Small
    • بحسب الفراء: Smooth و Shaggy

كل شيء سيكون على ما يرام، إلا أن المشاكل سوف تتفاقم حالما تحتاج إلى إنشاء صنف كلب يكون Large و Smooth على حد سواء، إذ يمكنك إنشاء كائن من صنفٍ واحدٍ فقط. ومع ذلك، يمكنك تجنب هذه المشكلة باستخدام التركيب بدلًا من الميراث (انظر نمط الاستراتيجية). وبعبارة أخرى، سيكون للصنف Dog حقلين مكونين، الحجم والفراء. ستقوم بتركيب العناصر المكونة من الأصناف اللازمة إلى هذه الحقول. حتى تتمكن من إنشاء كلب Dog لديه حجم كبير LargeSize وفراء أشعث ShaggyFur.

آلية الحل

  1. أنشئ صنفًا فرعيًّا جديدًا من الصنف المعني.
  2. إذا كنت بحاجة إلى بيانات إضافية لإنشاء كائنات من صنفٍ فرعي، أنشئ بانيًّا وأضف المعاملات اللازمة إليه. لا تنسَ استدعاء تطبيق أصل الباني.
  3. ابحث عن كل استدعاءات باني الصنف الأصل. عندما تكون وظيفة الصنف الفرعي ضرورية، يستعاض عن الباني الأصل بالباني الفرعي.
  4. انقل التوابع والحقول الضرورية من الصنف الأصل إلى الصنف الفرعي. قم بهذا من خلال دفع التابع لأسفل ودفع الحقل لأسفل. من الأسهل البدء بنقل التوابع أولًا. وبهذه الطريقة، تظل الحقول متاحة طوال العملية بأكملها: من الصنف الأصل قبيل الانتقال، ومن الصنف الفرعي نفسه بعد اكتمال النقل.
  5. بعد أن يكون الصنف الفرعي جاهزًا، ابحث عن كل الحقول القديمة التي تحكمت في اختيار الوظيفة. احذف هذه الحقول باستخدام التعدديّة الشكليّة لتحل محل جميع العوامل التي استخدمت فيها الحقول. مثال بسيط: في صنف السيارات، يوجد الحقل isElectricCar، واعتمادًا عليه، في التابع ()refuel، تكون السيارة إما مزودة بالمحروقات أو مشحونة بالكهرباء. بعد إعادة التصميم، يحذف الحقل isElectricCar وسيكون للصنفين Car و ElectricCar التطبيقات الخاصة بهما في تابع ()refuel.

انظر أيضًا

مصادر