2009-08-13 14 views
10

पर विचार के लिए निम्न विधि हस्ताक्षर:क्या यह अच्छी सी # शैली है?

  • डेटाबेस तक पहुँचता पोल वस्तुओं की एक सूची उत्पन्न करने के लिए:

    public static bool TryGetPolls(out List<Poll> polls, out string errorMessage) 
    

    इस विधि निम्न प्रदर्शन करती है।

  • सफलता और त्रुटि होने पर सत्य लौटाता है मैसेज एक खाली स्ट्रिंग होगी
  • गलत नहीं होता है अगर यह सफल नहीं होता है और त्रुटि संदेश में एक अपवाद संदेश होगा।

क्या यह अच्छी शैली है?

अद्यतन: चलें मैं निम्नलिखित विधि हस्ताक्षर का उपयोग कर कहते हैं:

public static List<Poll> GetPolls() 

और उस विधि में, यह किसी भी अपवाद को पकड़ने नहीं करता है (तो मैं फोन करने वाले निर्भर अपवाद को पकड़ने के लिए)। मैं उस विधि के दायरे में मौजूद सभी ऑब्जेक्ट्स का निपटान और बंद कैसे करूं? जैसे ही एक अपवाद फेंक दिया जाता है, कोड जो ऑब्जेक्ट को बंद और डिस्प्ले करता है, अब तक पहुंच योग्य नहीं है।

  1. प्राप्त और
  2. वापसी एक बूलियन मान का संकेत सफलता
  3. वापसी एक त्रुटि संदेश

है यही कारण है कि चुनाव की एक सूची प्रदान:

+1

कोड प्रारूपित करने के लिए, इससे पहले चार रिक्त स्थान जोड़ें। सबसे आसान तरीका है कि अपना कोड टाइप/कॉपी करें, इसे हाइलाइट करें, और संपादक में "कोड" बटन पर क्लिक करें। –

उत्तर

43

विधि तीन अलग अलग काम करने की कोशिश कर रहा है यही कारण है कि एक डिजाइन दृष्टिकोण से सुंदर गन्दा।

एक बेहतर दृष्टिकोण बस घोषित करने के लिए होगा:

public static List<Poll> GetPolls() 

तो इस विधि एक Exception फेंक कुछ भी गलत हो जाता है, तो चलो।

+3

TryGetPolls होने के कारण उपयोगी हो सकता है अगर यह वैध रूप से कुछ भी वापस नहीं कर सकता है। एक साफ समाधान के लिए – Michael

+0

+1 –

+4

@ माइकल: "कोशिश करें ..." विधियां विशिष्ट मामलों में अच्छी हैं जहां कुछ गलत हो सकता है लेकिन आपको परवाह नहीं है (अधिक या कम)। अगर यह वैध रूप से कुछ भी वापस नहीं कर सकता है तो उसे शून्य/कुछ भी वापस नहीं करना चाहिए। – STW

11

मेरा मानना ​​है कि

public static bool TryGetPolls(out List<Poll> polls) 

अधिक उचित होगा। यदि विधि TryGet है तो मेरी प्रारंभिक धारणा होगी कि यह असफल होने की उम्मीद करने का कारण होगा, और यह निर्धारित करने के लिए कॉलर पर है कि आगे क्या करना है। यदि वे कॉलर त्रुटि को संभाल नहीं रहा है, या त्रुटि जानकारी चाहता है, तो मैं उनसे संबंधित Get विधि को कॉल करने की अपेक्षा करूंगा।

+0

यहां तक ​​कि बेहतर, बढ़ी हुई अमूर्तता के लिए एक IList का उपयोग करें। –

7

एक सामान्य नियम के रूप में, मैं नहीं कहूंगा।

कारण मैं नहीं कहता वास्तव में ऐसा नहीं है क्योंकि आप TryGetX कर रहे हैं और पैरामीटर के साथ bool लौट रहे हैं। मुझे लगता है कि यह खराब शैली है क्योंकि आप एक त्रुटि स्ट्रिंग भी लौट रहे हैं।

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

