سؤال

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

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

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

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

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

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

"لا يمكن عرض قائمة أسماء العملاء المطلوبة."

"فشل الحصول على قائمة العملاء الذين طلبتهم بسبب خطأ في قاعدة البيانات."

"كان هناك خطأ في الاتصال بقاعدة البيانات عند استرداد قائمة العملاء"

"فشل تسجيل الدخول للمستخدم xx"

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

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

المحلول

انها مجرد فظيعة بعض الشيء.

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

لكنك ستحتاج إلى تسجيل كل خطأ لا تتعامل معه.

بالمناسبة، عرض المعلومات حول الأخطاء التي تحدث قد يؤدي إلى ثغرات أمنية.كلما قلّت معرفة المهاجمين بنظامك، قلت احتمالية عثورهم على طرق لاختراقه (تذكر تلك الرسائل مثل "خطأ في بناء الجملة في عبارة SQL:حدد * من المستخدمين حيث اسم المستخدم='a';قاعدة بيانات drp؛--'..." متوقع:"إسقاط" بدلاً من "drp".إنهم لا يصنعون مواقع مثل هذه بعد الآن).

نصائح أخرى

يعد طرح استثناءات جديدة أمرًا مكلفًا من الناحية الفنية، ومع ذلك لن أقوم بإجراء نقاش كبير حول ذلك نظرًا لأن كلمة "مكلفة" نسبية - إذا كنت تطرح 100 استثناء من هذا القبيل في الدقيقة، فمن المحتمل ألا ترى التكلفة؛إذا كنت ترمي 1000 من هذه الاستثناءات في الثانية، فقد ترى نجاحًا كبيرًا في الأداء (وبالتالي، لا يستحق المناقشة هنا حقًا - الأداء هو مكالمتك).

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

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

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

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

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

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

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

فيما يلي بعض المقالات اللائقة حول أفضل ممارسات التعامل مع الاستثناءات:

http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx

http://aspalliance.com/1119

Jeez هذا حصل على الألفاظ ... الاعتذارات مقدما.

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

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

أعتقد أنك على الطريق الصحيح فيما تفعله.

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

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

  1. يمكننا أن نفعل شيئًا حيال ذلك - على سبيل المثال، نحن نعلم أن هذا قد يحدث أحيانًا ويمكننا تصحيحه في الكود عند حدوثه (نادر جدًا).

  2. نريد أن نعرف حدوث ذلك وأين (ثم نعيد طرح الاستثناء).

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

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

  1. نريد قمع الاستثناء بالكامل والاستمرار.وغني عن القول أننا نفعل ذلك فقط لأنواع الاستثناءات المتوقعة وفقط عندما لا تكون هناك طريقة أخرى لاكتشاف الحالة التي تولد الاستثناء.

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

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