سؤال

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

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

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

وإليك بعض النقاط في الاعتبار:

  1. هناك الكثير من الناس من إنشاء حسابات في وقت واحد.أنا لا أريد أن قفل كل الجدول المستخدم بين "حدد" لمعرفة ما إذا كان الاسم موجود و "إدراج" إذا لم يحدث ذلك.في حالة قواعد البيانات العلائقية ، قد يكون هناك بعض الحيل للتغلب على هذه, ولكن ما أنا مهتم حقا في هي الحالة العامة حيث قبل التحقق استثناء لا تعمل بسبب أساسيا حالة السباق.نفس الشيء يمكن أن ينطبق تبحث عن الملف في نظام الملفات ، الخ.
  2. نظرا CTO هو الميل القيادة الإدارية الناجمة عن القراءة تكنولوجيا الأعمدة في "المؤتمر الوطني العراقي.", أحتاج طبقة من المراوغة حول استمرار آلية حتى أستطيع أن طرد السبات استخدام كودو, أو أيا كان من دون تغيير أي شيء ما عدا طبقة أدنى من رمز المثابرة.في الواقع ، هناك العديد من مثل هذه الطبقات من التجريد في نظام بلدي.كيف يمكنني منعهم من تسرب بالرغم من دون رادع استثناءات ؟
  3. واحدة من مخطوب الضعف فحص الاستثناءات هو الحاجة إلى "التعامل مع" لهم في كل مكالمة على المكدس—إما بإعلان أن استدعاء الأسلوب يلقي عليهم أو القبض عليهم والتعامل معها.التعامل معها في كثير من الأحيان يعني التفاف عليها في آخر فحص استثناء من نوع المناسبة إلى مستوى من التجريد.لذا, فعلى سبيل المثال, في فحص-استثناء الأراضي ملف النظام القائم على التنفيذ من UserRegistry قد قبض IOException, بينما قاعدة بيانات تنفيذ قبض SQLException, ولكن كلا سوف رمي UserNotFoundException الذي يخفي وراء التنفيذ.كيف يمكنني الإستفادة من دون رادع الاستثناءات تجنيب نفسي من عبء هذا التفاف في كل طبقة ، دون تسرب تنفيذ التفاصيل ؟
هل كانت مفيدة؟

المحلول

المنظمة البحرية الدولية التفاف الاستثناءات (فحص أو خلاف ذلك) لديه العديد من الفوائد التي تستحق التكلفة:

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

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

3) أنها تمكنك من أن تصبح مستقلة التنفيذ من أقل مستوى الرمز.إذا كنت التفاف الاستثناءات تحتاج إلى مبادلة خارج السبات بعض ORM, لديك فقط لتغيير السبات-التعامل مع التعليمات البرمجية.جميع طبقات أخرى من التعليمات البرمجية سوف يكون لا يزال بنجاح باستخدام ملفوفة الاستثناءات و سيتم تفسيرها في نفس الطريق, على الرغم الأساسية الظروف قد تغيرت.لاحظ أن هذا ينطبق حتى إذا السبات التغييرات في بعض الطريق (على سبيل المثال:التبديل الاستثناءات في نسخة جديدة);ليس فقط على الجملة استبدال التكنولوجيا.

4) وتشجع استخدام فئات مختلفة من الاستثناءات تمثل حالات مختلفة.على سبيل المثال, قد يكون لديك DuplicateUsernameException عندما يحاول المستخدم إعادة استخدام اسم المستخدم و DatabaseFailureException عندما لا تستطيع التحقق من خداع المستخدمين بسبب كسر في اتصال DB.وهذا بدوره يتيح لك الإجابة على سؤالك ("كيف يمكنني استرداد؟") في مرنة وقوية الطرق.إذا كنت تحصل على DuplicateUsernameException, كنت قد قررت أن تشير إلى اسم مستخدم مختلف للمستخدم.إذا كنت تحصل على DatabaseFailureException قد وليكن فقاعة تصل إلى نقطة حيث يعرض "للصيانة" صفحة المستخدم وإرسال إشعار البريد الإلكتروني لك.مرة واحدة كنت قد مخصص الاستثناءات لديك customizeable الردود ... و هذا شيء جيد.

نصائح أخرى

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

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

انظر أنماط الجيل ، والتعامل مع إدارة الأخطاء

من تقسيم المجال و الأخطاء الفنية نمط

خطأ فني يجب أن لا يسبب المجال الخطأ أن يتم إنشاء (لم توين يجب الوفاء).عندما خطأ فني يجب أن يسبب الأعمال معالجة الفشل ، ينبغي أن يكون ملفوفة كما SystemError.

المجال أخطاء يجب أن تبدأ دائما من نطاق المشكلة و معالجتها من قبل مجال المدونة.

المجال أخطاء يجب أن تمرير "بسلاسة" من خلال التقنية الحدود.قد يكون من أن مثل هذه الأخطاء يجب أن يكون تسلسل وإعادة تشكيلها لهذا أن يحدث.وكلاء واجهات يجب أن يتحمل مسؤولية القيام بذلك.

أخطاء فنية يجب أن يتم التعامل معها في نقاط معينة في تطبيق مثل الحدود (انظر سجل في توزيع الحدود).

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

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

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

مساعدة ؟

أنا أتفق مع نيك.استثناء وصفت ليست حقا "استثناء غير متوقع" لذلك يجب تصميم رمز لذلك أخذ الاستثناءات المحتملة في الحسبان.

كما أنصح أن نلقي نظرة على وثائق Microsoft مكتبة المؤسسة معالجة الاستثناء كتلة لديها لطيفة مخطط من الخطأ التعامل مع الأنماط.

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

try {
    throw new IllegalArgumentException();
} catch (Exception e) {
    System.out.println("boom");
}

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

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

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

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

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

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

    في أقرب وقت ممكن نمسك ConstraintViolationException وتحويله إلى MessageException مع رسالة لطيفة.من المهم أن تحويله قريبا عندما يمكننا أن نكون متأكدين إنها "اسم مستخدم فريد القيد" الذي انتهك وليس بعض القيود الأخرى.

    في مكان ما بالقرب من أعلى مستوى معالج فقط التعامل مع MessageException بطريقة مختلفة.بدلا من "نحن تسجيل مشكلتك ولكن الآن أنت مسقي" ببساطة عرض الرسالة الواردة في MessageException لا تتبع المكدس.

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

رمز قد تبدو مثل هذا

// insert the user
try {
   hibernateSession.save(user);
} catch (ConstraintViolationException e) {
   throw new MessageException("Username " + user.getName() + " already exists. Please choose a different name.");
}

في مكانا مختلفا تماما هناك أفضل معالج استثناء

try {
   ... render the page
} catch (MessageException e) {
   ... render a nice page with the message
} catch (Exception e) {
   ... render "we logged your problem but for now you're hosed" message
}

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

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

@إريكسون

فقط لإضافة المواد الغذائية إلى أفكارك:

فحص مقابل لحالها أيضا ناقش هنا

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

بخصوص مسألة محددة ، يجب الإمساك دون رادع استثناء على مستوى عال ، لتغليف ذلك ، كما قال @Kanook في الاستثناء دون عرض مكدس الاستدعاءات (كما satellite بواسطة @Jan Soltis )

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

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