2008-09-16 14 views
5

मैं इस तकनीक के बारे में कुछ प्रतिक्रिया प्राप्त करने में दिलचस्पी लेता हूं जिसे मैंने कहीं से उठाया था।सफलता/विफलता को इंगित करने के लिए एकाधिक वापसी मान।

जब मैं कोई फ़ंक्शन सफल या विफल हो सकता हूं, तो मैं इसका उपयोग करता हूं, लेकिन आप यह विफल होने के बारे में अधिक जानकारी प्राप्त करना चाहते हैं। इस काम को करने का एक मानक तरीका अपवाद हैंडलिंग के साथ होगा, लेकिन मुझे अक्सर इस तरह की चीज के लिए शीर्ष पर थोड़ा सा लगता है, साथ ही PHP4 यह पेशकश नहीं करता है।

असल में तकनीक सफलता के लिए सच लौटने शामिल है, और कुछ जो विफलता के लिए गलत पर बराबर है। यहाँ दिखाने के लिए मैं क्या मतलब है एक उदाहरण है:

define ('DUPLICATE_USERNAME', false); 
define ('DATABASE_ERROR', 0); 
define ('INSUFFICIENT_DETAILS', 0.0); 
define ('OK', true); 

function createUser($username) { 
    // create the user and return the appropriate constant from the above 
} 

इस की सुंदरता है कि आपके फोन कर कोड में, अगर आप परवाह नहीं है क्यों उपयोगकर्ता निर्माण में असफल, आप सरल और पठनीय कोड लिख सकते हैं:

if (createUser('fred')) { 
    // yay, it worked! 
} else { 
    // aww, it didn't work. 
} 

आप विशेष रूप से कारण है कि यह काम नहीं किया (उपयोगकर्ता के लिए, प्रवेश के लिए प्रदर्शन, या जो कुछ भी करते हैं) की जांच करना चाहते हैं, तो ===

$status = createUser('fred'); 
if ($status) { 
    // yay, it worked! 
} else if ($status === DUPLICATE_USERNAME) { 
    // tell the user about it and get them to try again. 
} else { 
    // aww, it didn't work. log it and show a generic error message? whatever. 
} 

तरह से मैं इसे देख के साथ पहचान तुलना उपयोग करते हैं, इसके लाभ टी हैं टोपी यह एक सामान्य उम्मीद है कि इस तरह के एक समारोह का सफल निष्पादन सच हो जाएगा, और विफलता झूठी वापसी होगी।

नकारात्मकता यह है कि आप केवल 7 "error" return values: false, 0, 0.0, "0", null, "", and (object) null. कर सकते हैं यदि आप पहचान जांच का उपयोग करना भूल जाते हैं तो आप अपना प्रोग्राम प्रवाह गलत कर सकते हैं। किसी और ने मुझे बताया है कि enum जैसे स्थिरांक का उपयोग करना जहां वे सभी झूठी समतुल्य हैं "ick" है।


तो, प्रश्न को पुन: स्थापित करने के लिए: इस तरह का अभ्यास कितना स्वीकार्य है? क्या आप एक ही चीज़ को हासिल करने के लिए एक अलग तरीके की सिफारिश करेंगे?

उत्तर

13

मैं उन लोगों से सहमत हूं जिन्होंने कहा है कि यह डब्ल्यूटीएफ पक्ष पर थोड़ा सा है। यदि यह स्पष्ट रूप से दस्तावेज़ीकृत कार्यक्षमता है, तो यह एक समस्या से कम है, लेकिन मुझे लगता है कि त्रुटि कोड के लिए सफलता और पूर्णांक के लिए 0 लौटने का वैकल्पिक मार्ग सुरक्षित होना सुरक्षित होगा।

function createUser($username, &$error) 

तो आप उपयोग कर सकते: आपको लगता है कि विचार या एक वैश्विक पिछले त्रुटि चर का विचार पसंद नहीं करते हैं, के रूप में अपने कार्य को फिर से परिभाषित करने पर विचार

if (createUser('fred', $error)) { 
    echo 'success'; 
} 
else { 
    echo $error; 
} 

