مع تعطل التطبيق (خارج) ، من فضلك!
نشرت: 2020-02-12يحاول المبرمجون تجنب الأعطال في التعليمات البرمجية الخاصة بهم. إذا استخدم شخص ما تطبيقه ، فلا ينبغي أن ينكسر أو يتوقف بشكل غير متوقع. يعد هذا أحد أبسط مقاييس الجودة - إذا تعطل أحد التطبيقات غالبًا ، فربما لا يتم إجراؤه بشكل جيد.
تحدث أعطال التطبيق عندما يكون البرنامج على وشك القيام بشيء غير محدد أو سيئ مثل قسمة قيمة على صفر أو الوصول إلى موارد مقيدة على جهاز. قد يتم ذلك أيضًا بشكل صريح بواسطة المبرمج الذي كتب التطبيق. "لن يحدث هذا أبدًا لذا سأتخطى ذلك" - هذا أمر شائع جدًا وليس تفكيرًا غير منطقي تمامًا. هناك بعض الحالات التي لا يمكن أن تحدث أبدًا حتى… يحدث ذلك.
وعود كاذبة
تعد واجهات برمجة التطبيقات من أكثر الحالات شيوعًا التي نعلم فيها أنه لا يمكن حدوث شيء ما. لقد اتفقنا بين الواجهة الخلفية والواجهة الأمامية - وهذا هو رد الخادم الوحيد الذي يمكنك الحصول عليه لهذا الطلب. قام المشرفون على هذه المكتبة بتوثيق سلوك هذه الوظيفة. لا يمكن للوظيفة أن تفعل أي شيء آخر. كلا الطريقتين في التفكير صحيحان ، لكن كلاهما يمكن أن يسبب مشاكل.
عندما تستخدم مكتبة ، يمكنك الاعتماد على أدوات اللغة لمساعدتك في التعامل مع جميع الحالات الممكنة. إذا كانت اللغة التي تستخدمها تفتقر إلى أي شكل من أشكال التحقق من النوع أو التحليل الثابت ، فيجب عليك الاهتمام بذلك بنفسك. ومع ذلك ، يمكنك التحقق من ذلك قبل الشحن إلى بيئة الإنتاج ، لذا فهي ليست مشكلة كبيرة. قد يكون ذلك صعبًا ، لكنك تقرأ التغييرات قبل تحديث تبعياتك وتكتب اختبارات الوحدة ، أليس كذلك؟ سواء كنت تستخدم مكتبة أو تجعلها أكثر صرامة في الكتابة ، يمكنك توفير أفضل لشفرتك والمبرمجين الآخرين.
الاتصال بالواجهة الخلفية أصعب قليلاً. غالبًا ما يكون مقترنًا بشكل غير محكم ، لذا يمكن إجراء التغيير على جانب واحد بسهولة دون إدراك كيف سيؤثر على الجانب الآخر. غالبًا ما يؤدي التغيير على الواجهة الخلفية إلى كسر افتراضاتك على الواجهة الأمامية وغالبًا ما يتم توزيع كلاهما بشكل منفصل. يجب أن تنتهي بشكل سيء. نحن بشر فقط ويحدث أحيانًا أننا لم نفهم الطرف الآخر أو نسينا إخبارهم بهذا التغيير الصغير. مرة أخرى ، هذه ليست مشكلة كبيرة مع التعامل الصحيح مع الشبكة - ستفشل استجابة فك التشفير ونعرف كيفية التعامل معها. حتى أفضل كود فك التشفير يمكن أن يتأثر بالتصميم السيئ على الرغم من ...
وظائف جزئية. تصميم سيء.
"سيكون لدينا متغيرين منطقيين هنا:" isActive "و" canTransfer "، بالطبع لا يمكنك النقل عندما لا يكون نشطًا ، ولكن هذه مجرد تفاصيل." هنا يبدأ ، تصميمنا السيئ الذي يمكن أن يضرب بشدة. الآن سيقوم شخص ما بعمل دالة مع هاتين الوسيطتين ومعالجة بعض البيانات بناءً عليها. أبسط حل هو ... مجرد الانهيار في حالة غير صالحة ، يجب ألا يحدث ذلك أبدًا ، لذا لا يجب أن نهتم. نحن نهتم أحيانًا ونترك بعض التعليقات لإصلاحها لاحقًا أو نسأل عما يجب أن يحدث ، ولكن يمكن شحنها في النهاية دون إكمال هذه المهمة.
// كود مزيف function doTransfer (Bool isActive، Bool canTransfer) { إذا (نشط ويمكن نقله) { // افعل شيئًا متاحًا للنقل } else if (not isActive and not canTransfer) { // افعل شيئًا للنقل غير متوفر } else if (isActive and not canTransfer) { // افعل شيئًا للنقل غير متوفر } else {// aka (not isActive and canTransfer) // هناك أربع حالات محتملة // لا ينبغي أن يحدث هذا ، يجب ألا يكون النقل متاحًا عندما لا يكون نشطًا يصطدم() } }
قد يبدو هذا المثال سخيفًا ولكن في بعض الأحيان قد تصطاد نفسك في هذا النوع من المصيدة التي يصعب تحديدها وحلها أكثر من ذلك. ستنتهي بشيء يسمى وظيفة جزئية. هذه وظيفة تم تعريفها فقط لبعض مدخلاتها المحتملة التي تتجاهل أو تتعطل مع الآخرين. يجب دائمًا تجنب الدوال الجزئية (يرجى ملاحظة أنه في اللغات المكتوبة ديناميكيًا يمكن التعامل مع معظم الوظائف على أنها جزئية). إذا لم تستطع لغتك ضمان السلوك المناسب مع فحص النوع والتحليل الثابت ، فقد تتعطل بعد مرور بعض الوقت بطريقة غير متوقعة. تتطور الكود باستمرار وقد لا تكون افتراضات الأمس صالحة اليوم.
اخفاق سريع. كثيرا ما تفشل.
كيف تستطيع حماية نفسك؟ أفضل دفاع هو الهجوم! هناك قول جميل: "تفشل بسرعة. تفشل كثيرًا ". لكن ألم نتفق فقط على أنه يجب علينا تجنب أعطال التطبيق والوظائف الجزئية والتصميم السيئ؟ يمنح Erlang OTP المبرمجين ميزة أسطورية تتمثل في شفاء نفسه بعد الحالات غير المتوقعة والتحديث أثناء التشغيل. يمكنهم تحمل ذلك ، ولكن ليس كل شخص لديه هذا النوع من الرفاهية. فلماذا نفشل بسرعة وفي كثير من الأحيان؟
بادئ ذي بدء ، للعثور على تلك الحالات والسلوكيات غير المتوقعة . إذا لم تتحقق مما إذا كانت حالة تطبيقك صحيحة ، فقد يؤدي ذلك إلى نتائج أسوأ من التعطل!
ثانيًا ، لمساعدة المبرمجين الآخرين على التعاون في نفس قاعدة الشفرة . إذا كنت بمفردك في مشروع الآن ، فقد يكون هناك شخص آخر من بعدك. قد تنسى بعض الافتراضات والمتطلبات. من الشائع إلى حد ما عدم قراءة الوثائق المقدمة حتى يعمل كل شيء أو لا توثق الطرق والأنواع الداخلية على الإطلاق. في هذه الحالة ، يقوم شخص ما باستدعاء إحدى الوظائف المتاحة بقيمة غير متوقعة ولكنها صالحة. على سبيل المثال ، لنفترض أن لدينا وظيفة "انتظار" تأخذ أي قيمة عددية وتنتظر هذا المقدار من الثواني. ماذا لو مر أحدهم بـ "-17"؟ إذا لم يتعطل مباشرة بعد القيام بذلك ، فقد يؤدي ذلك إلى بعض الأخطاء الجسيمة والحالات غير الصالحة. هل تنتظر إلى الأبد أم لا على الإطلاق؟

