إعادة التصميم (Refactoring)

من موسوعة حسوب

ما الهدف؟

تهدف عملية إعادة التصميم (refactoring) للحصول على شيفرة جيّدة سهلة القراءة يسهل تطويرها والتخلُّص من المتطلَّبات التقنيّة الزائدة فيها، وهذا ما يُعرَف بالشيفرة النظيفة (clean code) لأنّ الشيفرة الرديئة لا بُدَّ وأن تنعكس سلبًا على نجاح المشروع البرمجيّ.

كيف تكون الشيفرة نظيفة؟

  • واضحةً مقروءةً
  • لا تكرار فيها
  • بأقل عددٍ ممكنٍ من الأصناف (classes)
  • تجتاز الاختبارات المختلفة بنجاح
  • سهلة ولا تحتاج الصيانة (maintenance) المتكرِّرة

فخ الأعباء التقنية (Technical Debts)

يقع الكثير من المبرمجين في فخ الأعباء التقنية وهذا مكلفٌ جدًا إن لم يُعالَج بفترة مبكِّرة، ومن أسبابه:

  • ضغط العمل: مما يؤدي لنشر بعض الميّزات (features) قبل الانتهاء منها كلِّيَّا.
  • التغافل عن عواقب الأعباء التقنيّة: لأنّ الأعباء التقنيّة ستحدُّ من سرعة التطوير البرمجيّ.
  • الفشل بمعالجة الترابط الشديد ما بين المكونات البرمجيّة: وذلك عندما يبدو المشروع كتلةً واحدةً بدلًا من وحداتٍ مستقلةٍ.
  • إهمال إجراء الاختبارات: وتكون النتائج حينئذٍ كارثيّة!
  • صياغة توثيقيّة هزيلة: تكون سببًا للكثير من المشاكل لدى المبرمجين الجُدد.
  • غياب التواصل الفعّال بين أعضاء الفريق: كأن يتابع المبرمجون والمطورون العمل وفقًا لمعلوماتٍ وعملياتٍ قديمةٍ من المشروع.
  • التطوير بعيد الأمد لعدّة فروع بوقتٍ واحدٍ: وخاصّة عندما يكون هنالك تغييرات إفراديّة.
  • تسويف عملية إعادة التصميم (refactoring): وهذا يعني زيادة عدد الشيفرات التي سيُعاد العمل عليها مستقبلًا.
  • لا رقابة للالتزام بالنمط المُوحَّد: عندما يكتب كلُّ شخصٍ شيفرةً بحسب نظرته وطريقته الخاصّة.
  • الإلمام غير الكافي: عندما لا يعرف المُطوِّر كيفيّة كتابة شيفرة فعّالةً ومناسبة.

متى نحتاج إعادة التصميم؟

  1. عند إضافة ميّزةٍ (feature) جديدة: إذ سيصبح التحكُّم بالشيفرة النظيفة (clean code) أكثر سهولةً، وبالتالي فإنّ إجراء التغييرات سيكون أسهل بكثيرٍ مما كان عليه قبل إعادة التصميم.
  2. عند إصلاح الأخطاء (bugs): إذ ستتَّضح الأخطاء بجهدٍ ووقتٍ أقل، وستغني إعادة التصميم المبكِّرة عن الحاجةَ لإعادة التصميم المُخصَّص لاحقًا.
  3. أثناء مراجعة الشيفرة (code review): إذ هي الفرصةُ الأخيرة لتوضيب الشيفرة قبل نشرها للعامّة.

مثال

تفيد عملية إعادة التصميم في تبسيط التعليمات الشرطيّة المعقَّدة وذلك عبر عزل عملياتها في توابع مستقلَّة كما في المثال الآتي.

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

if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
    charge = quantity * winterRate + winterServiceCharge;
}
else {
    charge = quantity * summerRate;
}

الشيفرة بعد التصميم

if (notSummer(date)) {
    charge = winterCharge(quantity);
}
else {
    charge = summerCharge(quantity);
}

والفرق واضحٌ ما بين الشيفرتين من ناحية التنظيم (organization) وسهولة كشف الأخطاء (bug detects) وقابليّة القراءة (readability) والصيانة (maintenance).

مشاكل الشيفرات (Code Smells)

المبالغة والإطالة

قد يزداد حجم الشيفرة ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ويبدو هذا التضخم واضحًا في:

  1. التوابع  الطويلة (long methods)
  2. الأصناف الواسعة (large classes)
  3. هوس الحقول الأساسيّة (primitives obsession)
  4. المعاملات الكثيرة في التوابع (long parameter list)
  5. البيانات المُجمَّعة (data clumps)

الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه (OOP)

مثل:

  1. استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة
  2. الوراثة الفائضة (refused bequest)
  3. الشكل المعقَّد لتعليمة switch
  4. الحقول المؤقّتة (temporary fields)

عرقلة التغيير

إذ عند إحداث أيّ تغييرٍ في الشيفرة لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، من معوِّقات التغيير:

  1. التغيير المتشعِّب (divergent change)
  2. الهيكليّة التفرعيّة للوراثة (parallel inheritance hierarchies)
  3. تغيير الأصناف المتعدِّدة (shotgun surgery)

الأجزاء الفائضة

وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها:

  1. التعليقات (comments)
  2. تكرار  الشيفرة (duplicates)
  3. أصناف البيانات (data classes)
  4. الشيفرة الميتة (dead code)
  5. الأصناف الخاملة (lazy classes)
  6. الخيال البرمجيّ (speculative generality)

الروابط الازدواجية

كإنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو التفويض المفرط (excessive delegation)، وتتمثل هذه المشكلة بالنقاط الآتية:

  1. التسلط على الكائنات الأخرى (feature envy)
  2. الارتباط الوثيق غير المناسب (inappropriate intimacy)
  3. أصناف المكتبة غير الكافية (incomplete library class)
  4. سلاسل الرسائل (message chains)
  5. الوسيط (middle man)

تقنيات الحلول

مصادر