دمج التوابع (Inline Methods)

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

المشكلة

أن يكون محتوى التابع (method body) بسيطًا وواضحًا أكثر من التابع بحدِّ ذاته، ويمكن عندئذٍ الاستغناء عنه.

الحل

نقل الشيفرة الموجودة في التابع (محتوى التابع) إلى مواقع استدعائه، وحذف التابع برمته إذ لا داعي له.

مثال

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

نلاحظ أن محتوى التابع moreThanFiveLateDeliveries()‎ واضحٌ وبسيطٌ لدرجةٍ تجعل الاستغناء عنه ممكنًا:

في لغة Java:

class PizzaDelivery {
  //...
  int getRating() {
    return moreThanFiveLateDeliveries() ? 2 : 1;
  }
  boolean moreThanFiveLateDeliveries() {
    return numberOfLateDeliveries > 5;
  }
}

في لغة #C:

class PizzaDelivery 
{
  // ...
  int GetRating() 
  {
    return MoreThanFiveLateDeliveries() ? 2 : 1;
  }
  bool MoreThanFiveLateDeliveries() 
  {
    return numberOfLateDeliveries > 5;
  }
}

في لغة PHP:

function getRating() {
  return ($this->moreThanFiveLateDeliveries()) ? 2 : 1;
}
function moreThanFiveLateDeliveries() {
  return $this->numberOfLateDeliveries > 5;
}

في لغة Python:

class PizzaDelivery:
    # ...
    def getRating(self):
        return 2 if self.moreThanFiveLateDeliveries() else 1
  
    def moreThanFiveLateDeliveries(self):
        return self.numberOfLateDeliveries > 5

في لغة TypeScript:

class PizzaDelivery {
  // ...
  getRating(): number {
    return moreThanFiveLateDeliveries() ? 2 : 1;
  }
  moreThanFiveLateDeliveries(): boolean {
    return numberOfLateDeliveries > 5;
  }
}

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

سيُستبدَل استدعاءُ التابع ليحلَّ محتوى التابع محلَّه بالشكل:

في لغة Java:

class PizzaDelivery {
  //...
  int getRating() {
    return numberOfLateDeliveries > 5 ? 2 : 1;
  }
}

في لغة #C:

class PizzaDelivery 
{
  // ...
  int GetRating() 
  {
    return numberOfLateDeliveries > 5 ? 2 : 1;
  }
}

في لغة PHP:

function getRating() {
  return ($this->numberOfLateDeliveries > 5) ? 2 : 1;
}

في لغة Python:

class PizzaDelivery:
  # ...
  def getRating(self):
    return 2 if self.numberOfLateDeliveries > 5 else 1

في لغة TypeScript:

class PizzaDelivery {
  // ...
  getRating(): number {
    return numberOfLateDeliveries > 5 ? 2 : 1;
  }
}

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

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

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

جعل الشيفرة أكثر وضوحًا بتقليل عدد التوابع غير المفيدة فيها.

آلية الحل

  1. التأكُّد من أنّ التابع لا يُعاد تعريفه في أيّ من الأصناف الفرعية (subclasses)، فإن كان مُعرَّفًا فعليك العزوف عن دمج التابع.
  2. إيجاد كافّة استدعاءات هذا التابع في الشيفرة وتبديلها إلى محتواه الفعليّ.
  3. حذف التابع.

انظر أيضًا

مصادر