أهم جزء من الاصطدام المتعمد هو القيام بذلك بأمان . في حالة تعطل التطبيق الخاص بك ، يجب عليك تقديم بعض المعلومات للسماح بالتشخيص. من السهل جدًا استخدام مصحح أخطاء ولكن يجب أن يكون لديك طريقة ما للإبلاغ عن أعطال التطبيق بدونه. يمكنك استخدام أنظمة التسجيل للحفاظ على هذه المعلومات بين عمليات تشغيل التطبيق أو النظر إليها خارجيًا.
ثاني أهم جزء من الاصطدام المتعمد هو تجنب ذلك في بيئة الإنتاج ...
لا تفشل. أي وقت مضى.
سوف تقوم بشحن الرمز الخاص بك في النهاية. لا يمكنك جعله مثاليًا ، فغالبًا ما يكون التفكير في تقديم ضمانات للصحة أمرًا مكلفًا للغاية. ومع ذلك ، يجب عليك التأكد من أنه لن يسيء التصرف أو يتعطل. كيف يمكنك تحقيق ذلك بما أننا قررنا بالفعل الانهيار بسرعة وفي كثير من الأحيان؟
جزء مهم من الانهيار المتعمد هو القيام بذلك فقط في البيئات غير الإنتاجية . يجب عليك استخدام التأكيدات التي تم تجريدها في إصدارات الإنتاج لتطبيقك. سيساعد هذا أثناء التطوير ويسمح باكتشاف المشكلات مع عدم التأثير على المستخدمين النهائيين. ومع ذلك ، لا يزال من الأفضل التعطل في بعض الأحيان لتجنب حالات التطبيق غير الصالحة. كيف يمكننا تحقيق ذلك إذا قمنا بالفعل بعمل وظائف جزئية؟
اجعل الحالات غير المحددة وغير الصالحة من المستحيل تمثيلها والعودة إلى الحالات الصالحة بخلاف ذلك. قد يبدو ذلك سهلاً ولكنه يتطلب الكثير من التفكير والعمل. بغض النظر عن مقدارها ، فهي دائمًا أقل من البحث عن الأخطاء وإجراء إصلاحات مؤقتة و ... مزعج المستخدمين. سيؤدي تلقائيًا إلى تقليل احتمالية حدوث بعض الوظائف الجزئية.
// كود مزيف الدالة doTransfer (حالة الولاية) { التبديل (الدولة) { حالة State.canTransfer { // افعل شيئًا متاحًا للنقل } حالة State.cannotTransfer { // افعل شيئًا للنقل غير متوفر } حالة State.notActive { // افعل شيئًا للنقل غير متوفر } // من المستحيل تمثيل النقل المتاح دون أن يكون نشطًا // لا يوجد سوى ثلاث حالات محتملة } }
كيف يمكنك جعل الدول غير الصالحة مستحيلة؟ دعنا نختار اثنين من الأمثلة السابقة. في حالة المتغيرين المنطقيين "isActive" و "canTransfer" ، يمكننا تغيير هذين المتغيرين إلى تعداد فردي. سوف يمثل بشكل شامل جميع الدول الممكنة والصالحة. حتى مع ذلك ، يمكن لأي شخص إرسال متغيرات غير محددة ، ولكن هذا أسهل بكثير في التعامل معها. ستكون قيمة غير صالحة لن يتم استيرادها إلى برنامجنا بدلاً من تمرير حالة غير صالحة إلى الداخل مما يجعل كل شيء أكثر صعوبة.
يمكن أيضًا تحسين وظيفة الانتظار الخاصة بنا بشكل جيد في اللغات المكتوبة بقوة. يمكننا جعله يستخدم فقط الأعداد الصحيحة بدون إشارة على المدخلات. هذا وحده سيصلح جميع مشاكلنا لأن الحجج غير الصالحة سيتم تجريدها من قبل المترجم. لكن ماذا لو لم تكن لغتك أنواع؟ لدينا بعض الحلول الممكنة. أولاً - تعطل فقط ، هذه الوظيفة غير محددة للأرقام السالبة ولن نقوم بأشياء غير صالحة أو غير محددة. سيتعين علينا اكتشاف الاستخدام غير الصحيح لها أثناء الاختبارات. ستكون اختبارات الوحدة (التي يجب أن نقوم بها على أي حال) مهمة حقًا هنا. ثانيًا - قد يكون هذا محفوفًا بالمخاطر ، ولكن اعتمادًا على السياق قد يكون مفيدًا. يمكننا الرجوع إلى القيم الصالحة مع الاحتفاظ بالتوكيد في البنيات غير الإنتاجية لإصلاح الحالات غير الصالحة عندما يكون ذلك ممكنًا. قد لا يكون حلاً جيدًا لوظائف مثل هذا ، ولكن إذا قمنا بعمل قيمة مطلقة لعدد صحيح بدلاً من ذلك ، فسوف نتجنب أعطال التطبيق. اعتمادًا على اللغة الملموسة ، قد يكون من الجيد أيضًا طرح / إثارة بعض الأخطاء / الاستثناءات بدلاً من ذلك. قد يكون من المفيد الرجوع إلى الوراء إن أمكن ، حتى عندما يرى المستخدم خطأ ، فإنها تجربة أفضل بكثير من الانهيار.
لنأخذ مثالاً آخر هنا. إذا كانت حالة بيانات المستخدم في تطبيق الواجهة الأمامية على وشك أن تكون غير صالحة لبعض الحالات ، فقد يكون من الأفضل فرض تسجيل الخروج والحصول على بيانات صالحة مرة أخرى من الخادم بدلاً من التعطل. قد يضطر المستخدم إلى القيام بذلك على أي حال أو يمكن أن يتم القبض عليه داخل حلقة تعطل لا نهاية لها. مرة أخرى - يجب أن نؤكد ونعطل في مثل هذه المواقف في البيئات غير الإنتاجية ، لكن لا تسمح للمستخدمين أن يكونوا مختبرين خارجيين.
ملخص
لا أحد يحب التعطل والتطبيقات غير المستقرة. نحن لا نحب صنعها أو استخدامها. إن الفشل السريع مع التأكيدات التي توفر تشخيصًا مفيدًا أثناء التطوير والاختبارات سيواجه الكثير من المشكلات مبكرًا. سيؤدي الرجوع عن الحالات الصالحة في الإنتاج إلى جعل تطبيقك أكثر استقرارًا. إن جعل الحالات غير الصالحة غير قابلة للتمثيل سيؤدي إلى التخلص من فئة كاملة من المشاكل. امنح نفسك مزيدًا من الوقت للتفكير قبل التطوير حول كيفية التخلص من الحالات غير الصالحة والتراجع عنها ، والمزيد أثناء الكتابة لتضمين بعض التأكيدات. يمكنك البدء في تحسين تطبيقاتك اليوم!
اقرأ أكثر:
- التصميم بالعقد
- نوع البيانات الجبرية