سؤال

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

علي سبيل المثال،

void f(int *p)
{
  assert(p);
  p->do();
}

سؤالي هو هل نحتاج إلى افتراض أنه لا يمكن تلبية الحالة في وضع الإصدار والتعامل مع الحالة وفقًا لذلك؟

void f(int *p)
{
  assert(p);

  if (p)
  {
    p->do();
  }
}

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

هل كانت مفيدة؟

المحلول

إذا فشل التأكيد ، يجب أن يعطل البرنامج.

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

إذا كنت في المخيم الذي يقول ، "أوه ، ولكن ماذا لو فشلت التأكيدات في الإنتاج؟ أحتاج إلى القبض عليهم!" ثم تفتقد هذه النقطة. اسأل نفسك ، في مثل هذه الحالة ، لماذا لا ترمي استثناء فقط (أو التعامل مع الخطأ)؟

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

نصائح أخرى

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

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

إحدى النقاط المهمة على الرغم من ذلك - غالبًا ما تستخدم التأكيدات للكشف عن المشكلات الرئيسية مع سلامة بياناتك. إذا واصلت تلك المؤكدة ، فقد تخاطر بالبيانات. في هذه الحالات ، قد يكون من الأفضل التعطل بدلاً من تدمير بياناتك. (من الواضح أن أي نوع من معالج التحطم الذي يظهر على الأقل واجهة مستخدم معقولة مع وصف خطأ سيكون من الأفضل).

بالمعنى الدقيق للكلمة ، فإن الكود الثاني لديه التكرار.

void f(int *p)
{
  assert(p);
  if (p)    // Beats the purpose of assertion
  {
    p->do();
  }
}

التأكيد يعني حدوث خطأ. شيء غير متوقع/غير ملموس. في الكود أعلاه ، إما

1) أنت تتعامل بشكل صحيح مع القضية التي يكون فيها p فارغًا. (من خلال عدم استدعاء p-> do ())- وهو ما يفترض أنه الشيء الصحيح/المتوقع. ومع ذلك ، فإن التأكيد هو انذار كاذب.

2) من ناحية أخرى ، إذا لم يتصلوا ب)

في الكود أعلاه ، يعمل المبرمج بجد للتعامل مع الحالات الخاطئة على أي حال.

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

التأكيدات هي رمز تصحيح الأخطاء ، وليس رمز التشغيل. لا تستخدمها لالتقاط أخطاء الإدخال.

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

إذا كان هناك أي احتمال أن تنشأ الشرط في عملية الحياة الحقيقية ، فلا تعتمد على التأكيدات - استخدم الاستثناءات أو بعض آلية الخطأ الأخرى.

تأكيدات مفيدة لتصحيح الأخطاء كما ذكرت. يجب ألا يدخلوا أبدًا رمز الإنتاج (كما تم تجميعه ، لا بأس في لفها في #ifdefs بالطبع)

إذا كنت تواجه مشكلة حيث تتجاوز سيطرتك لتصحيحها وتحتاج إلى تسجيل الوصول في رمز الإنتاج الخاص بك ، فسوف أفعل شيئًا مثل:

void f(int *p)
{

  if (!p)
  {
    do_error("FATAL, P is null.");
  }

  p->do();
}

حيث do_error هي وظيفة تسجل خطأ وتخرج بشكل نظيف.

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

لا تبذل الكثير من الجهد في التعامل مع الاستثناءات. ببساطة تأكد من أنه يمكنك الحصول على الاستثناء الكامل ، بما في ذلك stacktrace. وهذا ينطبق على بناء à التحرير على وجه الخصوص.

نظرًا لأن العديد من الأشخاص يعلقون على وضع التأكيدات في وضع الإصدار:

في ما أعمل عليه ، فإن الكفاءة مهمة للغاية (في بعض الأحيان ، يستغرق التنفيذ على مجموعات البيانات الكبيرة عشرات الساعات إلى أيام قليلة لإكمالها). وبالتالي ، لدينا وحدات ماكرو خاصة تؤكد فقط في رمز التصحيح (تشغيل خلال QA وما إلى ذلك). على سبيل المثال ، يعد التأكيد داخل حلقة A for هو بالتأكيد نفقات عامة وقد ترغب في تجنبها في رمز الإصدار. بعد كل شيء ، إذا كان كل IZ جيدًا ، فليس من المفترض أن تفشل.

أحد الأمثلة التي يؤكد فيها رمز الإصدار جيد - إذا لم يكن من المفترض أن يضرب المنطق فرعًا معينًا من التعليمات البرمجية على الإطلاق. في هذه الحالة ، يكون التأكيد (0) جيدًا [وبالتالي يمكن دائمًا ترك أي نوع من التأكيد (0) في رمز الإصدار].

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top