تقديم التوكيد (Introduce Assertion)

من موسوعة حسوب
مراجعة 15:03، 19 ديسمبر 2018 بواسطة Khaled-yassin (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: تقديم التوكيد (Introduce Assertion)}}</noinclude> == المشكلة == لكي يعمل جزء من الشيفرة البرمجية...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

المشكلة

لكي يعمل جزء من الشيفرة البرمجية بشكل صحيح، يجب أن تتحقق بعض الشروط أو تكون القيم صحيحة.

الحل

استبدل هذه الافتراضات بنقاط تحقق خاصة بالتوكيد.

مثال

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

في لغة Java:

double getExpenseLimit() {
  // يجب أن يكون إما حدًا للنفقات أو مشروعًا أساسيًا
  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.getMemberExpenseLimit();
}

في لغة C#‎:

double GetExpenseLimit() 
{
  // ايجب أن يكون إما حدًا للنفقات أو مشروعًا أساسيً
  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.GetMemberExpenseLimit();
}

في لغة PHP:

function getExpenseLimit() {
  // يجب أن يكون إما حدًا للنفقات أو مشروعًا أساسيًا
  return ($this->expenseLimit != NULL_EXPENSE) ?
    $this->expenseLimit:
    $this->primaryProject->getMemberExpenseLimit();
}

في لغة Python:

def getExpenseLimit(self):
    # يجب أن يكون إما حدًا للنفقات أو مشروعًا أساسيًا
    return self.expenseLimit if self.expenseLimit != NULL_EXPENSE else \
        self.primaryProject.getMemberExpenseLimit()

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

في لغة Java:

double getExpenseLimit() {
  Assert.isTrue(expenseLimit != NULL_EXPENSE || primaryProject != null);

  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.getMemberExpenseLimit();
}

في لغة C#‎:

double GetExpenseLimit() 
{
  Assert.IsTrue(expenseLimit != NULL_EXPENSE || primaryProject != null);

  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.GetMemberExpenseLimit();
}

في لغة PHP:

function getExpenseLimit() {
  assert($this->expenseLimit != NULL_EXPENSE || isset($this->primaryProject));

  return ($this->expenseLimit != NULL_EXPENSE) ?
    $this->expenseLimit:
    $this->primaryProject->getMemberExpenseLimit();
}

في لغة Python:

def getExpenseLimit(self):
    assert (self.expenseLimit != NULL_EXPENSE) or (self.primaryProject != None)

    return self.expenseLimit if (self.expenseLimit != NULL_EXPENSE) else \
        self.primaryProject.getMemberExpenseLimit();

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

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

وتُصبح هذه الافتراضات واضحة بإضافة التأكيدات المقابلة. وكما هو الشان مع التلميح بالنوع في معاملات التابع، يمكن أن تعمل هذه التوكيدات كتوثيق مباشر لشيفرتك البرمجية.

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

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

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

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

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

آلية الحل

عندما ترى أن الشرط قد اُفتُرِض، أضِف توكيدًا على هذا الشرط من أجل التأكد.

يجب أن لا تغيير إضافة التوكيد من سلوك البرنامج.

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

مصادر