أن طريقة استرجاع العودة 'null' أو رمي استثناء عندما لا يمكن أن تنتج عودة قيمة ؟ [مغلقة]

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

  •  05-07-2019
  •  | 
  •  

سؤال

لدي الطريقة التي من المفترض أن عودة كائن إذا وجدت.

إذا لم يتم العثور علي أن:

  1. العودة فارغة
  2. رمي استثناء
  3. أخرى
هل كانت مفيدة؟

المحلول

إذا كنت دائما أتوقع أن تجد قيمة ثم رمي استثناء إذا مفقود.الاستثناء يعني أن هناك مشكلة.

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

أكثر أهمية:ماذا تفعل أماكن أخرى في الكود ؟ الاتساق هو المهم.

نصائح أخرى

فقط رمي استثناء إذا كان حقا خطأ.إذا كان هذا هو السلوك المتوقع من أجل الاعتراض على عدم وجود إرجاع null.

وإلا فإنه هو مسألة تفضيل.

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

مهما فعلت ننصح بشدة ضد الخيار الثالث:تعود سلسلة تقول "WTF".

إذا كان باطلا لم يدل على خطأ فقط ثم العودة فارغة.

إذا باطل هو دائما خطأ ثم رمي استثناء.

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

من الصعب أن إساءة استخدام محاولة الروتينية.من السهل أن تنسى أن تحقق null.

لذلك عندما باطل هو خطأ تكتب

object o = FindObject();

عندما تكون فارغة ليس خطأ يمكنك رمز شيئا مثل

if (TryFindObject(out object o)
  // Do something with o
else
  // o was not found

أنا فقط أردت أن ألخص الخيارات المذكورة قبل رمي بعض جديدة في:

  1. العودة فارغة
  2. رمي استثناء
  3. استخدام null كائن نمط
  4. توفر المعلمة المنطقية لكم طريقة ، حتى يمكن المتصل من اختار إن كان يريد رمي استثناء
  5. توفر المزيد من المعلمة ، لذلك المتصل يمكن تعيين قيمة التي يعود إذا لا قيمة

أو قد تجمع بين هذه الخيارات:

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

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

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

يجب عدم الإفراط في ذلك ، ولكن قد يكون مفيدا ، espeacially عند كتابة مساعد الدرجة التي سوف تستخدم في مئات التطبيقات المختلفة مع العديد من مختلف الخطأ التعامل مع الاتفاقيات.

استخدام null كائن نمط أو رمي استثناء.

تكون متسقة مع API(s) الذي تستخدمه.

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

النسخة القصيرة:استخدام الاستثناءات استثنائية للتعامل مع السلوك ، عدم التعامل مع التدفق الطبيعي التحكم في البرنامج.

-ألان.

ذلك يعتمد إذا كانت لغتك و رمز يعزز:LBYL (انظر قبل أن تقفز) أو EAFP (أسهل طلب المغفرة من إذن)

LBYL يقول يجب التحقق من القيم (حتى تعود فارغة)
EAFP يقول أن مجرد محاولة العملية ومعرفة ما إذا كان فشل (رمي استثناء)

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


EAFP مقابلLBYL في بايثون:
http://mail.python.org/pipermail/python-list/2003-May/205182.html (أرشيف ويب)

مزايا رمي استثناء:

  1. نظافة تدفق التحكم في الاتصال الخاص بك التعليمات البرمجية. التحقق null يقحم المشروط الفرع الذي هو أصلا التعامل معها من قبل try/catch.التحقق فارغة لا تشير إلى ما هو عليه كنت التحقق هل أنت التحقق من باطل لأن كنت تبحث عن خطأ كنت تتوقع ، أو أنت التحقق من باطل حتى لا تمر كذلك على downchain?
  2. يزيل الغموض ما "null" يعني. باطل ممثل خطأ أو باطل ما هو في الواقع المخزنة في القيمة ؟ من الصعب القول عندما يكون لديك فقط شيء واحد إلى قاعدة تحديد قبالة.
  3. تحسين الاتساق بين أسلوب السلوك في التطبيق. الاستثناءات هي عادة ما تعرض في أسلوب التوقيعات ، لذلك كنت أكثر قدرة على فهم ما الحالات حافة الطرق في تطبيق الحساب ، وما معلومات التطبيق الخاص بك يمكن أن تتفاعل بطريقة يمكن التنبؤ بها.

لمزيد من التوضيح مع الأمثلة ، انظر: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/

الاستثناءات هي ذات الصلة إلى تصميم العقد.

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

1) جميع المدخلات طريقة صحيحة في هذه الحالة يجب عليك العودة فارغة عندما لم يتم العثور على الكائن.

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

is_present(key)
find(key) throws Exception

إذا و فقط إذا توفر كل أساليب 2nd العقد ، يحق لك رمي استثناء شيء وجدت!

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

يعتمد على ما كان يعني أنه لم يتم العثور على الكائن.

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

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

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

وإليك بعض الاقتراحات.

إذا إرجاع جمع تجنب العودة null, العودة فارغة جمع مما يجعل التعداد أسهل للتعامل مع دون فارغة تحقق أولا.

عدة .NET API استخدام نمط thrownOnError المعلمة الذي يعطي المتصل الاختيار ما إذا كان هو حقا حالة استثنائية أو لم يكن إذا لم يتم العثور على الكائن.نوع.GetType هو مثال على ذلك.آخر النمط المشترك مع BCL هو TryGet نمط أين منطقية هو إرجاع القيمة التي يتم تمريرها عبر معلمة إخراج.

