رمي/عدم رمي استثناء على أساس معلمة - لماذا لا يكون هذا هو فكرة جيدة ؟

StackOverflow https://stackoverflow.com/questions/624647

سؤال

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

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

Uri ParseUri(string uriValue, bool throwOnError)

الآن بالطبع أستطيع أن أرى ذلك في 99% من الحالات سيكون هذا فظيع لكن هو استخدام في بعض الأحيان مبرر ؟

حالة واحدة لقد رأيت ذلك استخدامها مع "AllowEmpty" المعلمة عند الوصول إلى البيانات في قاعدة البيانات أو ملف التكوين.على سبيل المثال:

object LoadConfigSetting(string key, bool allowEmpty);

في هذه الحالة سيكون البديل هو العودة إلى null.ولكن بعد الدعوة سوف يكون رمز تناثرت null المراجع التحقق.(و الأسلوب من شأنه أيضا أن يمنع القدرة على الواقع تسمح فارغة كما تحديدا شكلي القيمة ، إذا كنت تميل ذلك).

ما هي أفكارك ؟ لماذا تكون هذه مشكلة كبيرة ؟

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

المحلول

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

فإنه سيكون أفضل بكثير و أكثر قابلية للقراءة إلى 2 واجهات برمجة التطبيقات في هذه الحالة.

Uri ParseUriOrThrow(string value);

bool TryParseUri(string value, out Uri uri);

في هذه الحالة انها 100 ٪ من الواضح ما هذه واجهات برمجة التطبيقات القيام به.

المادة على القيم المنطقية لماذا هي سيئة كما المعلمات: http://blogs.msdn.com/jaredpar/archive/2007/01/23/boolean-parameters.aspx

نصائح أخرى

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

في المثال أعلاه, ماذا يحدث إذا كان تحليل فشل throwOnError هي كاذبة ؟ الآن المستخدم تخمين إذا لاغية إذا كان سوف تعاد ، أو يعلم الله...

صحيح هناك جدل مستمر بين الاستثناءات والعودة القيم أفضل معالجة الأخطاء الطريقة ولكن أنا متأكد أن هناك توافق في الآراء حول كونها متسقة الخلاف مع أيا كان اختيارك.API لا يمكن أن مفاجأة للمستخدمين ومعالجة الأخطاء يجب أن تكون جزءا من واجهة ، وأن تكون واضحة المعالم مثل واجهة.

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

ومع ذلك, أعتقد أن المقالة MSDN بدقة مشيرا إلى 'throwOnError' الأعلام.في هذه الحالات إما الخطأ تجاهل داخل الأسلوب نفسه (سيئة, كما انها خفية) أو من نوع null/خطأ يتم إرجاع كائن (سيئة لأنك لا تستخدم الاستثناءات للتعامل مع الخطأ ، وهو ما يتعارض و نفسها عرضة للخطأ).

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

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

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

مثال آخر في خط مع هذا يمكن أن يكون مجموعة من TryParse الطرق على بعض أنواع قيمة

bool DateTime.TryParse(string text, out DateTime)

وجود donTThrowException المعلمة الهزائم الغرض من الاستثناءات (في أي لغة).إذا كان رمز الدعوة يريد أن يكون:

public static void Main()
{
        FileStream myFile = File.Open("NonExistent.txt", FileMode.Open, FileAccess.Read);
}

أهلا بكم في (C# حتى لا يكون فحص الاستثناءات).في جافا نفس الشيء سوف يتحقق مع:

public static void main(String[] args) throws FileNotFoundException
{
        FileInputStream fs = new FileInputStream("NonExistent.txt");
}

في الحالتين المتصل العمل أن يقرر كيفية التعامل مع (أو لا) الاستثناء لا المستدعى هو.

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

جيفري Richters كتاب CLR عن طريق C# نقطة الخروج "يجب عليك رمي استثناء عندما الأسلوب لا يمكن إكمال مهمته كما يشير اسمها".

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

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

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

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

Byte[] ReadPacket(منطقي DontThrowIfNone) // توثيق تعود فارغة إذا كان أي { الباحث ليون = ReadByte(DontThrowIfNone);// توثيق العودة -1 إذا كان أي شيء إذا (لين

إذا كان هناك شيء مثل TimeoutException أثناء قراءة البيانات يجب أن يسبب استثناء ، هذا الاستثناء ينبغي أن يلقى في ReadByte() أو ReadMultiBytesbytes().ومع ذلك ، إذا كان مثل هذا الافتقار إلى البيانات ينبغي النظر العادي ، ثم ReadByte() أو ReadMultiBytesbytes() روتين لا ينبغي رمي استثناء.إذا كان أحد ببساطة استخدام تفعل/محاولة نمط ، ReadPacket و TryReadPacket إجراءات من شأنها أن تحتاج إلى متطابقة تقريبا رمز ، ولكن مع واحد باستخدام قراءة* أساليب أخرى باستخدام TryRead* الأساليب.رديء.

قد يكون من الأفضل استخدام التعداد بدلا من منطقية.

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