public static bool TryGetPolls(out List<Poll> polls); 
public static List<Poll> GetPolls(); 

इस तरह उपयोगकर्ता क्या उचित है और GetPollsTryGetPolls के मामले में लागू किया जा सकता कर सकते हैं:

इसके बजाय, क्या आप देख रहे हैं तरीकों की एक जोड़ी है। मुझे लगता है कि आपके static नेस संदर्भ में समझ में आता है।

  • एक खाली संग्रह
  • अशक्त

बाहर एकाधिक मापदंडों, मेरे लिए, एक code smell है:

7

लौटने पर विचार करें। विधि केवल एक चीज करना चाहिए।

throw new Exception("Something bad happened"); 
//OR 
throw new SomethingBadHappenedException(); 
+1

+1: ज्ञात मामले के लिए एक कस्टम अपवाद लागू करने पर भी विचार करें जहां यह कुछ शर्तों को विफल कर देगा। –

+0

लेकिन आपको सिस्टम से कुछ और विशिष्ट फेंकना चाहिए। अपवाद जो त्रुटि के प्रकार को अधिक सटीक रूप से फिट करता है। –

+0

धन्यवाद इयान। यह दिशानिर्देश के रूप में अधिक था कि किसी तरह का अपवाद फेंक दिया जाना चाहिए। स्नानघर की दीवार की दीवार से शाब्दिक प्रतिलिपि/पेस्ट होने का मतलब नहीं था। :) –

1

यह क्या त्रुटि संदेश है पर निर्भर करता है:

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

हालांकि, यह हो सकता है कि आप प्रयास के बारे में "मेटा" जानकारी वापस लौटना चाहते हैं, इस मामले में आपको केवल एक विधि कॉल से जानकारी के एक से अधिक टुकड़े वापस करने का एक तरीका चाहिए। उस स्थिति में, मैं एक पोलस्पॉन्स क्लास बनाने का सुझाव देता हूं जिसमें दो गुण होते हैं: सूची < पोल> पोल, और स्ट्रिंग त्रुटि संदेश। फिर अपने विधि एक PollResponse ऑब्जेक्ट प्रदान की है:

class PollResponse 
{ 
    public List<Poll> Polls { get; } 
    public string MetaInformation { get; } 
} 
+0

यह मूल कोड, आईएमएचओ के रूप में गैर-मूर्खतापूर्ण है। Idiomatic C# त्रुटियों की रिपोर्ट करने के लिए अपवादों का उपयोग करता है, न कि उन में त्रुटि संदेश वाले कस्टम ऑब्जेक्ट्स। –

+3

स्कॉट की तकनीक यहां System.Web.HttpResponse के समान हो सकती है, मुझे नहीं लगता कि यह एक अनुचित धारणा है कि पोल ऑब्जेक्ट्स का संग्रह संभालने से पूरी तरह से नई ऑब्जेक्ट हो सकती है जो त्रुटियों, भाषाओं, समाप्ति, उपयोगकर्ता दृश्यता स्तर इत्यादि को संभालती है। –

+0

@ ग्रेग - मुझे लगता है कि यह वास्तव में क्या त्रुटि है नीचे आता है। यहां हर कोई सिर्फ यह मान रहा है कि यह एक कार्यक्रम अपवाद है, लेकिन यह आवश्यक नहीं है। एक कार्यक्रम अपवाद का मतलब है कि निष्पादन जारी नहीं हो सका। एक अपवाद और एक त्रुटि एक ही बात नहीं है। जब कोई उपयोगकर्ता किसी वर्ण को किसी फ़ील्ड में दर्ज करने का प्रयास करता है, तो यह एक त्रुटि है, लेकिन मुझे अपवाद फेंकने की आवश्यकता नहीं है। शायद इस मामले में "त्रुटि" यह है कि मतदान डेटा पुराना है, या शायद परिणाम 100% तक नहीं जोड़ते हैं। मैं "फ़ंक्शन कॉल से दो चीज़ों को कैसे वापस कर सकता हूं" के आधार पर और सोच रहा था? –

0

