استخراج الصنف (Extract Class)

من موسوعة حسوب
مراجعة 09:09، 2 مارس 2019 بواسطة جميل-بيلوني (نقاش | مساهمات) (مراجعة وتدقيق.)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

المشكلة

وجود صنفٍ (class) واحدٍ يقوم بمهامٍ عديدةٍ يمكن توزيعها على صنفين.

الحل

إنشاء صنفٍ جديدٍ ونقل بعض الحقول (fields) والتوابع (methods) إليه، والتي تتعلَّق بالمهام الوظيفيّة (functionality) لهذا الصنف الجديد.

مثال

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

يحتوي الصنف Person على عددٍ من الحقول كاسم الشخص (name) ورمز منطقة المكتب (officeAreaCode) ورقمه (officeNumber)، وتابعًا للحصول على هذا الرقم باسم getTelephoneNumber، كما في مخطط الأصناف الآتي:

الصنف Person يحتوي على عددٍ من الحقول كاسم الشخص (name) ورمز منطقة المكتب (officeAreaCode) ورقمه (officeNumber)، وتابعًا للحصول على هذا الرقم باسم getTelephoneNumber.
الصنف Person يحتوي على عددٍ من الحقول كاسم الشخص (name) ورمز منطقة المكتب (officeAreaCode) ورقمه (officeNumber)، وتابعًا للحصول على هذا الرقم باسم getTelephoneNumber.

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

أصبح هنالك صنفٌ مخصَّصٌ للرقم الهاتفي (TelephoneNumber) يشمل كلَّ الحقول والتوابع المتعلقة به، وبقي الصنف الأصليّ Person محتويًا على ما تبقى من الحقول والتوابع، أي يصبح الصنفان بالشكل:

الصنف Person يحتوي على حقلٍ واحدٍ باسم name وتابعٍٍ للحصول على رقم الهاتف getTelephoneNumber، أمّا الصنف TelephoneNumber فهو يحتوي على حقلين باسم officeAreaCode و officeNumber بالإضافة إلى التابع السابق getTelephoneNumber.
الصنف Person يحتوي على حقلٍ واحدٍ باسم name وتابعٍٍ للحصول على رقم الهاتف getTelephoneNumber، أمّا الصنف TelephoneNumber فهو يحتوي على حقلين باسم officeAreaCode و officeNumber بالإضافة إلى التابع السابق getTelephoneNumber.

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

تبدأ الأصناف بسيطةً وواضحةً وتقوم بمهامها الخاصّة كلٌّ على حِدة، ولكن سرعان ما يتوسَّع البرنامج ليُضاف حقلٌ (field) هنا وتابعٌ (method) هناك، ليصبح على عاتق الصنف الواحد -في النهاية- عددٌ كبيرٌ من المهام التي يمكن توزيعها على صنفين على الأقل.

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

  • تساعد آلية إعادة التصميم هذه على الالتزام بمبدأ المسؤولية الواحدة (Single Responsibility Principle) مما يجعل الشيفرة أكثرَ وضوحًا وبساطةً.
  • تكون الأصناف ذات المهمة الواحدة (لكلِّ صنفٍ) أكثر وثوقيّة (reliable) وقابليّةً لإحداث التغييرات؛ فليكن مثلًا أحد الأصناف مسؤولًا عن عشر مهامٍ مختلفةٍ، سيشكِّل عندئذٍ إحداثُ تغييرٍ على هذا الصنف (بهدف تحسين مهمةٍ واحدةٍ) خطرًا على تسع مهامٍ أخرى بالطرف المقابل لذلك التحسين.

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

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

آلية الحل

قبل البدء بالحل، يجب التفكير أولًا بكيفية تقسيم مهام هذا الصنف، ثم اتباع الخطوات الآتية:

  1. إنشاء صنفٍ جديد لاحتواء المهمة التي يُرغب بفصلها عن الصنف الحاليّ.
  2. ربط الصنفين بعلاقةٍ أحاديّة الاتجاه (unidirectional) وذلك لإتاحة استخدام الصنف الجديد دون مشاكل تُذكَر، أمّا إن كان من الضروري الربط ما بين الصنفين بعلاقة ثنائيّة الاتجاه (bidirectional) فلا مشكلة في ذلك مؤقتًا.
  3. الاستفادة من تقنيتي نقل الحقول (Move Fields) ونقل التوابع (Move Methods) لنقل الحقول والتوابع المرتبطة بمهمة الصنف الجديد إليه، ومن الأفضل -بالنسبة للتوابع- البدءُ بنقل التوابع الخاصّة (private) للتقليل من احتمال حدوث الأخطاء، ويكون النقل عبر خطواتٍ صغيرةٍ مع ضرورة اختبار النتائج بعد كلِّ عملية نقلٍ لتجنُّب الوقوع بوابلٍ من الأخطاء المتشابكة وتعذُّر حلها في النهاية! وبعد الانتهاء من النقل بأكمله، عليك بإلقاء نظرةٍ شاملةٍ على الأصناف الناتجة، فمن الممكن أن تُعيد تسمية الصنف الأصليّ لتصبح أكثر وضوحًا، وتتأكَّد من إمكانيّة التخلص من علاقة الربط ثنائيّة الاتجاه ما بين الصنفين في حال وجودها.
  4. ضمان الوصول إلى الصنف الجديد من خارجه، إذ من الممكن إخفاء الصنف كليًا عن العميل بجعله خاصًّا (private) وإدارته عبر الحقول المتبقية في الصنف السابق (الصنف الأصلي)، أو من الممكن جعله عامًّا (public) وإعطاء العميل إمكانيّة تغيير القيم مباشرةً. يعتمد قرار تحديد الوصول إليه (عامًا أو خاصًّا) على مستوى الأمان المطلوب للصنف الأصليّ عند حدوث بعض التغييرات غير المتوقَّعة في قيم الصنف الجديد.

انظر أيضًا

مصادر