अंदर CreateUser, सिर्फ $ त्रुटि पॉप्युलेट किसी भी त्रुटि के साथ आप सामना करते हैं और यह संदर्भ के कारण फ़ंक्शन स्कोप के बाहर पहुंच योग्य होगा।

+0

अच्छी युक्ति - थोड़े सभी मानदंडों को पूरा करता है, वास्तव में - जब तक यह दूसरा पैरामीटर (?) – nickf

+0

की आपूर्ति नहीं करता है, तो PHP 4 में डिफ़ॉल्ट मान असाइन किए जाते हैं संदर्भ द्वारा पारित चर के लिए समर्थित नहीं था, इसलिए मुझे लगता है कि इसे कॉल करते समय आपको हमेशा $ त्रुटि चर की आपूर्ति करना होगा। –

+0

बमर। एक चीज जो मैं वास्तव में उम्मीद कर रहा था वह अतिरिक्त कोड से बचने के लिए था जब मुझे विफलता के कारण की परवाह नहीं थी। शायद मैं इस सपने पर बहुत ज्यादा चिपक रहा हूं। – nickf

2

जब तक यह दस्तावेज और अनुबंधित होता है, और WTFy भी नहीं, तो कोई समस्या नहीं होनी चाहिए।

फिर फिर, मैं इस तरह के कुछ के लिए अपवादों का उपयोग करने की सिफारिश करता हूं। यह और अधिक समझ में आता है। यदि आप PHP5 का उपयोग कर सकते हैं, तो यह जाने का तरीका होगा। अन्यथा आपके पास ज्यादा विकल्प नहीं है।

2

अपवाद उपलब्ध नहीं होने पर मैंने देखा है कि एक और आम दृष्टिकोण है कि त्रुटि प्रकार को 'last_error' चर में कहीं भी संग्रहीत करना है और फिर जब विफलता होती है (यानी यह झूठी होती है) त्रुटि को देखो।

एक और तरीका आदरणीय यूनिक्स उपकरण दृष्टिकोण संख्याबद्ध त्रुटि कोड का उपयोग करना है - विभिन्न त्रुटि स्थितियों के लिए सफलता और किसी भी पूर्णांक (जो कुछ त्रुटि के लिए मानचित्र) के लिए 0 लौटाएं।

इनमें से अधिकतर अपवादों की तुलना में पीड़ित हैं जब मैंने उन्हें देखा है।

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

+0

वैश्विक के माध्यम से एक त्रुटि लौटने से किसी भी तरह के बहुप्रचारित वातावरण में कोई अच्छा विचार नहीं है। लौटने वाले जादू संख्याएं कैली कोड को पढ़ने में मुश्किल बनाती हैं और त्रुटि के लिए प्रवण होती हैं। यदि आप अपवादों का उपयोग नहीं कर सकते हैं, कम से कम उतना स्पष्ट हो जितना आप कर सकते हैं। विभिन्न त्रुटि स्थितियों के लिए –

+0

