تبديل الشرطيات المتداخلة بعبارات الحماية (Replace Nested Conditional with Guard Clauses

من موسوعة حسوب
< Refactoring
مراجعة 13:24، 18 ديسمبر 2018 بواسطة Khaled-yassin (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: تبديل الشرطيات المتداخلة بعبارات الحماية (Replace Nested Conditional with Guard Clauses}}</noinclude> ==...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

المشكلة

وجود مجموعة متداخلة من الشرطيات وصعوبة تحديد التدفق الطبيعي لتنفيذ الشيفرة البرمجية.

الحل

عزل جميع الاختبارات الخاصة والحالات الطرفية في عبارات منفصلة ووضعها قبل الاختبارات الرئيسية. من الناحية المثالية، يجب أن يكون لديك قائمة "مسطحة" من الشرطيات، واحدة تلو الأخرى.

مثال

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

في لغة Java:

public double getPayAmount() {
  double result;
  if (isDead){
    result = deadAmount();
  }
  else {
    if (isSeparated){
      result = separatedAmount();
    }
    else {
      if (isRetired){
        result = retiredAmount();
      }
      else{
        result = normalPayAmount();
      }
    }
  }
  return result;
}

في لغة C#‎:

public double GetPayAmount()
{
  double result;
  
  if (isDead)
  {
    result = DeadAmount();
  }
  else 
  {
    if (isSeparated)
    {
      result = SeparatedAmount();
    }
    else 
    {
      if (isRetired)
      {
        result = RetiredAmount();
      }
      else
      {
        result = NormalPayAmount();
      }
    }
  }
  
  return result;
}

في لغة PHP:

public function getPayAmount() {
  if ($this->isDead)
    $result = $this->deadAmount();
  else {
    if ($this->isSeparated)
      $result = $this->separatedAmount();
    else {
      if ($this->isRetired)
        $result = $this->retiredAmount();
      else
        $result = $this->normalPayAmount();
    }
  }
  return $result;
}

في لغة Python:

def getPayAmount(self):
    if self.isDead:
        result = deadAmount()
    else:
        if self.isSeparated:
            result = separatedAmount()
        else:
            if self.isRetired:
                result = retiredAmount()
            else:
                result = normalPayAmount()
    return result

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

في لغة Java:

public double getPayAmount() {
  if (isDead){
    return deadAmount();
  }
  if (isSeparated){
    return separatedAmount();
  }
  if (isRetired){
    return retiredAmount();
  }
  return normalPayAmount();
}

في لغة C#‎:

public double GetPayAmount() 
{
  if (isDead)
  {
    return DeadAmount();
  }
  if (isSeparated)
  {
    return SeparatedAmount();
  }
  if (isRetired)
  {
    return RetiredAmount();
  }
  return NormalPayAmount();
}

في لغة PHP:

public function getPayAmount() {
  if ($this->isDead)
    return $this->deadAmount();
  if ($this->isSeparated)
    return $this->separatedAmount();
  if ($this->isRetired)
    return $this->retiredAmount();
  return $this->normalPayAmount();
}

في لغة Python:

def getPayAmount(self):
    if self.isDead:
        return deadAmount()
    if self.isSeparated:
        return separatedAmount()
    if self.isRetired:
        return retiredAmount()
    return normalPayAmount()

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

من السهل إلى حد ما اكتشاف "الشرطية المُّعقدة". وتشكل المسافات البادئة في كل مستوى من التداخلية سهم يشير إلى اليمين في اتجاه الألم والشقاء:

if () {
    if () {
        do {
            if () {
                if () {
                    if () {
                        ...
                    }
                }
                ...
            }
            ...
        }
        while ();
        ...
    }
    else {
        ...
    }
}

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

لتبسيط الموقف، تُعزل الحالات الخاصة إلى شروط منفصلة تُنهي التنفيذ مباشرة ثم تُعيد قيمة فارغة إذا كانت عبارات الحماية صحيحة. في الواقع، مهمتك هنا هي جعل الهيكل مسطحُا.

آلية الحل

محاولة تخليص الشيفرة البرمجية من الآثار الجانبية - قد يكون فصل الاستعلام عن المُعدِّل مفيدًا لهذا الغرض. سيكون هذا الحل ضروريًا لإجراء إعادة التشكيل المبينة أدناه.

  1. اعزل جميع عبارات الحماية التي تؤدي إلى استدعاء استثناء أو إلى الإعادة الفورية لقيمة من التابع. وضع هذه الشروط في بداية التابع.
  2. بعد اكتمال إعادة الترتيب وإكمال كافة الاختبارات بنجاح، راجع ما إذا كان يمكنك استخدام توحيد التعبير الشرطي لعبارات الحماية التي تؤدي إلى نفس الاستثناءات أو القيم المُعادة.

انظر أيضًا

مصادر