هل يمكن أن تنظر أيضا باطل من وجوه نمط في بعض الظروف التي يمكن أن تكون إما تقصير أو نسخة مع أي سلوك.المفتاح هو تجنب null الشيكات في جميع أنحاء رمز قاعدة.انظر هنا لمزيد من المعلومات http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

في بعض الوظائف إضافة معلمة:

..., bool verify = true)

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

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

في C++, أستطيع أن أفكر 3 نكهات مختلفة من إعداد الأسلوب الذي يجد كائن.

الخيار

Object *findObject(Key &key);

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

الخيار ب

void findObject(Key &key, Object &found);

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

الخيار ج

bool findObject(Key &key, Object &found);

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

if (!findObject(myKey, myObj)) { ...

مشيرا فقط إلى الحالة التي يكون فيها لاغية لا يعتبر استثنائيا سلوك أنا بالتأكيد في محاولة طريقة, فمن الواضح, لا تحتاج إلى "قراءة كتاب" أو "انظر قبل أن تقفز" كما قيل هنا

وذلك أساسا:

bool TryFindObject(RequestParam request, out ResponseParam response)

وهذا يعني أن المستخدم رمز سوف تكون أيضا واضحة

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...

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

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

أو العودة خيارا

الخيار هو في الأساس الطبقة الحاوية أن قوات العميل للتعامل مع الحالات كشك.ميلان لديه هذا المفهوم ، تبدو انها API.

ثم لديك أساليب مثل T getOrElse(T valueIfNull) على هذا الكائن ثيت إما العودة الكائن وجدت ، أو allternative العميل specifieces.

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

طالما أنه من المفترض أن يعود المرجعية إلى كائن إرجاع NULL يجب أن تكون جيدة.

ومع ذلك ، إذا كانت تعود كل شئ (مثل C++ إذا كنت تفعل:عودة بلاه;' بدلا من 'عودة &بلاه;' (أو 'blah' هو مؤشر), ثم لا يمكنك إرجاع NULL, لأنه ليس من نوع 'الكائن'.في هذه الحالة رمي استثناء ، أو إرجاع كائن فارغ لا يكون علامة نجاح المجموعة هو كيف يمكنني معالجة المشكلة.

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

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

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

إرجاع null, الاستثناءات هي بالضبط:شيء التعليمات البرمجية الخاصة بك لا ليس من المتوقع.

الاستثناءات يجب أن يكون استثنائية.العودة فارغة إذا كان صحيحا أن تعود فارغة.

تفضل العودة فارغة --

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

إذا كان الطالب لا تستخدم حقا لا ضريبة عليه try/catch كتلة

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

إذا كان الأسلوب retrives كائن واحد ، ثم لديك بعض الخيارات.

  1. إذا كان الأسلوب يجب أن تجد دائما نتيجة حقيقية استثناء حالة عدم العثور على الكائن, ثم يجب عليك رمي استثناء (في جاوة:يرجى وهي لحالها استثناء)
  2. (جافا فقط) إذا كنت يمكن أن يتسامح مع هذا الأسلوب يلقي فحص استثناء ، رمي المشروع محددة ObjectNotFoundException أو ما شابه ذلك.في هذه الحالة المترجم يقول لك إذا كنت تنسى أن التعامل مع الاستثناء.(هذا هو بلدي المفضل في التعامل مع لم يتم العثور على الأشياء في جاوة.)
  3. اذا كنت تقول انها حقا حسنا, إذا لم يتم العثور على الكائن و الأسلوب الخاص بك اسم هو مثل findBookForAuthorOrReturnNull(..), ثم يمكنك العودة فارغة.في هذه الحالة هو بقوة recomminded إلى استخدام نوع من الاختيار الثابتة أو مترجم الشيك اللي تبونه يمنع dereferencing النتيجة دون فارغة الاختيار.في حالة جافا يمكن أن تكون على سبيل المثال.FindBugs (انظر DefaultAnnotation في http://findbugs.sourceforge.net/manual/annotations.html) أو IntelliJ-التحقق.

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

إذا كنت تستخدم مكتبة أو فئة أخرى مما يطرح استثناء ، يجب أن rethrow ذلك.هنا هو مثال على ذلك.Example2.java مثل المكتبة ، Example.java يستخدم هذا الكائن.Main.java مثال للتعامل مع هذا الاستثناء.يجب أن تظهر رسالة ذات مغزى و (إذا لزم الأمر) تتبع المكدس المستخدم في الدعوة الجانب.

Main.java

public class Main {
public static void main(String[] args) {
    Example example = new Example();

    try {
        Example2 obj = example.doExample();

        if(obj == null){
            System.out.println("Hey object is null!");
        }
    } catch (Exception e) {
        System.out.println("Congratulations, you caught the exception!");
        System.out.println("Here is stack trace:");
        e.printStackTrace();
    }
}
}

Example.java

/**
 * Example.java
 * @author Seval
 * @date 10/22/2014
 */
public class Example {
    /**
     * Returns Example2 object
     * If there is no Example2 object, throws exception
     * 
     * @return obj Example2
     * @throws Exception
     */
    public Example2 doExample() throws Exception {
        try {
            // Get the object
            Example2 obj = new Example2();

            return obj;

        } catch (Exception e) {
            // Log the exception and rethrow
            // Log.logException(e);
            throw e;
        }

    }
}

Example2.java

 /**
 * Example2.java
 * @author Seval
 *
 */
public class Example2 {
    /**
     * Constructor of Example2
     * @throws Exception
     */
    public Example2() throws Exception{
        throw new Exception("Please set the \"obj\"");
    }

}

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

  • وجوه ؛ عودة وجوه
  • كائن لا وجدت ؛ رمي استثناء

وإلا العودة فارغة.

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