الفرق بين المراجعتين لصفحة: «Refactoring/extract subclass»
Khaled-yassin (نقاش | مساهمات) أنشأ الصفحة ب'<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>Dogs</code> وله سلوكًا مختلفًا اعتمادًا على حجم وفراء الكلاب، يمكن استنباط اثنين من التسلسلات الهرمية: | ||
** بحسب الحجم: <code> | ** بحسب الحجم: <code>Large</code> و <code>Medium</code> و <code>Small</code> | ||
** بحسب الفراء: <code> | ** بحسب الفراء: <code>Smooth</code> و <code>Shaggy</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>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
.
آلية الحل
- أنشئ صنفًا فرعيًّا جديدًا من الصنف المعني.
- إذا كنت بحاجة إلى بيانات إضافية لإنشاء كائنات من صنفٍ فرعي، أنشئ بانيًّا وأضف المعاملات اللازمة إليه. لا تنسَ استدعاء تطبيق أصل الباني.
- ابحث عن كل استدعاءات باني الصنف الأصل. عندما تكون وظيفة الصنف الفرعي ضرورية، يستعاض عن الباني الأصل بالباني الفرعي.
- انقل التوابع والحقول الضرورية من الصنف الأصل إلى الصنف الفرعي. قم بهذا من خلال دفع التابع لأسفل ودفع الحقل لأسفل. من الأسهل البدء بنقل التوابع أولًا. وبهذه الطريقة، تظل الحقول متاحة طوال العملية بأكملها: من الصنف الأصل قبيل الانتقال، ومن الصنف الفرعي نفسه بعد اكتمال النقل.
- بعد أن يكون الصنف الفرعي جاهزًا، ابحث عن كل الحقول القديمة التي تحكمت في اختيار الوظيفة. احذف هذه الحقول باستخدام التعدديّة الشكليّة لتحل محل جميع العوامل التي استخدمت فيها الحقول. مثال بسيط: في صنف السيارات، يوجد الحقل
isElectricCar
، واعتمادًا عليه، في التابع()refuel
، تكون السيارة إما مزودة بالمحروقات أو مشحونة بالكهرباء. بعد إعادة التصميم، يحذف الحقلisElectricCar
وسيكون للصنفينCar
وElectricCar
التطبيقات الخاصة بهما في تابع()refuel
.