2013-02-22 15 views
5

अमरूद पूर्व शर्त जांचने के लिए सहायक कार्यों की पेशकश करता है लेकिन मुझे मध्यवर्ती परिणामों की जांच करने के लिए सहायक कार्यों को नहीं मिला।क्या मुझे मध्यवर्ती परिणामों की जांच करने के लिए पूर्व शर्त जांच का उपयोग करना चाहिए?

private void foo(String param) 
{ 
    checkNotNull(param, "Required parameter is not set"); 

    int x = get(param); 
    if (x == -1) { 
     throw new RuntimeException("This should never have happened and indicates a bug."); 
    } 
} 
  • मैं अपने खुद के सहायक में if (...) {....} हिस्सा लपेट कर देना चाहिए?
  • या मुझे गुवा से checkState का उपयोग करना चाहिए?
  • या मुझे get() की param के परिणामस्वरूप विफलता देखना चाहिए और checkArgument का उपयोग करना चाहिए?
  • क्या मुझे इन मामलों में आवेषण का उपयोग करना चाहिए?
  • या क्या मुझे कुछ याद आ रहा है?

आपके विचार के लिए धन्यवाद।

+1

तरीका है अपने कोड डेटा की जाँच करता है काफी वैध है, लेकिन आप 'RuntimeException' तुलना में एक अधिक 'ठोस' अपवाद का उपयोग करना चाहें - शायद' IllegalStateException', या अपनी खुद की। – vikingsteve

+2

आमतौर पर, * * "यह कभी नहीं हुआ होना चाहिए" * अपवाद एक RuntimeException की बजाय एक AssertionError होना चाहिए। जोर का उपयोग करना थोड़ा नाजुक है क्योंकि यह JVM तर्कों पर निर्भर करता है ... इसके अलावा आपका कोड मुझे ठीक लग रहा है। – assylias

+1

ऐसा लगता है कि हो रही -1 तर्क के साथ काम करने का एक परिणाम के रूप में एक वैध 'IllegalArgumentException' है, इसलिए मैं का प्रयोग करेंगे' checkArgument (एक्स - -1, "मेरा संदेश") '' –

उत्तर

7

यह वरीयता और सम्मेलन के मामले के बीच कहीं है।

आम तौर पर, लोग प्रोग्रामिंग त्रुटियों को इंगित करने के लिए आवेषण का उपयोग करेंगे; यही है, "अगर मैंने अपना काम सही किया, तो एक गैर-शून्य paramकभी परिणामस्वरूप उपयोगकर्ता इनपुट या अन्य बाहरी ताकतों के बावजूद get से -1 में परिणाम होगा।" मैं उन्हें लगभग टिप्पणियों के रूप में मानता हूं जो वैकल्पिक रूप से रनटाइम पर सत्यापित किए जा सकते हैं।

दूसरी ओर, यदि get वापस कर सकती है -1 कुछ मामलों में, लेकिन यह है कि इनपुट अमान्य है, तो मैं आम तौर पर एक IllegalArgumentException फेंक होता है, और checkArgument यह करने के लिए एक पूरी तरह से उचित तरीका है। इसका एक दोष यह है कि जब आप बाद में इसे पकड़ते हैं, तो यह कहीं भी कहीं से भी आ सकता था। पर विचार करें:

try { 
    baz(); 
    bar(); 
    foo(myInput); 
} catch (IllegalArgumentException e) { 
    // Where did this come from!? 
    // It could have come from foo(myInput), or baz(), or bar(), 
    // or some method that any of them invoked, or really anywhere 
    // in that stack. 
    // It could be something totally unrelated to user input, just 
    // a bug somewhere in my code. 
    // Handle it somehow... 
} 

मामलों में जहां कि मामलों में - उदाहरण के लिए, आप उपयोगकर्ता है कि वे अपने इनपुट के रूप में -1 प्रवेश करने की अनुमति नहीं कर रहे हैं करने के लिए एक उपयोगी टिप्पणी पॉप अप करना चाहते हैं - आप फेंक कर सकते हैं एक कस्टम अपवाद है, ताकि आप और अधिक आसानी से इसे बाद में पकड़ कर सकते हैं:

try { 
    baz(); 
    bar(); 
    foo(myInput); 
} catch (BadUserInputException e) { 
    reportError("Bad input: " + e.getMessage()); 
    log.info("recorded bad user input", e); 
} 

checkState का सवाल है, यह वास्तव में मेरे लिए सही नहीं लग रहा। उस अपवाद का आमतौर पर तात्पर्य है कि समस्या यह थी कि this (या एप्लिकेशन में कुछ अन्य, अधिक वैश्विक स्थिति) में था। the docs से:

सिग्नल कि एक विधि अवैध या अनुचित समय पर लागू की गई है।

आपके मामले में, -1 -1 कभी भी उपयुक्त नहीं है, इसलिए checkState भ्रामक है।अब, अगर यह किया गया था:

