2008-12-06 18 views
9

मुझे कक्षाओं का एक सेट विकसित करने के लिए एक परियोजना सौंपा गया है जो एक स्टोरेज सिस्टम के लिए एक इंटरफ़ेस के रूप में कार्य करता है।प्रवाह नियंत्रण के लिए अपवादों का उपयोग करने से मैं कैसे बच सकता हूं?

public CustomObject get(String key, Date ifModifiedSince) 

मूल रूप से विधि CustomObjectkey के साथ जुड़े वापस जाने के लिए यदि और केवल यदि वस्तु ifModifiedSince के बाद संशोधित किया गया है माना जाता है: एक आवश्यकता वर्ग का समर्थन है जो निम्न हस्ताक्षर के साथ एक प्राप्त विधि है। यदि स्टोरेज सिस्टम में key नहीं है तो विधि को शून्य वापस करना चाहिए।

मैं परिदृश्य में जहाँ कुंजी मौजूद है, लेकिन वस्तु संशोधित नहीं किया गया कैसे निपटेंगे:

मेरे समस्या है?

यह महत्वपूर्ण है क्योंकि इस कक्षा का उपयोग करने वाले कुछ एप्लिकेशन वेब सेवाएं और वेब अनुप्रयोग होंगे। उन अनुप्रयोगों को यह जानने की आवश्यकता होगी कि 404 (नहीं मिला), 304 (संशोधित नहीं), या 200 (ठीक है, यहां डेटा है) वापस करना है या नहीं।

समाधान मैं वजन कर रहा हूँ कर रहे हैं:

  1. एक कस्टम अपवाद फेंक जब भंडारण प्रणाली शामिल नहीं है key
  2. जब ifModifiedSince विफल रहता है एक कस्टम अपवाद फेंक।
  3. कस्टमऑब्जेक्ट में एक स्टेटस प्रॉपर्टी जोड़ें। संपत्ति की जांच करने के लिए कॉलर की आवश्यकता है।

मैं इन तीन विकल्पों में से किसी से भी खुश नहीं हूं। मुझे विकल्प 1 और 2 पसंद नहीं है क्योंकि मुझे प्रवाह नियंत्रण के लिए अपवादों का उपयोग करना पसंद नहीं है। न तो मुझे एक मूल्य वापस करना पसंद है जब मेरा इरादा इंगित करना है कि कोई मूल्य था।

बहरहाल, मैं विकल्प की ओर झुकाव रहा हूँ 3.

वहाँ एक विकल्प मैं पर विचार नहीं कर रहा हूँ है? क्या इनमें से किसी भी तीन विकल्पों में से किसी के बारे में कोई मजबूत भावना है? इस सवाल का


जवाब सम्मान, व्याख्या:

  1. एक contains विधि प्रदान करें और, get(key, ifModifiedSince) कॉल करने से पहले यह फोन अपवाद फेंक अगर कुंजी मौजूद नहीं है फोन करने वाले की आवश्यकता होती है, वापसी अशक्त यदि ऑब्जेक्ट संशोधित नहीं किया गया है।
  2. एक समग्र वस्तु में प्रतिक्रिया और डेटा (यदि कोई हो) लपेटें।
  3. कुछ राज्य (UNMODIFIED, KEY_DOES_NOT_EXIST) को इंगित करने के लिए एक पूर्वनिर्धारित स्थिरांक का उपयोग करें।
  4. कॉलर होने के लिए इंटरफ़ेस लागू करता है जो कॉलबैक के रूप में उपयोग किया जाता है।
  5. डिज़ाइन बेकार है।

मैं क्यों नहीं चुन सकते उत्तर # 1

मैं मानता हूँ कि यह आदर्श समाधान है, लेकिन यह एक है मैं पहले से ही (अनिच्छा से) को खारिज कर दिया था। इस दृष्टिकोण के साथ समस्या यह है कि इनमें से अधिकांश मामलों में इन वर्गों का उपयोग किया जाएगा, बैकएंड स्टोरेज सिस्टम एक तृतीय पक्ष रिमोट सिस्टम होगा, जैसे अमेज़ॅन एस 3। इसका मतलब है कि contains विधि को स्टोरेज सिस्टम की एक राउंड ट्रिप की आवश्यकता होगी, जो ज्यादातर मामलों में एक और दौर यात्रा के बाद होगी। चूंकि यह दोनों समय और धन खर्च करेगा, यह एक विकल्प नहीं है।

यदि उस सीमा के लिए नहीं, तो यह सबसे अच्छा तरीका होगा।

(मुझे पता है मैं प्रश्न में इस महत्वपूर्ण तत्व का उल्लेख नहीं था, लेकिन मैं इसे संक्षिप्त रखने के लिए कोशिश कर रहा था जाहिर है यह प्रासंगिक था।।)


