مقدمة
هذه المقالة هي رد فعل على المقالة: ماذا سيحدث لمعالجة الخطأ في C ++ 2a . بعد كل فقرة ، أصبت بحكة ، وفتحت جروحًا شافية وبدأت تنزف. ربما آخذ ما هو مكتوب من قلبي. لكني أريد فقط أن أصرخ حول قصر النظر والأمية الذي يظهره مبرمجو C ++ في القرن الحادي والعشرين. ولا حتى في البداية.
دعنا نبدأ.
التصنيف
تقليديا ، يمكن تقسيم جميع المواقف الخاطئة في البرنامج إلى مجموعتين كبيرتين:
- أخطاء فادحة.
- ليست أخطاء فادحة أو متوقعة.
سأجد الآن خطأ. لكن الأخطاء المميتة - هي أيضًا متوقعة إلى حد ما. نتوقع أن السفر عبر الذاكرة غالبًا ما يؤدي إلى السقوط ، ولكن قد لا يؤدي إلى ذلك. وهذا أمر متوقع ، أليس كذلك؟ عند تقديم التصنيف ، سيكون من الممكن دائمًا التحقق منه من أجل الاتساق.
ولكن هذا خطأ فادح ومتكرر.
دعونا نلقي نظرة على الأخطاء الفادحة.
القسمة على 0 . أتساءل لماذا هذا الخطأ فادح؟ أود أن أعرض استثناءً في هذه الحالة وأن أمسك به لمزيد من المعالجة. لماذا هي قاتلة؟ لماذا يفرض عليّ سلوك معين من برنامجي الخاص ، ولا يمكنني التأثير عليه بأي شكل من الأشكال؟ أليست لغة C ++ تتعلق بالمرونة وحقيقة أن اللغة تتجه نحو المبرمج؟ على الرغم من ...
إلغاء الإشارة إلى مؤشر Null . أتذكر على الفور جافا ، هناك NullPointerException
التي يمكن معالجتها. يوجد أيضًا NullPointerException
مكتبة Poco! فلماذا يكرر المطوّرون العاديون بعزم الصم والبكم نفس المانترا؟
بشكل عام ، لماذا بدأت هذا الموضوع؟ إنه مهم للغاية ويكشف فقط عن فهم المطور حول معالجة الأخطاء. لا يتعلق هذا بمعالجة الخطأ في حد ذاته ، فهو مقدمة لعمل مهم. يتعلق الأمر دائمًا بموثوقية التطبيق ، والتسامح مع الأخطاء ، وأحيانًا ، في أكثر الأنواع النادرة والمهددة بالانقراض ، حتى أقول ، أنواع البرامج المهددة بالانقراض ، حول السلوك المعاملات والمتسق.
في هذا الجانب ، تبدو جميع الخلافات حول القسمة على صفر ومؤشرات الإحالة وكأنها صراع بين الطيور على فتات الخبز. بالتأكيد عملية مهمة. ولكن فقط من وجهة نظر الطيور.
دعونا نعود إلى الانقسام إلى القدرية وغيابه ... سأبدأ بسؤال بسيط: إذا تلقيت بيانات غير صحيحة عبر الشبكة ، فهل هذا خطأ فادح؟
إجابة بسيطة وصحيحة: تعتمد على. من الواضح أن هذا ليس خطأ فادحًا في معظم الحالات ، ويجب التحقق من صحة جميع البيانات المستلمة عبر الشبكة وإرجاع 4xx إذا كانت البيانات غير صحيحة. هل هناك أي حالات تحتاج فيها إلى التصادم؟ وتحطمت بعواء صاخب ، بحيث تأتي الرسائل القصيرة ، على سبيل المثال. نعم ولا واحد.
يوجد. يمكنني إعطاء مثال من مجال الموضوع الخاص بي: خوارزمية إجماع موزعة. تتلقى العقدة استجابة تحتوي على تجزئة من سلسلة تغييرات من عقدة أخرى. وهذه التجزئة تختلف عن التجزئة المحلية. هذا يعني أن هناك خطأ ما ، ومواصلة التنفيذ أمر خطير بكل بساطة: قد تختلف البيانات ، إن لم يكن بالفعل. يحدث ذلك عندما يكون توفر الخدمة أقل أهمية من اتساقها. في هذه الحالة ، علينا أن نسقط ، مع هدير ، حتى يسمع الجميع. على سبيل المثال تلقينا البيانات عبر الشبكة ، وتم التحقق منها ، وسقطت. بالنسبة لنا ، هذا الخطأ ليس أكثر فتكًا. هل هذا الخطأ متوقع؟ حسنًا ، نعم ، لقد كتبنا الرمز مع التحقق من الصحة. من الغباء أن تقول العكس. فقط لا نريد متابعة البرنامج بعد ذلك. مطلوب التدخل اليدوي ، لم تنجح الأتمتة.
اختيار القدرية
الشيء الأكثر غموضاً في معالجة الأخطاء هو تقرير ما هو مميت وما هو غير قاتل. لكن كل مبرمج يسأل هذا السؤال لنفسه طوال نشاط التطوير بأكمله. لذلك ، فإنه يجيب على نحو ما على هذا السؤال. الجواب الصحيح يأتي من الممارسة لسبب ما.
ومع ذلك ، هذا ليس سوى الجزء المرئي من جبل الجليد. في الأعماق هناك سؤال أكثر وحشية. لفهم العمق الكامل ، تحتاج إلى تعيين مهمة بسيطة ومحاولة الإجابة عليها.
التحدي . اصنع إطارًا لشيء ما.
كل شيء بسيط. نحن نصنع إطار عمل ، على سبيل المثال ، للتفاعل الشبكي. أو تحليل JSON. أو في أسوأ الأحوال ، XML. يطرح السؤال على الفور: ولكن عندما يحدث خطأ من المقبس - هل هو خطأ فادح أم لا؟ لإعادة الصياغة: هل يجب أن أقوم باستثناء أو أعيد خطأ؟ هل هذا وضع استثنائي أم لا؟ أو يمكن إرجاع std::optional
؟ أم راهبة؟ (^ 1)
الاستنتاج المتناقض هو أن الإطار نفسه لا يستطيع الإجابة على هذا السؤال. فقط الرمز الذي يستخدمه يعرف. هذا هو السبب في أن مكتبة boost.asio الممتازة ، في رأيي ، تستخدم كلا الخيارين. اعتمادًا على التفضيلات الشخصية لمؤلف الكود والمنطق المطبق ، يمكن اختيار طريقة أو أخرى لمعالجة الأخطاء. في البداية ، كنت محرجًا قليلاً من هذا النهج ، ولكن بمرور الوقت كنت مشبعًا بمرونة هذا النهج.
ومع ذلك ، هذا ليس كل شيء. الأسوأ هو أن يأتي. هنا نكتب رمز التطبيق ، ولكن يبدو لنا أنه تم تطبيقه. بالنسبة لرمز آخر ، مستوى أعلى ، سيكون رمزنا مكتبة. على سبيل المثال التقسيم إلى كود التطبيق / المكتبة (الإطار ، إلخ) هو اصطلاح محض يعتمد على مستوى إعادة استخدام المكونات. يمكنك دائمًا تثبيت شيء ما في الأعلى وسيتوقف رمز التطبيق عن ذلك. وهذا يعني على الفور أن اختيار ما هو صالح وما لم يتم تحديده بالفعل بواسطة الكود الذي يستخدم ، وليس مستخدمًا.
إذا قفزنا إلى الجانب ، اتضح أنه في بعض الأحيان لا يمكن حتى فهم من يستخدم من. على سبيل المثال يمكن أن يستخدم المكون A المكون B ، والمكون B المكون A (^ 2). على سبيل المثال من يحدد ما سيحدث ليس واضحًا على الإطلاق.
تشابك التشابك
عندما تنظر إلى كل هذا الخزي ، يطرح السؤال على الفور: كيف تتعايش معه؟ ماذا تفعل ما هي المبادئ التوجيهية التي تختارها ، حتى لا تغرق في التنوع؟
للقيام بذلك ، من المفيد النظر حولك وفهم كيفية حل هذه المشكلات في أماكن أخرى. ومع ذلك ، يجب على المرء البحث بحكمة: من الضروري التمييز بين "جمع الطوابع" والحلول الكاملة.
ما هو جمع الطوابع؟ هذا مصطلح جماعي ، مما يعني أننا تبادلنا هدفًا ولكن شيء آخر. على سبيل المثال: كان لدينا هدف - الاتصال والتواصل مع أحبائهم. ونحن ذات مرة ، واشترنا لعبة باهظة الثمن ، لأن "الموضة" و "الجميلة" (^ 3). هل هذا مألوف؟ هل تعتقد أن هذا لا يحدث للمبرمجين؟ لا تملق نفسك.
معالجة الخطأ ليس الهدف. عندما نتحدث عن معالجة الخطأ ، نصل على الفور إلى طريق مسدود. لأنها طريقة لتحقيق الهدف. والهدف الأولي هو جعل برامجنا موثوقة وبسيطة ومفهومة. هذه هي الأهداف التي يجب تحديدها والالتزام بها دائمًا. ومعالجة الخطأ هراء لا يستحق المناقشة. أريد أن أرمي استثناء - ولكن على الصحة! عاد خطأ - أحسنت! تريد موناد؟ مبروك ، لقد خلقت وهم التقدم ، ولكن فقط في رأسك (^ 4).
ثم أردت كتابة كيفية القيام بذلك بشكل صحيح ، لكنني كتبت بالفعل. تلتئم الجروح وتوقف النزيف. باختصار ، النصائح هي:
- افصل إلى مكونات ذات حدود واضحة.
- على الحدود ، صف كيف وكيف تطير. من المستحسن أن تكون موحدة. ولكن الأهم من ذلك بكثير.
- اجعل من السهل معالجة الأخطاء في التعليمات البرمجية التي ستستخدمها.
- إذا كان هناك شيء يمكن معالجته داخليًا دون تحميل رمز المستخدم ، فلا تلصقه. كلما قل عدد الأخطاء التي يحتاج المستخدم إلى معالجتها ، كان ذلك أفضل.
- احترم المستخدم الخاص بك ، لا تكن غباء! اكتب واجهات بديهية بسلوك متوقع حتى لا يحتاج إلى قراءة التعليقات والشتائم.
النصيحة الخامسة هي الأهم ، لأن يجمع بين الأربعة الأولى.
ملاحظة: في مرحلة الطفولة ، كنت دائما أشعر بالفضول للنظر إلى النمل. الآلاف من النمل ، كل شخص يفعل شيئًا ، يزحف حول عمله. العملية قيد التشغيل. الآن أنا أيضا أشاهد باهتمام. أيضا خلف عش النمل. حيث يقوم آلاف الأفراد بعملهم الصغير. أتمنى لهم حظا سعيدا في عملهم الشاق!
^ 1: الناس مغرمون بالأشياء العصرية. عندما لعب الجميع ما يكفي ، استيقظ مبرمجو C ++ ، ثم استدار كل شيء.
^ 2: يمكن أن يحدث هذا عندما يكون هناك العديد من الملخصات في المكون B الذي يربطها. انظر قلب السيطرة .
^ 3: وفي اليوم التالي ، تحطمت bam ، وتعطلت الشاشة.
^ 4: أنا لست ضد الموناد ، أنا ضد الطموح ، مثل ، انظر ، ها هو الموناد ، أي أحادي في فئة أحادية من endofunctors! يسمع التصفيق والموافقة. وفي مكان ما بعيد جدا ، بالكاد مسموع ، شخص هزات الجماع.