@mmaibaum> सफलता के लिए 0 और किसी भी पूर्णांक (जो कुछ त्रुटि के लिए मानचित्र) के लिए वापसी करें। हाँ, मैंने इसे माना था, लेकिन इसका मतलब यह है कि यदि आप इसे अपने कोड में देख सकते हैं: यदि (! CreateUser ('fred')) {// यह काम किया ...} ऐसा लगता है कि मेरे लिए कुछ हद तक अंतर्ज्ञानी है। मुझे नहीं पता कि यह सिर्फ इतना है कि मैं इसका उपयोग नहीं कर रहा हूं। – nickf

2

अक्सर आप विफलताओं को इंगित करने के लिए 0, और 1, 2, 3 इत्यादि को अलग-अलग असफलताओं को इंगित करने के लिए वापस कर देंगे।ऐसा करने का आपका तरीका हैकिश की तरह है, क्योंकि आपके पास केवल इतनी सारी त्रुटियां हो सकती हैं, और इस तरह के कोडिंग आपको जल्दी या बाद में काट देगा।

मुझे एक संरचना/ऑब्जेक्ट को परिभाषित करना पसंद है जिसमें सफलता का संकेत देने के लिए एक बूलियन शामिल है, और एक त्रुटि संदेश या अन्य मान इंगित करता है कि किस प्रकार की त्रुटि हुई। आप अन्य क्षेत्रों को भी शामिल कर सकते हैं यह इंगित करने के लिए कि किस प्रकार की कार्रवाई निष्पादित की गई थी।

यह लॉगिंग बहुत आसान बनाता है, क्योंकि आप केवल स्थिति-संरचना को लॉगर में पास कर सकते हैं, और फिर उचित लॉग प्रविष्टि डालेंगे।

-1

मेरी राय में, आपको केवल इस तकनीक का उपयोग करना चाहिए यदि विफलता आपकी विधि/कार्य के "ऑपरेशन का सामान्य हिस्सा" है। उदाहरण के लिए, यह संभव है कि कॉल विफल हो जाए क्योंकि यह विफल हो जाता है। यदि विफलता एक असाधारण घटना है, तो आपको अपवाद हैंडलिंग का उपयोग करना चाहिए ताकि आपका प्रोग्राम यथासंभव जल्दी और सुन्दर तरीके से समाप्त हो सके।

विभिन्न "झूठे" मानों के उपयोग के लिए, मैं एक उचित त्रुटि कोड के साथ एक कस्टम "परिणाम" -class का एक उदाहरण वापस बेहतर कर दूंगा। कुछ ऐसा:

class Result 
{ 
    var $_result; 
    var $_errormsg; 

    function Result($res, $error) 
    { 
     $this->_result = $res; 
     $ths->_errorMsg = $error 
    } 

    function getResult() 
    { 
     return $this->_result; 
    } 

    function isError() 
    { 
     return ! ((boolean) $this->_result); 
    } 

    function getErrorMessage() 
    { 
     return $this->_errorMsg; 
    } 
+0

यह वस्तुओं के लिए मेरे लिए ओवरकिल और ऑब्जेक्ट्स चिल्लाता है, मेरे लिए। यदि आप वास्तव में परिणाम/त्रुटि बंडल करना चाहते हैं तो क्यों न केवल एक सरणी वापस करें? –

+0

अच्छी तरह से, मैं तकनीक का उपयोग करने के कारणों में से एक कारण यह है कि यह बहुत आसान है, के विपरीत ... :) लेकिन प्रयास के लिए धन्यवाद! – nickf

0

आईक।

यूनिक्स प्री-अपवाद में यह errno के साथ किया जाता है। आप सफलता के लिए 0 या विफलता के लिए -1 लौटते हैं, तो आपके पास एक त्रुटि है जिसे आप वास्तविक त्रुटि प्राप्त करने के लिए एक पूर्णांक त्रुटि कोड से पुनर्प्राप्त कर सकते हैं। यह सभी मामलों में काम करता है, क्योंकि आपके पास त्रुटि कोड की संख्या (यथार्थवादी) सीमा नहीं है। INT_MAX निश्चित रूप से 7 से अधिक है, और आपको इस प्रकार (errno) के बारे में चिंता करने की ज़रूरत नहीं है।

मैं इस प्रश्न में प्रस्तावित समाधान के खिलाफ वोट देता हूं।

-2

इसे करने के लिए सही तरीके से COM HRESULT को देखें।

लेकिन अपवाद आमतौर पर बेहतर होते हैं।

अद्यतन: सही तरीका यह है: जितना चाहें उतने त्रुटि मान परिभाषित करें, न केवल "झूठे" वाले। फ़ंक्शन सफल होने पर जांचने के लिए फ़ंक्शन का उपयोग करें() सफल हुआ।

if (succeeded(result = MyFunction())) 
    ... 
else 
    ... 
+0

http://en.wikipedia.org/wiki/HRESULT – GEOCHET

0

यदि आप वास्तव में इस तरह की चीज करना चाहते हैं, तो आपके पास प्रत्येक त्रुटि के लिए अलग-अलग मान होना चाहिए, और सफलता की जांच करें।

define ('OK', 0); 
define ('DUPLICATE_USERNAME', 1); 
define ('DATABASE_ERROR', 2); 
define ('INSUFFICIENT_DETAILS', 3); 

और जाँच की तरह कुछ:

if (createUser('fred') == OK) { 
    //OK 

} 
else { 
    //Fail 
} 
0

यह है कि एक सफल निष्पादन सच रिटर्न मतलब है।सामान्य त्रुटियों से निपटने बहुत आसान हो जाएगा:

if (!createUser($username)) { 
// the dingo ate my user. 
// deal with it. 
} 

लेकिन यह बिल्कुल मतलब नहीं है झूठे के विभिन्न प्रकार के साथ संबद्ध करने के लिए जिसका अर्थ है। झूठी का मतलब केवल एक चीज और एक चीज होना चाहिए, इस पर ध्यान दिए बिना कि प्रोग्रामिंग भाषा इसका कैसे व्यवहार करती है या नहीं। आप त्रुटि स्थिति स्थिरांक वैसे भी, स्विच/मामले

define(DUPLICATE_USERNAME, 4) 
define(USERNAME_NOT_ALPHANUM, 8) 

switch ($status) { 
case DUPLICATE_USERNAME: 
    // sorry hun, there's someone else 
    break; 
case USERNAME_NOT_ALPHANUM: 
    break; 
default: 
    // yay, it worked 
} 

इसके अलावा इस तकनीक के साथ साथ बेहतर छड़ी को परिभाषित करने के लिए जा रहे हैं, तो आप बिटवाइज़ करने में सक्षम AND और OR स्थिति संदेश, हो जाएगा तो आप स्थिति संदेश लौट सकते हैं कि DUPLICATE_USERNAME & USERNAME_NOT_ALPHANUM जैसे एक से अधिक अर्थ ले जाएं और उचित तरीके से इसका इलाज करें। यह हमेशा एक अच्छा विचार नहीं है, यह इस बात पर निर्भर करता है कि आप इसका उपयोग कैसे करते हैं।

+0

का उपयोग कर सकते हैं मैं उलझन में हूं। यदि createUser DUPLICATE_USERNAME (4) देता है, तो आपका पहला कोड नमूना "इसके साथ सौदा" भाग निष्पादित नहीं करेगा। – nickf

2

इस तरह का अभ्यास कितना स्वीकार्य है?

मैं कहूंगा कि यह अस्वीकार्य है।

  1. === ऑपरेटर की आवश्यकता है, जो बहुत खतरनाक है। यदि उपयोगकर्ता == का उपयोग करता है, तो यह बग खोजने के लिए बहुत कठिन होता है।
  2. झूठ को इंगित करने के लिए "0" और "" का प्रयोग भविष्य के PHP संस्करणों में बदल सकता है। प्लस अन्य भाषाओं का एक बहुत में "0" और "" झूठे जो महान भ्रम होता है के रूप में मूल्यांकित नहीं है

का उपयोग GetLastError() वैश्विक समारोह के प्रकार शायद PHP में सबसे अच्छा अभ्यास है, क्योंकि यह अच्छी तरह से में संबंधों भाषा के साथ, क्योंकि PHP अब भी एक प्रक्रियात्मक लैंगेज है। मुझे लगता है कि आपके द्वारा दिए गए दृष्टिकोण के साथ एक और समस्या यह है कि बहुत कम अन्य सिस्टम इस तरह काम करते हैं। प्रोग्रामर को त्रुटि जांच का यह तरीका सीखना है जो त्रुटियों का स्रोत है। चीज़ों को काम करना सबसे अच्छा है जैसे कि अधिकांश लोग अपेक्षा करते हैं।

if (makeClient()) 
{ // happy scenario goes here } 

else 
{ 
    // error handling all goes inside this block 
    switch (getMakeClientError()) 
    { case: // .. } 
} 
+0

यह PHP में कार्यों के लिए अभूतपूर्व नहीं है ===। स्ट्रॉप्स() पर देखो। – nickf

+0

"=== ऑपरेटर की आवश्यकता है, जो बहुत खतरनाक है। यदि उपयोगकर्ता == का उपयोग करता है, तो यह बग खोजने के लिए बहुत कठिन होता है।" असल में, इसके विपरीत यह '==' के साथ कृपापूर्वक विफल रहता है। इस विधि का लाभ यह है कि आप बस कर सकते हैं! MakeClient() यह देखने के लिए कि यह सफल था या नहीं। – Lewis

1

जब अपवाद उपलब्ध नहीं हैं, मैं PEAR मॉडल का उपयोग करें और अपने सभी वर्गों में ISERROR() कार्यक्षमता उपलब्ध कराएंगे।

0

मुझे पसंद है कि COM दोनों अपवाद और अपवाद अक्षम कॉलर्स को संभाल सकता है। नीचे दिया गया उदाहरण दिखाता है कि कैसे HRESULT का परीक्षण किया जाता है और विफलता के मामले में एक अपवाद फेंक दिया जाता है। (आमतौर पर tli फाइलों में ऑटोजनरेटेड)

inline _bstr_t IMyClass::GetName () { 
    BSTR _result; 
    HRESULT _hr = get_name(&_result); 
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); 
    return _bstr_t(_result, false); 
} 

वापसी मानों का उपयोग करना निपटने बिखरे हुए त्रुटि और सबसे खराब स्थिति होने से पठनीयता को प्रभावित करेगा, वापसी मान कोड द्वारा जाँच की कभी नहीं कर रहे हैं। यही कारण है कि जब अनुबंध का उल्लंघन होता है तो मैं अपवाद पसंद करता हूं।

throw new Validation_Exception_SQLDuplicate("There's someone else, hun");), 

लौटने संरचनाओं,

return new Result($status, $stuff); 
if ($result->status == 0) { 
    $stuff = $result->data; 
} 
else { 
    die('Oh hell'); 
} 

मैं जो व्यक्ति कोड पैटर्न आप मूल रूप से सुझाव दिया उपयोग करने के लिए के बाद आया हो नहीं चाहते:

0

अन्य तरीके अपवादों में शामिल हैं।

और मेरा मतलब है "आपके बाद आया" जैसा कि "रोजगार में आपका पीछा किया गया था और" आपके बाद आया "के बजाय" कोड के बाद "कोड बनाए रखना था, हालांकि दोनों विकल्प हैं।

1

यहां पहिया को पुनर्निर्मित करना। वर्गों का उपयोग करना

ठीक है, आप वर्ष 1982 में में PHP 4 में आपका स्वागत है अपवाद नहीं है, सी

पर एक नज़र आप त्रुटि कोड हो सकता है ले लो। नकारात्मक मूल्यों पर विचार करें, वे अधिक सहज महसूस करते हैं, इसलिए आपको केवल यह जांचना होगा कि (createUser()> 0)।

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

लेकिन PHP एक कारण के लिए एक ढीली टाइप की गई भाषा है, और विभिन्न प्रकार के त्रुटि कोड फेंक रहा है लेकिन उसी "झूठी" का मूल्यांकन करना ऐसा कुछ नहीं है जो नहीं किया जाना चाहिए।

जब आप अंतर्निहित प्रकार से बाहर निकलते हैं तो क्या होता है?

क्या होता है जब आपको कोई नया कोडर मिलता है और यह समझाना होता है कि यह चीज़ कैसे काम करती है? कहो, 6 महीने में, आपको याद नहीं होगा।

क्या PHP === ऑपरेटर इसके माध्यम से प्राप्त करने के लिए पर्याप्त तेज़ है? क्या यह त्रुटि कोड से तेज़ है? या कोई अन्य विधि?

बस इसे छोड़ दें।

+0

ऐसा नहीं है कि मैंने इसे स्वयं परीक्षण किया है, लेकिन === शायद == से भी तेज होना चाहिए, क्योंकि ऐसा कोई मौका नहीं है कि उसे कोई कास्टिंग करना पड़ेगा। मैं इसे कैसे समझाऊंगा? ... इसे दस्तावेज? – nickf

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