if (x == -1 && (!allowNegativeOne()) { ... } 

... तो यह है कि अधिक उपयुक्त, होगा, हालांकि यह अभी भी दोष यह है कि IllegalArgumentException ऊपर था है।

तो, आखिरकार, इस सवाल का सवाल है कि आपको if रखना चाहिए या एक सहायक विधि का उपयोग करना चाहिए। यह वास्तव में स्वाद के लिए आता है, चेक कितना जटिल है, और कितनी बार इसका उपयोग किया जाता है (उदाहरण के लिए अन्य तरीकों में)। यदि चेक x == -1 जितना आसान है और यह जांच कभी भी अन्य तरीकों से नहीं की जाती है (इसलिए कोड पुन: उपयोग कोई मुद्दा नहीं है), तो मैं केवल if रखूंगा।

2

यदि get विधि स्ट्रिंग को एक int में परिवर्तित कर रही है, तो उसे वहां वैधता करना चाहिए, अधिमानतः एक अवैध आर्ग्यूमेंट अपवाद या कुछ ऐसे रनटाइम अपवाद को फेंकना चाहिए। उपरोक्त के साथ आप अपनी विधि में अमूर्तता के स्तर भी मिश्रण कर रहे हैं। जैसे आपके checkNotNull शून्य के लिए param की जांच को हटा देता है, लेकिन param के लिए एक int के रूप में जांच get विधि और foo विधि पर विभाजित है। एक चेकपेकंडिशन प्रकार विधि क्यों नहीं है? जैसे

private void paramShouldBeNonNullInt(String value) { 
    if (value == null) throw new IllegalArgumentException("value was null"); 
    try { 
     Integer.parseInt(value) 
    } catch (NumberFormatException e) { 
     throw new IllegalArgumentException("value was not an integer"); 
    } 
} 
+0

get' सिर्फ एक उदाहरण है, कृपया इसे अर्थशास्त्र को अनदेखा करें, 'चेक नॉटनुल' भी एक उदाहरण के रूप में है कि मैं 'अगर (...)' भाग को दिखाना चाहता हूं, संक्षेप में मुझे बस 'चेकऑर थ्रो रनटाइम()' फ़ंक्शन या ' चेकस्टेट 'मैं वास्तव में चाहता हूं। –

2

सबसे पहले आपको अनुबंधों (जैसे दावे/प्रोग्रामिंग त्रुटियों) और त्रुटि प्रबंधन (जैसे पुनर्प्राप्ति योग्य अपवाद जो पकड़ा जा सकता है और उसे पुनर्प्राप्त किया जाना चाहिए) के बीच एक अंतर बनाने की आवश्यकता है।

यदि आपको मध्यवर्ती परिणाम की जांच करने की आवश्यकता है, तो ऐसा लगता है कि आप आमंत्रित सेवा पर भरोसा नहीं करते हैं और आप यह सुनिश्चित करना चाहते हैं कि आपकी धारणाएं हों। सही? इसे एक दावे के रूप में व्यक्त किया जाना चाहिए, और इसके लिए अमरूद का बहुत अच्छा समर्थन नहीं है।

valid4j पर एक नज़र डालें। यहां मिला https://github.com/helsing/valid4j और यहां http://www.valid4j.org

private int getFoo(String param) { 
    require(param, notNullValue()); // Violation means programming error at client 

    int x = get(param); 

    ensure(x, not(equalTo(-1)); // Violation means programming error at supplier 
    return x; 
} 
0

कुछ अन्य उत्कृष्ट जवाब यहां:

मैं तो इस तरह कोड (hamcrest-matchers के लिए valid4j के समर्थन का उपयोग करके) व्यक्त होता।

पूर्व शर्त javadoc से

:

पूर्वशर्त अपवाद संकेत देने के लिए कि विधि एक त्रुटि बना दिया है बुला उपयोग किया जाता है। (...) पोस्टकंडिशन या अन्य आविष्कार विफलताओं को इन प्रकार के अपवादों को फेंकना नहीं चाहिए।

तो ...

मैं लपेट चाहिए अगर (...) {....} मेरे अपने सहायक में भाग?

नहीं, मौजूदा सुविधाएं पर्याप्त अच्छी होनी चाहिए।

या मुझे गुवा से चेकस्टेट का उपयोग करना चाहिए?

हां संभवतः: यदि इस विधि को कॉल करने से पहले किसी फ़ाइल से पैरामीटर लोड किए जाने की आवश्यकता है, तो यह इस वर्ग का उपयोग कैसे किया जाना चाहिए इसके अनुबंध का हिस्सा होगा।

या मुझे पर्म के परिणामस्वरूप प्राप्त() की विफलता को देखना चाहिए और चेकआर्गमेंट का उपयोग करना चाहिए?

हाँ संभवतः: उदा। अगर पैरामीटर के सिंटैक्स पर कुछ स्वरूपण प्रतिबंध था। (हालांकि शायद कि get() अंदर जाना होगा)

मैं का उपयोग करना चाहिए इन मामलों में इस बात पर ज़ोर?

हां। यदि यह उपरोक्त की तरह पूर्व शर्त जांच नहीं है, तो सामान्यतः मैं यहां assert का उपयोग करूंगा। मत भूलना भी आपको संदेश जोड़ सकते हैं:

assert x != 1 : "Indicates a bug."; 

मैं उम्मीदों दस्तावेज़ और एक वर्ग या विधि के आंतरिक/निजी क्रियान्वयन को सत्यापित करने के लिए इस उपयुक्त पाते हैं।

आपको लगता है कि एक क्रम की जांच, आप कर सकता है if (...) throw AssertionError बनाना चाहते, लेकिन वह शायद ही आवश्यक है यदि आप कुशल कोड है कि आप विश्वास नहीं करते हैं के साथ काम कर रहे हैं।

संबंधित मुद्दे