पर निर्भर करता है, तो एक त्रुटि एक आम घटना है या अगर यह हमें सही मायने में एक अपवाद।

यदि त्रुटियां बेहद दुर्लभ और बुरी हैं तो आप विधि को सिर्फ चुनावों की सूची वापस करने पर विचार करना चाहेंगे और कोई त्रुटि होने पर अपवाद फेंक दें।

यदि कोई त्रुटि ऐसी चीज है जो सामान्य परिचालनों का वास्तविक रूप से सामान्य हिस्सा है, जैसे int.ryryParse विधि में एक पूर्णांक को स्ट्रिंग को कवर करने में त्रुटि की तरह, आपके द्वारा बनाई गई विधि अधिक उपयुक्त होगी।

मुझे लगता है कि पूर्व में शायद आपके लिए सबसे अच्छा मामला है।

+0

मैं आपके सभी तर्कों से सहमत हूं कि दूसरे मामले में, मैं yshuditelu की सलाह का उपयोग करूंगा, नहीं मूल कोड – Brian

+0

मुझे नहीं लगता कि "दुर्लभता" सही अवधारणा है। "असाधारण" अधिक सटीक है। किसी तर्क को एक तर्क के रूप में एक स्ट्रिंग के रूप में स्वीकार करने वाले फ़ंक्शन पर विचार करें। यदि स्ट्रिंग एक संख्या नहीं है, तो यह एक असाधारण मामला है, हालांकि आवश्यक रूप से दुर्लभ नहीं है। –

11

यह निश्चित रूप से सी # लिखने का एक मूर्ख तरीका नहीं है, जिसका अर्थ यह भी होगा कि यह शायद एक अच्छी शैली नहीं है।

जब आपके पास TryGetPolls विधि है तो इसका मतलब है कि यदि ऑपरेशन सफल होता है तो आप परिणाम चाहते हैं, और यदि ऐसा नहीं होता है तो आपको परवाह नहीं है कि यह सफल क्यों नहीं होता है।

जब आपके पास बस GetPolls विधि है तो इसका मतलब है कि आप हमेशा परिणाम चाहते हैं, और यदि यह सफल नहीं होता है तो आप जानना चाहते हैं कि Exception के रूप में क्यों।

दोनों को मिलाकर कहीं बीच में है, जो ज्यादातर लोगों के लिए असामान्य होगा। तो मैं कहूंगा कि या तो त्रुटि संदेश नहीं लौटाता है, या Exception विफलता पर फेंक देता है, लेकिन इस अजीब संकर दृष्टिकोण का उपयोग न करें।

तो अपने विधि हस्ताक्षर शायद होना चाहिए या तो:

IList<Poll> GetPolls(); 

या

bool TryGetPolls(out IList<Poll> polls); 

(ध्यान दें कि मैं भी या तो मामले में एक List<Poll> से एक IList<Poll> लौट रहा हूँ बल्कि, के रूप में यह भी अच्छा है कार्यान्वयन के बजाए एक अमूर्तता के लिए प्रोग्राम करने का अभ्यास करें।)

+0

ग्रेग, यह एक उत्कृष्ट बिंदु है। IList के लिए –

+0

+1 - मुझे भी इसका उल्लेख करना चाहिए था। –

+0

मैं सार्वजनिक एपीआई में विशेष रूप से अगर आपके नियंत्रण में नहीं है तो मैं एब्स्ट्रक्शन के लिए हूं। लेकिन अगर यह एक आंतरिक वर्ग है तो यह संभव है कि आप किसी अन्य चीज़ के साथ .NET ढांचे में सूची कार्यान्वयन को प्रतिस्थापित करेंगे। यदि यह एक इंटरफेस था कि आप पर्याप्त मेला कर सकते हैं, लेकिन नेट सूची वर्ग? केआईएसएस सिद्धांत के बारे में कैसे। – softveda

2

नहीं, मेरे दृष्टिकोण से यह बहुत खराब शैली है। मैं इसे इस तरह लिखूंगा:

public static List<Poll> GetPolls(); 

