यह वास्तव में एक बहुत महत्वपूर्ण सवाल है और यह अक्सर गलत तरीके से किया जाता है क्योंकि इसे पर्याप्त महत्व नहीं दिया जाता है, भले ही यह आपके आवेदन का एक बहुत बड़ा हिस्सा हो। यहाँ मेरे दिशानिर्देश हैं:
आपकी कॉन्फ़िगर क्लास, जिसमें सभी सेटिंग्स हैं, बस एक सादा पुराना डेटा टाइप, स्ट्रक्चर / क्लास होना चाहिए:
class Config {
int prop1;
float prop2;
SubConfig subConfig;
}
इसके लिए तरीकों की आवश्यकता नहीं होनी चाहिए और इनहेरिटेंस शामिल नहीं होना चाहिए (जब तक कि यह वैरिएंट फ़ील्ड को लागू करने के लिए आपकी भाषा में एकमात्र विकल्प नहीं है - अगला पैराग्राफ देखें)। यह छोटे विशिष्ट विन्यास वर्गों (जैसे उप-उपखंड) में सेटिंग्स को समूहित करने के लिए रचना का उपयोग कर सकता है और करना चाहिए। यदि आप इसे इस तरह करते हैं, तो यूनिट परीक्षणों और सामान्य रूप से आवेदन के चारों ओर से गुजरना आदर्श होगा क्योंकि इसमें न्यूनतम निर्भरताएं होंगी।
आपको अलग-अलग प्रकारों का उपयोग करने की आवश्यकता होगी, यदि अलग-अलग सेटअपों के लिए कॉन्फ़िगरेशन संरचना में विषम हैं। यह स्वीकार किया जाता है कि आपको डायनामिक कास्ट को किसी बिंदु पर डालने की आवश्यकता होगी जब आप इसे सही (उप) कॉन्फ़िगरेशन क्लास में डालने के लिए मूल्य पढ़ते हैं, और इसमें कोई संदेह नहीं है कि यह किसी अन्य कॉन्फ़िगरेशन सेटिंग पर निर्भर करेगा।
आपको यह करते हुए फ़ील्ड के रूप में सभी सेटिंग्स में टाइप करने में आलसी नहीं होना चाहिए:
class Config {
Dictionary<string, string> values;
};
यह आकर्षक है क्योंकि इसका मतलब है कि आप एक सामान्यीकृत क्रमबद्धता वर्ग लिख सकते हैं जिसे यह जानने की आवश्यकता नहीं है कि यह किस क्षेत्र से काम कर रहा है, लेकिन यह गलत है और मैं समझाता हूं कि एक क्षण में क्यों।
विन्यास का सीरियलाइजेशन पूरी तरह से अलग वर्ग में किया जाता है। ऐसा करने के लिए आप जो भी API या लाइब्रेरी का उपयोग करते हैं, आपके क्रमांकन फ़ंक्शन के बॉडी में ऐसी प्रविष्टियाँ होनी चाहिए जो मूल रूप से फ़ाइल में पथ / कुंजी से ऑब्जेक्ट पर फ़ील्ड में फ़ील्ड के लिए हो। कुछ भाषाएं अच्छी आत्मनिरीक्षण प्रदान करती हैं और आपके लिए यह बॉक्स से बाहर कर सकती हैं, अन्य आपको स्पष्ट रूप से मैपिंग लिखना होगा, लेकिन महत्वपूर्ण बात यह है कि आपको केवल एक बार मैपिंग लिखना होगा। उदाहरण के लिए इस उद्धरण पर विचार करें जिसे मैंने c ++ बूस्ट प्रोग्राम विकल्प पार्सर प्रलेखन से अनुकूलित किया है:
struct Config {
int opt;
} conf;
po::options_description desc("Allowed options");
desc.add_options()
("optimization", po::value<int>(&conf.opt)->default_value(10);
ध्यान दें कि अंतिम पंक्ति मूल रूप से कॉन्फ़िगर करने के लिए "ऑप्टिमाइज़ेशन" मैप्स :: ऑप्ट कहती है और यह भी कि आपके द्वारा अपेक्षित प्रकार की घोषणा है। आप चाहते हैं कि यदि आप फ़ाइल से पैरामीटर वास्तव में फ्लोट या इंट नहीं है, या मौजूद नहीं है, तो टाइप करने के लिए कॉन्फ़िगर की रीडिंग विफल हो सकती है। Ie विफलता तब होनी चाहिए जब आप फ़ाइल पढ़ते हैं क्योंकि समस्या फ़ाइल के प्रारूप / सत्यापन के साथ है और आपको एक अपवाद / रिटर्न कोड फेंकना चाहिए और सटीक समस्या की रिपोर्ट करनी चाहिए। आपको इस कार्यक्रम में बाद में देरी नहीं करनी चाहिए। इसीलिए आपको किसी भी तरह की डिक्शनरी को पकड़ने के लिए लुभाया नहीं जाना चाहिए। जैसा कि ऊपर उल्लेख किया गया है कि फाइल पढ़ने पर फेल नहीं होगी - जब तक कि मूल्य की आवश्यकता न हो, कास्टिंग में देरी हो जाती है।
आपको विन्यास वर्ग को केवल कुछ फैशन में पढ़ना चाहिए - कक्षा की सामग्री को एक बार सेट करने के बाद जब आप इसे बनाते हैं और इसे फ़ाइल से आरंभ करते हैं। यदि आपको अपने एप्लिकेशन में डायनामिक सेटिंग्स की आवश्यकता होती है जो बदलते हैं, साथ ही साथ जो नहीं हैं, तो आपके पास डायनेमिक को संभालने के लिए एक अलग वर्ग होना चाहिए बजाय इसके कि आपके कॉन्फिग क्लास के बिट्स को केवल पढ़ने के लिए अनुमति न दें ।
आदर्श रूप से आप अपने प्रोग्राम में एक जगह फ़ाइल में पढ़ते हैं अर्थात आपके पास केवल " ConfigReader
" का एक उदाहरण है । हालाँकि, यदि आप कॉन्फिगरेशन इंस्टेंस प्राप्त करने से जूझ रहे हैं, जहाँ आपको इसकी आवश्यकता है, जहाँ आपको इसकी आवश्यकता है, वहां एक दूसरे कॉन्फिगरर के साथ होना बेहतर है, क्योंकि यह ग्लोबल कॉन्फिगरेशन का परिचय देता है (जिसका मैं अनुमान लगा रहा हूँ कि ओपी का अर्थ "स्टेटिक" है "), जो कि मुझे मेरे अगले बिंदु पर ले आता है:
सिंगलटन के मोहक सायरन गीत से बचें: "मैं आपको उस क्लास क्लास को पास करने के लिए बचाऊंगा, आपके सभी निर्माता प्यारे और साफ होंगे। चलिए, यह बहुत आसान होगा।" सत्य एक अच्छी तरह से डिजाइन किए गए परीक्षण योग्य वास्तुकला के साथ है, आपको शायद ही अपने एप्लिकेशन के कई वर्गों के माध्यम से कॉन्फ़िगर वर्ग या इसके कुछ हिस्सों को पारित करने की आवश्यकता होगी। आप क्या पाएंगे, अपने शीर्ष स्तर के वर्ग में, आपका मुख्य () फ़ंक्शन या जो भी हो, आप व्यक्तिगत मूल्यों में अंतर को उजागर करेंगे, जो आप अपने घटक वर्गों को तर्क के रूप में प्रदान करेंगे, जिसे आप फिर से एक साथ रखते हैं (मैनुअल निर्भरता इंजेक्शन)। एक सिंगलटन / ग्लोबल / स्टैटिक कॉन्फिडेंस यूनिट यूनिट को आपके एप्लिकेशन को कार्यान्वित करने और समझने के लिए बहुत कठिन बना देगा - जैसे यह आपकी टीम में नए डेवलपर्स को भ्रमित करेगा, जो यह नहीं जान पाएंगे कि उन्हें सामान का परीक्षण करने के लिए ग्लोबल स्टेट सेट करना है।
यदि आपकी भाषा गुणों का समर्थन करती है तो आपको उन्हें इस उद्देश्य के लिए उपयोग करना चाहिए। इसका कारण यह है कि 'व्युत्पन्न' कॉन्फ़िगरेशन सेटिंग्स को जोड़ना बहुत आसान होगा जो एक या अधिक अन्य सेटिंग्स पर निर्भर करता है। जैसे
int Prop1 { get; }
int Prop2 { get; }
int Prop3 { get { return Prop1*Prop2; }
यदि आपकी भाषा मूल रूप से संपत्ति के मुहावरे का समर्थन नहीं करती है, तो इसका एक ही प्रभाव प्राप्त करने के लिए वर्कअराउंड हो सकता है, या आप बस एक रैपर वर्ग बना सकते हैं जो बोनस सेटिंग्स प्रदान करता है। यदि आप अन्यथा गुणों का लाभ नहीं दे सकते हैं तो यह अन्यथा मैन्युअल रूप से लिखने और कुछ ओओ-भगवान को प्रसन्न करने के उद्देश्य से गेटर्स / सेटर का उपयोग करने के लिए समय की बर्बादी है। आप एक सादे पुराने क्षेत्र के साथ बेहतर होंगे।
पूर्वता के क्रम में आपको अलग-अलग स्थानों से विलय करने और कई कॉन्फ़िगरेशन लेने के लिए एक सिस्टम की आवश्यकता हो सकती है। पूर्वता के उस क्रम को सभी डेवलपर्स / उपयोगकर्ता को अच्छी तरह से परिभाषित और समझना चाहिए। उदाहरण के लिए विंडोज़ रजिस्ट्री HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE पर विचार करें। आपको यह कार्यात्मक शैली करनी चाहिए ताकि आप अपने विन्यास को केवल पढ़ने के लिए रख सकें:
final_conf = merge(user_conf, machine_conf)
बजाय:
conf.update(user_conf)
अंत में मुझे यह जोड़ना चाहिए कि यदि आपका चुना हुआ ढांचा / भाषा अपने स्वयं के अंतर्निहित, प्रसिद्ध कॉन्फ़िगरेशन तंत्र प्रदान करता है, तो आपको अपने स्वयं के रोल के बजाय इसका उपयोग करने के लाभों पर विचार करना चाहिए।
इसलिए। विचार करने के लिए बहुत सारे पहलू - इसे सही से प्राप्त करें और यह आपके एप्लिकेशन आर्किटेक्चर को गहराई से प्रभावित करेगा, बग्स को कम करेगा, चीजों को आसानी से परीक्षण योग्य बना देगा और आपको कहीं और अच्छे डिजाइन का उपयोग करने के लिए मजबूर कर देगा।