استبدال شيفرات الأخطاء باستثناءات (Replace Error Code with Exception)

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

المشكلة

يعيد التابع قيمة خاصة تشير إلى خطأ.

الحل

إطلاق استثناء بدلًا من ذلك.

مثال

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

يعيد التابع ()withdraw القيمة 1- التي تمثِّل خطأً إن تحقق شرط محدَّد:

في لغة Java:

int withdraw(int amount) {
  if (amount > _balance) {
    return -1;
  }
  else {
    balance -= amount;
    return 0;
  }
}

في لغة C#‎:

int Withdraw(int amount) 
{
  if (amount > _balance) 
  {
    return -1;
  }
  else 
  {
    balance -= amount;
    return 0;
  }
}

في لغة PHP:

function withdraw($amount) {
  if ($amount > $this->balance) {
    return -1;
  } else {
    $this->balance -= $amount;
    return 0;
  }
}

في لغة Python:

def withdraw(self, amount):
    if amount > self.balance:
        return -1
    else:
        self.balance -= amount
    return 0

في لغة TypeScript:

withdraw(amount: number): number {
  if (amount > _balance) {
    return -1;
  }
  else {
    balance -= amount;
    return 0;
  }
}

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

رمي استثناء يصف الخطأ الحاصل عبر throw (أو raize):

في لغة Java:

void withdraw(int amount) throws BalanceException {
  if (amount > _balance) {
    throw new BalanceException();
  }
  balance -= amount;
}

في لغة C#‎:

///<exception cref="BalanceException">Thrown when amount > _balance</exception>
void Withdraw(int amount)
{
  if (amount > _balance) 
  {
    throw new BalanceException();
  }
  balance -= amount;
}

في لغة PHP:

function withdraw($amount) {
  if ($amount > $this->balance) {
    throw new BalanceException;
  }
  $this->balance -= $amount;
}

في لغة Python:

def withdraw(self, amount):
    if amount > self.balance:
        raize BalanceException()
    self.balance -= amount

في لغة TypeScript:

withdraw(amount: number): void {
  if (amount > _balance) {
    throw new Error();
  }
  balance -= amount;
}

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

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

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

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

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

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

آلية الحل

حاول تنفيذ هذه الخطوات لإعادة تصميم شيفرة خطأ واحد فقط في كل مرة. سيوفر هذا سهولة إبقاء كل المعلومات المهمة في رأسك وتجنب الأخطاء.

  1. ابحث عن كافة الاستدعاءات إلى التابع الذي يعيد شيفرات الخطأ، وبدلًا من التحقق من وجود شيفرة خطأ، غلفها في كُتَل try/catch.
  2. أطلِق استثناءً داخل التابع، بدلًا من إعادة شيفرة الأخطاء.
  3. غير توقيع التابع بحيث يحوي معلومات حول الاستثناء الذي يجري إلقاءه (قسم ‎@throws).

مصادر