यदि कॉल विफल हो जाता है, अपवाद फेंक दें और अपवाद में त्रुटि संदेश डालें। यही अपवाद है और आपका कोड बहुत साफ, अधिक पठनीय और बनाए रखने में आसान हो जाएगा।

0

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

डेटाबेस प्रकार के काम के लिए मुझे लगता है कि Exception सबसे अच्छा है।

0

मैं इसे इस तरह से पुन: स्थापित करूंगा।

public static List<Poll> GetPolls() 
{ 
    ... 
} 

यह शायद एक अपवाद (errorMessage) फेंक दिया जाना चाहिए अगर यह चुनाव को पुनः प्राप्त करने में विफल रहता है, के साथ साथ इस विधि श्रृंखलन जो बाहर मानकों के साथ काम की तुलना में कम बोझिल है के लिए अनुमति देता है।

यदि आप FxCop चलाते हैं, तो आप इसे खुश रखने के लिए सूची में IList को बदलना चाहेंगे।

1

वास्तव में नहीं - मैं इसके साथ कई समस्याएं देख सकता हूं।

सबसे पहले, विधि लगता है जैसे आप आमतौर पर सफल होने की अपेक्षा करते हैं; त्रुटियां (डेटाबेस से कनेक्ट नहीं हो सकती हैं, polls तालिका आदि तक नहीं पहुंच सकती) दुर्लभ होगी। इस मामले में, त्रुटियों की रिपोर्ट करने के लिए अपवादों का उपयोग करना अधिक उचित है। Try... पैटर्न उन मामलों के लिए है जहां आप अक्सर "असफल" कॉल की अपेक्षा करते हैं - उदा। एक पूर्णांक में स्ट्रिंग को पार्स करते समय, संभावनाएं अच्छी होती हैं कि स्ट्रिंग उपयोगकर्ता इनपुट है जो अमान्य हो सकती है, इसलिए आपको इसे संभालने का तेज़ तरीका होना चाहिए - इसलिए TryParse। यह मामला यहां नहीं है।

दूसरा, आप त्रुटियों की रिपोर्ट bool मान की उपस्थिति या त्रुटि की अनुपस्थिति, और एक स्ट्रिंग संदेश इंगित करते हैं। कॉलर विभिन्न त्रुटियों के बीच अंतर कैसे करेगा? वह निश्चित रूप से त्रुटि संदेश पाठ से मेल नहीं खा सकता है - यह एक कार्यान्वयन विवरण है जो परिवर्तन के अधीन है, और इसे स्थानीयकृत किया जा सकता है। और "डेटाबेस से कनेक्ट नहीं हो सकता" जैसे कुछ के बीच अंतर की दुनिया हो सकती है (शायद इस मामले में डेटाबेस कनेक्शन सेटिंग्स संवाद खोलें और उपयोगकर्ता को इसे संपादित करने दें?) और "डेटाबेस से कनेक्ट किया गया है, लेकिन यह कहता है 'एक्सेस अस्वीकृत' "। आपका एपीआई उन लोगों के बीच अंतर करने का कोई अच्छा तरीका नहीं देता है।

इसे समेटने के लिए: संदेशों की रिपोर्ट करने के लिए bool + out string के बजाय अपवादों का उपयोग करें। एक बार ऐसा करने के बाद, आप out तर्क की आवश्यकता के साथ, वापसी मूल्य के रूप में केवल List<Poll> का उपयोग कर सकते हैं। और, ज़ाहिर है, GetPolls पर विधि का नाम बदलें, क्योंकि Try...bool+out पैटर्न के लिए आरक्षित है।

0

मुझे लगता है कि यह ठीक है। मैं हालांकि पसंद करेंगे:

enum FailureReasons {} 
public static IEnumerable<Poll> TryGetPolls(out FailureReasons reason) 

तो त्रुटि तार डेटा एक्सेस कोड में नहीं रहते ...

0

