मुझे कोड समीक्षा के बाद एक डिज़ाइन विकल्प पर बस चर्चा करनी थी। मुझे आश्चर्य है कि आपकी क्या राय है।
यह Preferencesवर्ग है, जो कि-वैल्यू पेयर के लिए एक बकेट है। अशक्त मूल्य कानूनी हैं (यह महत्वपूर्ण है)। हम उम्मीद करते हैं कि कुछ मूल्यों को अभी तक सहेजा नहीं जा सकता है, और हम अनुरोध किए जाने पर इन मामलों को स्वचालित रूप से पूर्वनिर्धारित डिफ़ॉल्ट मान के साथ प्रारंभ करके संभालना चाहते हैं।
पर चर्चा की समाधान निम्नलिखित पैटर्न का इस्तेमाल (नोट: यह वह जगह है नहीं वास्तविक कोड, स्पष्ट रूप से - यह निदर्शी प्रयोजनों के लिए सरल बनाया गया है):
public class Preferences {
// null values are legal
private Map<String, String> valuesFromDatabase;
private static Map<String, String> defaultValues;
class KeyNotFoundException extends Exception {
}
public String getByKey(String key) {
try {
return getValueByKey(key);
} catch (KeyNotFoundException e) {
String defaultValue = defaultValues.get(key);
valuesFromDatabase.put(key, defaultvalue);
return defaultValue;
}
}
private String getValueByKey(String key) throws KeyNotFoundException {
if (valuesFromDatabase.containsKey(key)) {
return valuesFromDatabase.get(key);
} else {
throw new KeyNotFoundException();
}
}
}
इसे एक विरोधी पैटर्न के रूप में आलोचना की गई - प्रवाह को नियंत्रित करने के लिए अपवादों का दुरुपयोग । KeyNotFoundException- केवल एक उपयोग के मामले के लिए जीवन के लिए लाया - कभी भी इस वर्ग के दायरे से बाहर नहीं देखा जाएगा।
यह अनिवार्य रूप से दो तरीके से खेल रहा है, केवल एक दूसरे से कुछ संवाद करने के लिए।
डेटाबेस में मौजूद नहीं होने वाली कुंजी कुछ खतरनाक या असाधारण नहीं है - हम उम्मीद करते हैं कि जब भी कोई नया वरीयता सेटिंग जोड़ा जाता है, तो यह घटित हो, इसलिए ऐसा तंत्र जो जरूरत पड़ने पर एक डिफ़ॉल्ट मान के साथ इसे इनिशियलाइज़ करता है।
प्रतिवाद यह था कि getValueByKey- निजी पद्धति - जैसा कि अभी परिभाषित किया गया है, दोनों मूल्य के बारे में सार्वजनिक विधि को सूचित करने का कोई प्राकृतिक तरीका नहीं है , और क्या कुंजी थी। (यदि ऐसा नहीं था, तो इसे जोड़ना होगा ताकि मूल्य को अपडेट किया जा सके)।
लौटना nullअस्पष्ट होगा, क्योंकि nullयह पूरी तरह से कानूनी मूल्य है, इसलिए यह बताने वाला नहीं है कि इसका मतलब यह है कि कुंजी नहीं थी, या यदि वहाँ थी null।
getValueByKeyएक के कुछ प्रकार वापसी करना होगा Tuple<Boolean, String>ताकि हम बीच भेद कर सकते,, bool सही पर सेट किया है, तो कुंजी पहले से ही वहाँ है (true, null)और (false, null)। (एक outपैरामीटर C # में इस्तेमाल किया जा सकता है, लेकिन यह जावा है)।
क्या यह एक अच्छा विकल्प है? हां, आपको प्रभाव के लिए कुछ एकल-उपयोग वर्ग को परिभाषित करना होगा Tuple<Boolean, String>, लेकिन फिर हम छुटकारा पा रहे हैं KeyNotFoundException, ताकि इस तरह के शेष बाहर हो जाएं। हम एक अपवाद को संभालने के ओवरहेड से भी बच रहे हैं, हालांकि यह व्यावहारिक रूप से महत्वपूर्ण नहीं है - इसमें बोलने के लिए कोई प्रदर्शन विचार नहीं हैं, यह एक क्लाइंट ऐप है और यह ऐसा नहीं है कि उपयोगकर्ता की प्राथमिकताएं प्रति सेकंड लाखों बार पुनर्प्राप्त की जाएंगी।
इस दृष्टिकोण की भिन्नता Optional<String>कुछ रीति-रिवाजों के बजाय अमरूद का उपयोग कर सकती है (अमरूद पहले से ही परियोजना के दौरान प्रयोग किया जाता है) Tuple<Boolean, String>और फिर हम Optional.<String>absent()"उचित" के बीच अंतर कर सकते हैं null। यह अभी भी हैकिश महसूस करता है, हालांकि, उन कारणों के लिए जो देखने में आसान हैं - "शून्यता" के दो स्तरों का परिचय उस अवधारणा का दुरुपयोग करते हैं Optionalजो पहली जगह में एस बनाने के पीछे खड़ा था ।
एक अन्य विकल्प स्पष्ट रूप से जांचना होगा कि क्या कुंजी मौजूद है ( केवल एक boolean containsKey(String key)विधि जोड़ें और कॉल करें getValueByKeyयदि हमने पहले ही यह मान लिया है कि यह मौजूद है)।
अंत में, कोई निजी पद्धति को भी इनलाइन कर सकता है, लेकिन वास्तविक getByKeyमेरे कोड नमूने की तुलना में कुछ अधिक जटिल है, इस प्रकार इनलाइनिंग इसे काफी बुरा लगेगा।
मैं यहाँ बालों को विभाजित कर सकता हूं, लेकिन मैं उत्सुक हूं कि आप इस मामले में सबसे अच्छा अभ्यास करने के लिए सबसे करीब होंगे। मुझे Oracle के या Google के स्टाइल गाइड में कोई उत्तर नहीं मिला।
क्या कोड नमूने जैसे अपवादों का उपयोग एक विरोधी पैटर्न है, या यह स्वीकार्य है कि विकल्प बहुत साफ नहीं हैं, या तो? यदि यह है, तो किन परिस्थितियों में यह ठीक होगा? और इसके विपरीत?
getValueByKeyसार्वजनिक होने पर सवाल और दिलचस्प हो जाता है।