निष्कर्ष:

सभी उत्तरों को पढ़ने के बाद मैं इस निष्कर्ष पर पहुंचा हूं कि इस मामले में एक रैपर सबसे अच्छा तरीका है। अनिवार्य रूप से मैं एक प्रतिक्रिया कोड, और सामग्री निकाय (संदेश) सहित मेटा डेटा (शीर्षलेख) के साथ HTTP की नकल करूंगा। "==" .equals के बजाय() के साथ

static public final CustomObject UNCHANGED=new CustomObject(); 
एक मैच के लिए

और परीक्षण:

उत्तर

7

ऐसा लगता है कि आप वास्तव में दो आइटम वापस करना चाहते हैं: प्रतिक्रिया कोड और ऑब्जेक्ट मिला। आप एक हल्के रैपर बनाने पर विचार कर सकते हैं जो दोनों को पकड़ता है और उन्हें एक साथ वापस कर देता है।

public class Pair<K,V>{ 
    public K first; 
    public V second; 
} 

फिर आप एक नया जोड़ा बना सकते हैं जिसमें आपका प्रतिक्रिया कोड और डेटा हो। जेनेरिकों का उपयोग करने के दुष्प्रभाव के रूप में, फिर आप इस रैपर को फिर से उपयोग कर सकते हैं जो आपको वास्तव में चाहिए।

इसके अलावा, यदि डेटा की समयसीमा समाप्त नहीं हुई है, तो भी आप इसे वापस कर सकते हैं, लेकिन इसे 303 कोड दें ताकि उन्हें पता चल सके कि यह अपरिवर्तित है। 4xx श्रृंखला null के साथ जोड़ा जाएगा।

+1

यह बुरा नहीं है, लेकिन इसे अधिक दृढ़ता से टाइप किया जाना चाहिए, और इसे सामान्य बनाने की आवश्यकता नहीं है। –

+1

उस जोड़ी प्रकार को और अधिक दृढ़ता से टाइप नहीं किया जा सका, और आप चीजों को यथासंभव सामान्य क्यों नहीं बनाना चाहेंगे? पॉलिमॉर्फिज्म एक अच्छी बात है। – Apocalisp

+1

एक पाए गए ऑब्जेक्ट और प्रतिक्रिया कोड दोनों को वापस करने के बजाय, आप किसी भी वस्तु या विफलता कोड को वापस कर सकते हैं। इसे किसी भी प्रकार के संघ प्रकार के साथ टाइप-सुरक्षित बनाया जा सकता है जैसे । – Apocalisp

3

आप एक "मार्कर" अपरिवर्तित इंगित करने के लिए के रूप में एक विशेष अंतिम CustomObject बना सकते हैं।

यह अपरिवर्तित पर शून्य वापस करने के लिए भी काम कर सकता है और एक अपवाद फेंकने पर मौजूद नहीं है? अगर मुझे आपके 3 में से एक चुनना पड़ा, तो मैं 1 का चयन करूंगा क्योंकि यह सबसे असाधारण मामला लगता है।

+1

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

+0

हां, लेकिन अपवाद प्रयास/पकड़/अंत में एक श्रृंखला पेश करते हैं, इसलिए प्रदर्शन की लागत पर शुद्ध लाभ केवल प्रवर्तन है? और अपवाद हैंडलिंग अधिक वर्बोज़ है, और कारक कोड से अधिक दूर है। तो ... यह निर्भर करता है ... ओपी ने अपवादों से बचने के लिए कहा। –

3

ऐसी वस्तु की तलाश करना जो अस्तित्व में नहीं है, मुझे असाधारण मामला लगता है। एक विधि के साथ जोड़ा गया है जो एक कॉलर को यह निर्धारित करने की अनुमति देता है कि कोई ऑब्जेक्ट मौजूद है या नहीं, मुझे लगता है कि अपवाद फेंकना ठीक होगा।

public bool exists(String key) { ... } 

कोलर कर सकता है:

if (exists(key)) { 
    CustomObject modified = get(key,DateTime.Today.AddDays(-1)); 
    if (modified != null) { ... } 
} 

or 

try { 
    CustomObject modified = get(key,DateTime.Today.AddDays(-1)); 
} 
catch (NotFoundException) { ... } 
0

यदि यह स्वीकार्य है, तो आप एक प्रवर्धित CustomObject (एक आवरण) है, जो मान जो वस्तु और उसके संशोधन राज्य का प्रतिनिधित्व किया, यदि कोई हो, आदि निहित वापस आ सकते हैं ।

2

