© دراغون بول. غوكو.يتوقع مبرمج المدافع في أي وقت وفي أي مكان في الكود ظهور مشاكل محتملة ويكتب الكود بطريقة تحمي نفسها من مقدما. وإذا لم تتمكن من الدفاع عن نفسك ضد أي مشكلة ، فعليك على الأقل التأكد من أن عواقبها وتأثيرها على المستخدمين في حدها الأدنى.
أتذكر تأثير
FlashForward من أفلام هوليوود
الشهيرة عندما يرى بطل الرواية الكارثة الوشيكة ويبقى هادئًا للغاية ، لأنه يعلم مقدمًا أن ذلك سيحدث ولديه حماية منه. الفكرة وراء البرمجة الدفاعية هي حماية نفسك من المشكلات التي يصعب التنبؤ بها أو التي يصعب التنبؤ بها. يتوقع مبرمج الأمان حدوث أخطاء في أي مكان في النظام وفي أي وقت محدد لمنعها قبل أن تتسبب في حدوث ضرر. ومع ذلك ، فإن الهدف ليس إنشاء نظام لا يتعطل أبدًا ، بل لا يزال مستحيلًا. الهدف هو إنشاء نظام
يتعطل بأمان في حالة حدوث
أي مشكلة غير متوقعة.
دعونا نفهم بمزيد من التفصيل ما هو مدرج في مفهوم "سقوط بأمان".
- تسقط بسرعة. في حالة حدوث خطأ غير متوقع ، يجب إكمال جميع العمليات على الفور ، خاصةً إذا كانت الحسابات اللاحقة صعبة أو قد تؤدي إلى تلف البيانات.
- تقع بدقة. في حالة حدوث خطأ ، يجب على البرنامج تحرير جميع الموارد ، وإزالة الأقفال ، وحذف الملفات المؤقتة ونصف المسجلة ، وإغلاق الاتصالات. انتظر حتى تكتمل العمليات الحرجة ، التي قد يؤدي انقطاعها إلى نتائج غير متوقعة. أو طريقة آمنة لتحطم هذه العمليات.
- السقوط بشكل واضح وجميل. إذا تم كسر شيء ما ، يجب أن تكون رسالة الخطأ بسيطة وموجزة وتحتوي على تفاصيل مهمة من سياق النظام الذي حدث فيه الخطأ. سيساعد ذلك الفريق المسؤول عن النظام في اكتشاف المشكلة في أسرع وقت ممكن وحلها.
ولكن قد يكون لديك سؤال.
لماذا نضيع الوقت في المشاكل التي قد تنشأ في المستقبل؟
الآن ليسوا هناك ، رمز يعمل الكمال فقط. بالإضافة إلى ذلك ، قد لا تحدث المشكلات على الإطلاق. بعد كل شيء ، لا يقوم المحترفون بالهندسة من أجل الهندسة (
YAGNI - لست بحاجة إليها)!
الشيء الرئيسي هو البراغماتية
يعطي أندرو هانت في كتاب "مبرمج براغماتي" التعريف التالي للبرمجة الدفاعية - "
جنون العظمة البراغماتي ".
حماية الرمز الخاص بك من:
- الاخطاء الخاصة
- أخطاء الآخرين ؛
- الأخطاء والفشل في الأنظمة الأخرى التي تم دمجها بها ؛
- أخطاء الحديد والبيئات والمنصات التي يعمل عليها التطبيق الخاص بك.
دعونا نناقش العديد من الأساليب التكتيكية والاستراتيجية للبرمجة الدفاعية ، والتي من شأنها أن تخلق نظامًا موثوقًا ويمكن التنبؤ به مقاومًا للفشل التعسفي.
قد تبدو بعض النصائح "كابتن" ، ولكن في الممارسة العملية ، لا يتبعها كثير من المطورين. ولكن إذا كنت تلتزم بممارسات وأساليب بسيطة ، فسيؤدي ذلك إلى زيادة كبيرة في استقرار نظامك.
لا تثق بأحد
بيانات المستخدم غير موثوق بها بشكل افتراضي. غالبًا ما يسيء المستخدمون فهم ما يبدو واضحًا لنا (كمطورين للنظام). نتوقع إدخال غير صحيح ودائما التحقق من ذلك.
تحقق أيضًا من مقدار المدخلات. قد يكون أن المستخدم يرسل الكثير منهم. في نفس الوقت ، من وجهة نظر منطق الأعمال ، هذا هو السيناريو الصحيح. ولكن يمكن أن يؤدي إلى معالجة طويلة للغاية. ما الذي يمكن القيام به مع هذا؟ على سبيل المثال ، قم بتشغيلها بشكل غير متزامن ، إذا تجاوز مقدار بيانات الإدخال عتبة معينة وسمحت لك تفاصيل العمل بمعالجة البيانات في الخلفية.
تخضع إعدادات التطبيق (على سبيل المثال ، ملفات التكوين) أيضًا إلى ظهور بيانات غير صحيحة فيها. في كثير من الأحيان ، يتم تخزين إعدادات البرنامج في JSON ، YAML ، XML ، INI وغيرها من الأشكال. نظرًا لأن كل هذه ملفات نصية ، يجب أن يتوقع المرء أن يقوم شخص ما عاجلاً أو آجلاً بتغيير شيء ما فيها ، وسيبدأ البرنامج في العمل بشكل غير صحيح. يمكن أن يكون إما مستخدمًا نهائيًا أو شخصًا من فريقك.
قواعد البيانات والملفات والمستودعات المركزية للتكوينات والسجل - يمكن الوصول إلى جميع هذه الأماكن من قبل أشخاص آخرين ، وعاجلاً أم آجلاً سيغيرون شيئًا ما هناك (
قانون مورفي ).
مدخل القمامة → مدخل القمامة
يجب أن تكون المدخلات التي تجتاز عملية التحقق من الصحة وتبدأ معالجتها نظيفة إذا كنت تريد أن يفعل الكود الخاص بك بالضبط ما تتوقعه منه.
ومع ذلك ، من الممارسات الجيدة إجراء عمليات تدقيق إضافية للتحقق من صحة البيانات ، بما في ذلك عندما بدأت بالفعل معالجتها. في الأماكن الحرجة (الفوترة ، الترخيص ، البيانات الشخصية والسرية ، وما إلى ذلك) يعد هذا مطلبًا إلزاميًا تقريبًا. يعد ذلك ضروريًا حتى في حالة وجود أخطاء في التعليمات البرمجية أو مشاكل في أداة التحقق من صحة بيانات الإدخال ، قم بإيقاف تدفق التنفيذ في أسرع وقت ممكن. من الصعب إجراء تحقق عالي الجودة من خلال التحقق من جميع سيناريوهات الأخطاء المحتملة ، بحيث يمكنك استخدام طرق أبسط للتحقق من أن البرنامج لا يزال يعمل بشكل صحيح - التأكيدات والاستثناءات.
بجنون العظمة صحية هي سمة مميزة لجميع المطورين المحترفين. ولكن من المهم للغاية السعي لتحقيق التوازن الأمثل وفهم متى يكون الحل جيدًا بالفعل بما فيه الكفاية.
التكوينات منفصلة حول البيئات
سبب شائع للمشكلات هو عدم كفاية فصل التكوينات بين البيئات أو عدم وجود مثل هذا الفصل.
هذا يمكن أن يؤدي إلى العديد من المشاكل ، على سبيل المثال:
- تبدأ بيئة الاختبار في قراءة و / أو كتابة البيانات من الإنتاج وقواعد البيانات وقوائم الانتظار والموارد الأخرى ؛
- تستخدم بيئة الاختبار عمليات الدمج والخدمات الخارجية مع حساب الإنتاج ؛
- خلط الإحصاءات والمقاييس والأخطاء من بيئات مختلفة ؛
- خرق أمني (يمكن للمطورين والمختبرين وأعضاء الفريق الآخرين الوصول إلى موارد الإنتاج) ؛
- الأخطاء التي يصعب استكشافها على الإنتاج (على سبيل المثال ، يتم فقد جزء من الرسائل في قائمة الانتظار بسبب بدء بيئة الاختبار في قراءتها).
هذه مجرد أمثلة ، قائمة كاملة بالمشكلات التي قد تنجم عن عدم كفاية الفصل بين التكوينات تكاد تكون لا نهاية لها وتعتمد على تفاصيل المشروع.
يمكن أن يؤدي الفصل المسؤول بين بيانات التكوين حسب البيئة إلى تقليل احتمالية حدوث مجموعة كاملة من المشكلات المرتبطة بـ:
- الأمن؛
- الموثوقية.
- الدعم والنشر (سوف المهندسين DevOps شكرا لك).
بالإضافة إلى ذلك ، من الممارسات الجيدة تخزين البيانات السرية (المفاتيح والرموز وكلمات المرور) في مكان منفصل مصمم خصيصًا لتخزين ومعالجة الأسرار. تقوم هذه الأنظمة بتشفير البيانات بشكل آمن ولديها وسائل مرنة لإدارة حقوق الوصول وتسمح لك أيضًا بتغيير المفاتيح بسرعة إذا تم اختراقها. في هذه الحالة ، لن تحتاج إلى إجراء تغييرات على الكود وإعادة نشر التطبيق. هذا مهم بشكل خاص للأنظمة التي تعمل في المعاملات المالية أو البيانات السرية أو الشخصية.
تذكر تأثير المتتالية
أحد الأسباب الشائعة لسقوط الأنظمة الكبيرة والمعقدة هو التأثير المتتالي. يحدث انهيار أو تدهور وظيفة أحد أجزاء النظام ، واحداً تلو الآخر تبدأ الأنظمة الفرعية الأخرى المرتبطة به في الفشل. تتالي حتى يصبح النظام بأكمله غير قابل للوصول بشكل كامل.
بعض الحيل الواقية:
- استخدام المهلات التدريجي (الأسي) مع عنصر عشوائي ؛
- تعيين قيم معقولة لمهلة الاتصال ومهلة المقبس ؛
- تتوقع حدوث تراجع مسبق في حالة فشل الخدمات الفردية. من الأفضل تدهور بعض الوظائف مؤقتًا ، وتعطيل الخدمات تمامًا ، ولكن لا تخاطر بكسر النظام بأكمله. لكن تخيل أنه في هذه الحالة ، يرى المستخدم رسالة مفهومة وليست مخيفة ، وسيكتشف فريق الدعم والتطوير في أقرب وقت ممكن المشكلة.
الإبلاغ عن المشاكل بسرعة
جميع الأنظمة تفشل. في بعض الأحيان يحدث شيء غريب فيهم يتوقعه المبدعون "مرة كل 10 سنوات". تكامل واجهات برمجة التطبيقات الخارجية تصبح دورية غير متوفرة أو الاستجابة بشكل غير صحيح. غالبًا ما يكون التراجع عن كل هذه الحالات أمرًا صعبًا أو طويلًا أو ببساطة مستحيل. توقع هذه الحالة مقدمًا وأبلغ عنها في أسرع وقت ممكن. تسجيل الدخول إلى مستوى خطأ أو إلى نظام المراقبة - أمرا مفروغا منه. إضافة التحقق من صحة إضافية إلى healthcheck هو أفضل. لإرسال رسالة من الكود إلى Slack أو Telegram أو PagerDuty أو أي خدمة أخرى تخطر فريقك على الفور بالمشكلة ، فهي مثالية.
ولكن من المهم أن نفهم بوضوح عندما يكون من المنطقي إرسال الرسائل مباشرة. فقط إذا ارتبط أي خطأ أو موقف مشبوه أو غير نمطي بعمليات الأعمال ومن المهم أن يتلقى شخص أو مجموعة محددة من الأشخاص في الفريق إشعارًا في أسرع وقت ممكن ويستطيع الرد.
يجب معالجة جميع المشكلات والانحرافات الفنية الأخرى بالوسائل القياسية - المراقبة والإنذار والتسجيل.
ذاكرة التخزين المؤقت المستخدمة بشكل متكرر و / أو البيانات الحديثة
تشترك البرامج والأشخاص في شيء واحد - حيث يميلون إلى إعادة استخدام البيانات التي يتم استخدامها غالبًا أو التي تمت مصادفتها مؤخرًا. في الأنظمة المحملة بدرجة عالية ، يجب أن تتذكر دائمًا هذه البيانات وذاكرة التخزين المؤقت في أهم الأماكن في النظام.
تعتمد استراتيجية التخزين المؤقت اعتمادًا كبيرًا على تفاصيل المشروع والبيانات. إذا كانت البيانات قابلة للتغيير ، فهناك حاجة إلى إبطال ذاكرة التخزين المؤقت. لذلك ، فكر مقدماً في كيفية القيام بذلك. وفكر أيضًا في المخاطر التي قد تحدث في حالة ظهور بيانات قديمة في ذاكرة التخزين المؤقت أو نفاد ذاكرة التخزين المؤقت أو ما إلى ذلك.
استبدال العمليات باهظة الثمن مع تلك الرخيصة
يعد العمل باستخدام السلاسل أحد أكثر العمليات شيوعًا في أي برنامج. وإذا لم يتم هذا على النحو الأمثل ، يمكن أن يكون عملية مكلفة. في لغات البرمجة المختلفة ، قد تختلف تفاصيل التعامل مع الأوتار ، لكن يجب أن تتذكرها دائمًا.
في التطبيقات الكبيرة ذات قاعدة الشفرة الكبيرة ، غالبًا ما يتم العثور على الشفرة المكتوبة منذ عدة أعوام والتي تعمل بدون أخطاء ، ولكنها ليست الأمثل من حيث الأداء. غالبًا ما يوفر تغيير عادي في بنية البيانات من صفيف / قائمة إلى جدول تجزئة دفعة قوية (حتى لو كان ذلك في مكان محلي فقط في الرمز).
في بعض الأحيان يمكنك تحسين الأداء عن طريق إعادة كتابة الخوارزمية لاستخدام عمليات bitwise. لكن حتى في هذه الحالات النادرة عندما يكون لها ما يبررها ، فإن الشفرة معقدة للغاية. لذلك ، عند اتخاذ قرار ، خذ بعين الاعتبار قابلية قراءة الكود وحقيقة أنه يجب دعمه. ينطبق الشيء نفسه على التحسينات الصعبة الأخرى: دائمًا ، يصبح من الصعب قراءة هذه الشفرة ويصعب الحفاظ عليها. إذا كنت لا تزال تقرر تحسينات صعبة ، فلا تنس أن تكتب تعليقات تصف
ما تريد أن تفعله هذه الشفرة
ولماذا يتم كتابتها بهذه الطريقة.
في الوقت نفسه ، يجب التعامل مع التحسين بواقعية صحية:
- إذا تطلب الأمر ، كمطور ، لبضع ثوان أو دقائق - فمن المنطقي القيام بذلك على الفور ؛
- إذا كان أكثر من ذلك ، فمن المعقول أن تفعل ذلك على الفور فقط عندما تكون متأكداً 100 ٪ من ضرورة ذلك. في جميع الحالات الأخرى ، يكون من المنطقي تأجيله ، والكتابة في كود TODO ، وجمع المزيد من المعلومات ، والتشاور مع الزملاء ، إلخ.
التحسين السابق لأوانه هو أصل كل الشرور (دونالد نوث)
أعد كتابة بلغة أقل مستوى
هذا تدبير متطرف. اللغات منخفضة المستوى دائمًا ما تكون أسرع مقارنة باللغات ذات المستوى الأعلى. لكن هذا الحل له ثمن - تطوير مثل هذا البرنامج أطول وأكثر صعوبة. في بعض الأحيان ، عند إعادة كتابة الأجزاء المهمة من النظام بلغة منخفضة المستوى ، يمكنك تحقيق زيادة كبيرة في الإنتاجية. ولكن هناك آثار جانبية - عادة ما تفقد مثل هذه الحلول في الأنظمة الأساسية ويكون دعمها أكثر تكلفة. لذلك ، اتخاذ قرار بعناية.
وحده في هذا المجال ليس محارب
في الختام ، أود أن أشير إلى شيء واحد أكثر أهمية ، وربما الأكثر أهمية. لن تعمل التدابير التي درسناها في الفقرات السابقة إلا إذا التزم جميع أعضاء الفريق بها وكان لدى كل شخص فهم من المسؤول عن ماذا وما يجب القيام به في حالة حدوث موقف حرج. من المهم ، بعد إصلاح المشكلة ، عقد اجتماع (بعد الوفاة) مع جميع المهتمين ومعرفة سبب ظهور هذه المشكلة وما الذي يمكن القيام به لمنع حدوث هذه المشكلة في المستقبل. في كثير من الحالات ، تكون كل من التغييرات التقنية والتغييرات مطلوبة. مع كل Post Mortem الجديد ، سيصبح نظامك أكثر موثوقية ، وسيكون الفريق أكثر خبرة وتماسكًا ، وستكون الإنتروبيا في الكون أقل قليلاً ؛)
يستخدم المقال جزئيًا مواد من " لماذا الدفاعية البرمجة" هي أفضل طريقة لترميز قوي (رافي شانكار راجان).