सी # तरीके वास्तव में केवल एक बात करना चाहिए। आप उस विधि के साथ तीन चीजें करने की कोशिश कर रहे हैं। अगर ऐसा होता है तो दूसरों ने सुझाव दिया है और अपवाद फेंक दिया है। एक और विकल्प आपकी सूची वस्तु के लिए एक्सटेंशन विधियां बनाना होगा।

उदा। एक सार्वजनिक स्थैतिक कक्षा में:

List<Poll> polls = new List<Poll>().Fill(); 
if(polls != null) 
{ 
    // no errors occur 
} 

संपादित करें:

public static List<Poll> Fill(this List<Poll> polls) { 
    // code to retrieve polls 
} 

फिर, इस कॉल करने के लिए, आप की तरह कुछ करना होगा मैं सिर्फ यह बना हुआ है। आपको List<Poll>().Fill()

0

में नए ऑपरेटर की आवश्यकता हो सकती है या नहीं, कृपया अपनी धारणाओं, बाधाओं, इच्छाओं/लक्ष्यों और तर्क को बताएं; हमें यह जानने के लिए अनुमान लगाया जा रहा है कि आपके इरादे क्या हैं।

आप

  • करने के लिए अपने समारोह चुनाव सूची वस्तु बनाने
  • दबाने सभी अपवादों
  • एक बूलियन
  • के साथ सफलता से संकेत मिलता है और विफलता
पर एक वैकल्पिक त्रुटि संदेश प्रदान चाहते हैं यह सोचते हैं कि

तो उपर्युक्त हस्ताक्षर ठीक है (हालांकि सभी संभावित अपवादों को निगलना एक अच्छा पी नहीं है ractice)।

एक सामान्य कोडिंग शैली के रूप में, इसमें कुछ संभावित समस्याएं हैं, जैसा कि अन्य ने उल्लेख किया है। क्योंकि वे एपीआई कठिन उपयोग करने के लिए बनाने के

1

दिशा निर्देशों, रेफरी और बाहर मानकों से बचने के लिए अगर वे पूरी तरह से की आवश्यकता नहीं है की कोशिश करने का कहते हैं कि (विधियों में से कोई और अधिक श्रृंखलन, डेवलपर से पहले सभी चर घोषित करने के लिए है विधि) बुला

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

विधि घोषित करने का एक बेहतर तरीका इस तरह है।

public static List<Poll> GetPolls() ... 

और त्रुटि रिपोर्टिंग भी उपयोग अपवाद हैंडलिंग

try 
{ 
    var pols = GetPols(); 
    ... 
} catch (DbException ex) { 
    ... // handle exception providing info to the user or logging it. 
} 
0

वहाँ भी इस पैटर्न, के रूप में कई Win32 कार्यों में देखा जाता है के लिए।

public static bool GetPolls(out List<Poll> polls) 


if(!PollStuff.GetPolls(out myPolls)) 
    string errorMessage = PollStuff.GetLastError(); 

लेकिन आईएमओ यह भयानक है। मैं कुछ अपवाद के लिए जाऊंगा जब तक कि इस विधि को 3 डी गेम भौतिकी इंजन या कभी-कभी 65 सेकंड प्रति सेकंड चलाने की आवश्यकता न हो।

0

क्या मुझे यहां कुछ याद आया? प्रश्न पूछने वाला यह जानना चाहता है कि विधि विफल होने पर संसाधनों को कैसे साफ किया जाए।

public static IList<Poll> GetPolls() 
{ 
    try 
    { 
    } 
    finally 
    { 
     // check that the connection happened before exception was thrown 
     // dispose if necessary 
     // the exception will still be presented to the caller 
     // and the program has been set back into a stable state 
    } 
} 

एक डिजाइन पक्ष टिप्पणी पर, मैं भंडार वर्ग में इस पद्धति को आगे बढ़ाने ताकि आप जिसके साथ विधि को समझने के लिए संदर्भ न किसी तरह का विचार करना चाहते हैं। संभवतः, संपूर्ण आवेदन पोल को संग्रहित करने और प्राप्त करने के लिए ज़िम्मेदार नहीं है: यह डेटा स्टोर की ज़िम्मेदारी होनी चाहिए।

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