إلى أي مدى يجب أن يكون الكود الخاص بي "دفاعيًا"؟

StackOverflow https://stackoverflow.com/questions/869599

  •  22-08-2019
  •  | 
  •  

سؤال

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

كيف تعرف مكان رسم الخط؟

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

المحلول

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

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

نصائح أخرى

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

وأنا أميل إلى تغيير كمية من الدفاع وضعت في قانون بلدي على أساس اللغة. اليوم أنا أعمل في المقام الأول في C ++ حتى أفكاري والانجراف في هذا الاتجاه.

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

أنا لست من محبي مصطلح "البرمجة الدفاعية".بالنسبة لي يقترح رمزًا مثل هذا:

void MakePayment( Account * a, const Payment * p ) {
    if ( a == 0 || p == 0 ) {
       return;
    }
    // payment logic here
}

هذا خطأ، خطأ، خطأ، لكن لا بد أنني رأيته مئات المرات.لا ينبغي أبدًا استدعاء الوظيفة بمؤشرات فارغة في المقام الأول، ومن الخطأ تمامًا قبولها بهدوء.

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

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

والآن لنبدأ بالتصويت السلبي..

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

والآن أنا أفضل للتحقق من صحة من قبل وحدة الاختبار. التحقق من صحة يحدث بالتأكيد للبيانات القادمة من مصادر خارجية، ولكن ليس للمكالمات من المطورين غير خارجي.

وأنا دائما Debug.Assert الافتراضات بلدي.

وبلدي أيديولوجية الشخصية: يجب أن يكون الدفاعي برنامج يتناسب مع سذاجة الأقصى / الجهل من قاعدة المستخدمين المحتملين

إن اتخاذ موقف دفاعي ضد المطورين الذين يستهلكون كود API الخاص بك لا يختلف كثيرًا عن اتخاذ موقف دفاعي ضد المستخدمين العاديين.

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

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

البرمجة الدفاعية ليست سوى طريقة واحدة لإبرام العقد في التصميم حسب العقد طريقة الترميز.

الاثنان الآخران هما

  • البرمجة الإجمالية و
  • البرمجة الاسمية

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

//precondition : par is so and so and so 
function doSth(par) 
{
debug.assert(par is so and so and so )
//dostuf with par 
return result
}

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

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

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

وبمجرد الانتهاء من هذه العقلية، والمفتاح هو أن تكون متسقة في نهجكم. هل تتوقع تسليم ظهر رموز الحالة إلى comminicate مشاكل في سلسلة مكالمة أو تحب الاستثناءات. سوف نماذج مختلطة قتلك أو على الأقل تدفع لك للشرب. بشكل كبير. إذا كنت تستخدم أحد المعهد إلسس]، ثم عزل هذه الأمور في آليات هذا الفخ / تقرير من حيث استخدام. استخدام هذه الواجهات التفاف.

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

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

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

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

ومع ذلك، هناك نقاط معينة لا يمكن أن تكون فيها مصابًا بجنون العظمة.ينبغي الدفاع بدقة شديدة عن احتمال حدوث تجاوزات في المخزن المؤقت وفساد البيانات والمشكلات المماثلة.

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

وسؤال جيد، لقد الوجه متخبط بين القيام الشيكات التعقل وعدم القيام بها. في 50/50

والوضع، وكنت قد يستغرق حلا وسطا حيث أود فقط "والدليل على رصاصة" أي الروتينية التي هي:

و(أ) طلب من أكثر من مكان في المشروع

و(ب) والمنطق الذي من المرجح أن تتغير

و(ج) لا يمكنك استخدام القيم الافتراضية

و(د) روتين لا يمكن 'فشل' برشاقة

وDarknight

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