अपवादों के साथ समस्या है कि वे एक "असफल तेज" परिदृश्य का संकेत करने के लिए हैं है (यानी अगर संसाधित नहीं, एक अपवाद होगा रोक एक आवेदन) एक ई की वजह से xceptional और असामान्य व्यवहार।

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

इसलिए मैं अपवाद का उपयोग नहीं करता, बल्कि मैं परिणाम (संपत्ति या विशेष वस्तु) की सही व्याख्या करने के लिए कॉलर को करने की आवश्यकता को दस्तावेज करता हूं।

+0

हाँ, इस मामले में एक अपवाद एक बुरा निर्णय है। – OscarRyz

+0

कुंजी कहां से आई थी? यदि आपके पास कुंजी है, तो ऑब्जेक्ट मौजूद होना चाहिए और यदि ऐसा नहीं होता है तो यह एक असाधारण मामला है। – tvanfosson

+0

@ बुजर: ऐसा हो सकता है, लेकिन यदि आपका अपवाद अनचेक हो जाता है तो एप्लिकेशन को * रोकना होगा *? मुझे ऐसा नहीं लगता है। – VonC

1

उस विधि हस्ताक्षर की आवश्यकता कितनी सख्त है?

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

यदि यह एक विकल्प है तो मैं इसे अपने पर्यवेक्षक के साथ चर्चा करूंगा।

5

दी गई आवश्यकता के साथ आप यह नहीं कर सकते हैं।

यदि आप अनुबंध तैयार किया गया है, तो एक शर्त जोड़ सकते हैं और फोन करने वाले आह्वान

exists(key): bool 

सेवा क्रियान्वयन ऐसा दिखाई बनाने:

if (exists(key)) { 
    CustomObject o = get(key, ifModifiedSince); 
    if (o == null) { 
     setResponseCode(302); 
    } else { 
     setResponseCode(200); 
     push(o); 
    } 

} else { 
     setResponseCode(400); 
} 

ग्राहक अपरिवर्तित रहता है और कभी नहीं तुम नोटिस पहले से मान्य है।

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

तो फिर तुम विनिर्देशों का पालन करना चाहिए और इस तरह आगे बढ़ना:

CustomObject o = get(key, ifModifiedSince); 

if (o != null) { 
    setResponseCode(200); 
    push(o); 
    } else { 
    setResponseCode(404); // either not found or not modified. 
    } 

ठीक है, आप 302 इस मामले में नहीं भेज रहे हैं, लेकिन शायद यह है कि जिस तरह से यह डिजाइन किया गया है।

मेरा मतलब है, सुरक्षा कारणों के लिए, सर्वर में अधिक जानकारी के से वापस नहीं जाना चाहिए [जांच मिलता है (कुंजी, तारीख) केवल वापसी या तो नल या वस्तु]

तो इसके बारे में चिंता मत करो । अपने प्रबंधक से बात करें और उसे इस निर्णय को बताने दें। इस निर्णय के साथ कोड भी टिप्पणी करें। और यदि आपके पास आर्किटेक्ट हाथ में है तो इस अजीब प्रतिबंध के पीछे तर्क की पुष्टि करें।

संभावना है कि वे इसे नहीं देख रहे हैं और वे आपके सुझाव के बाद अनुबंध को संशोधित कर सकते हैं।

कभी-कभी सही आगे बढ़ना चाहते समय हम गलत हो सकते हैं और हमारे ऐप की सुरक्षा समझौता कर सकते हैं।

अपनी टीम के साथ संवाद करें।

+0

404 == नहीं मिला, 304 == संशोधित नहीं हुआ। यदि एक परिणाम का मतलब दो अलग-अलग चीजें हैं, तो वह किसी दिन किसी को काटने जा रहा है। – Dustin

+1

हां, लेकिन शायद यह इरादा है। उदाहरण के लिए। याहू में लॉग इन करें! एक नकली खाते के साथ। सर्वर कहता है: "अवैध आईडी या पासवर्ड।" वे नहीं कहते हैं कि "खाता मौजूद नहीं है" इसके लिए एक अच्छा कारण है। याहू आपको नहीं बताएगा कि कोई खाता मौजूद है या पासवर्ड गलत है। यहां तक ​​कि जब वे कर सकते थे। – OscarRyz

+1

यह उद्यम में सुरक्षा सलाहकार द्वारा लगाई गई सुरक्षा बाधा हो सकती है (हम सभी के पास एक अधिकार है?) ओउर शायद, डिजाइनर बस इस परिदृश्य को भूल गया (जो कभी सही नहीं होता? डिजाइन हमेशा सही होता है) हम नहीं जानते। संभवतः इस सेवा का आंतरिक रूप से उपयोग किया गया था और अब पब – OscarRyz

1

मैं अभी भी शून्य वापस आऊंगा।

संपत्ति का इरादा उस तारीख को वापस करना है जो निर्दिष्ट तिथि के बाद संशोधित किया गया था। यदि किसी ऑब्जेक्ट के लिए शून्य लौटाना ठीक है, तो निश्चित रूप से एक अनमोड ऑब्जेक्ट के लिए शून्य वापस लौटना ठीक है।

मैं व्यक्तिगत रूप से एक गैर-संशोधित ऑब्जेक्ट के लिए शून्य वापस कर दूंगा, और एक गैर-मौजूदा ऑब्जेक्ट के लिए अपवाद फेंक दूंगा। यह और अधिक प्राकृतिक लगता है।

प्रवाह नियंत्रण बीटीडब्ल्यू के लिए अपवादों का उपयोग न करने का आप सही हैं, इसलिए यदि आपके पास केवल 3 विकल्प हैं, तो आपका आंत वृत्ति सही है।

+0

यह एकमात्र उचित समाधान है। यदि विधि के लिए क्वालीफायर पूरा नहीं हुआ है, तो इसे शून्य वापस करना चाहिए, मुझे किसी और चीज का बिंदु नहीं दिख रहा है। अमान्य कुंजी पर शून्य संदिग्ध है और किसी भी तरह से जा सकता है। एक नक्शा शून्य वापस आ जाएगा, अन्य कक्षाएं IllegalArgumentException फेंक देंगे। – Robin

+0

बेशक अमान्य कुंजी केस पहले ही निर्धारित है, इसलिए दोनों के लिए शून्य। – Robin

1

आप की नेट पुस्तकालय पैटर्न का पालन करें और लिखें CustomObject (string.Empty और Guid.Empty) की तरह की है कि CustomObject.Empty बुलाया कस्टम वस्तु में एक सार्वजनिक स्थैतिक केवल पढ़ने के लिए क्षेत्र हो सकता था। यदि वस्तु संशोधित नहीं की जाती है तो आप इसे वापस कर सकते हैं (फ़ंक्शन उपभोक्ता को इसकी तुलना करने की आवश्यकता होगी)।
संपादित करें: मैं सिर्फ देखा है कि आप जावा में काम कर रहे हैं, लेकिन सिद्धांत अभी भी लागू होता

यह आप निम्नलिखित

का विकल्प
  • वापसी अशक्त यदि कुंजी नहीं करता है देता है अस्तित्व में नहीं है

  • रिटर्न कस्टमऑब्जेक्ट। लक्षण यदि कुंजी मौजूद है लेकिन ऑब्जेक्ट को संशोधित नहीं किया गया है।

दोष यह है कि उपभोक्ता को शून्य वापसी मूल्य और कस्टमऑब्जेक्ट के बीच अंतर जानने की आवश्यकता होगी। लक्षण वापसी मूल्य।

शायद संपत्ति को अधिक उपयुक्त रूप से कस्टमऑब्जेक्ट.NotModified कहा जाएगा क्योंकि खाली वास्तव में मूल्य प्रकारों के लिए लक्षित है क्योंकि वे शून्य नहीं हो सकते हैं। NotModified उपभोक्ता को अधिक आसानी से क्षेत्र का अर्थ बताएगा।

1

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

+0

अमेन! और वहां से कोई रास्ता नहीं है। – OscarRyz

+0

मैं दूसरा वह! इसमें एक अच्छी स्थिति नहीं है। –

1

कॉलबैक क्लास को उस तर्क के रूप में प्रदान करें जहां कॉलबैक क्लास या तो ईवेंट संचालित हो या सेटर संचालित हो।

आपके क्लास का इंटरफ़ेस कस्टम त्रुटियों में होने वाली विभिन्न त्रुटियों को परिभाषित करता है, यदि आवश्यक हो तो ईवेंट के पैरामीटर के रूप में।

public interface Callback { 
    public void keyDoesNotExist(); 
    public void notModified(CustomObject c); 
    public void isNewlyModified(CustomObject c); 
    . 
    . 
    . 
} 

इस तरह, आप कॉलबैक अंतरफलक के implementor क्या जब घटना होती है ऐसा करने के लिए निर्धारित करने की अनुमति है, और आप इंटरफेस के माध्यम से चुन सकते हैं, स्थिति को पुनः प्राप्त वस्तु के गुजरने की आवश्यकता है कि क्या। अंत में, यह वापसी पर तर्क की जटिलता को कम कर देता है। आपकी विधि एक बार ऐसा करती है। एपीआई के कार्यान्वयनकर्ताओं को ऐसा करने की आवश्यकता नहीं है, क्योंकि यह उनके लिए किया गया है।

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