এটি আসলেই একটি গুরুত্বপূর্ণ প্রশ্ন এবং এটি প্রায়শই ভুলভাবে করা হয় কারণ এটি প্রতিটি প্রয়োগের মূল অংশ হলেও এটি যথেষ্ট গুরুত্ব দেওয়া হয় না। এখানে আমার গাইডলাইন রয়েছে:
আপনার কনফিগার ক্লাসে, যা সমস্ত সেটিংস ধারণ করে তা কেবল একটি সরল পুরাতন ডেটা টাইপ, স্ট্রাক্ট / শ্রেণি হওয়া উচিত:
class Config {
int prop1;
float prop2;
SubConfig subConfig;
}
এটির পদ্ধতির প্রয়োজন হবে না এবং উত্তরাধিকারের সাথে জড়িত হওয়া উচিত নয় (যদি না কোনও বৈকল্পিক ক্ষেত্র বাস্তবায়নের জন্য আপনার ভাষাতে আপনার পছন্দ থাকে তবে - পরবর্তী অনুচ্ছেদটি দেখুন)। এটি সেটিংগুলি ছোট নির্দিষ্ট কনফিগারেশন ক্লাসে (যেমন উপরের সাবকনফিগ) বিভক্ত করতে ব্যবহার করতে পারে এবং ব্যবহার করা উচিত। আপনি যদি এভাবে এটি করেন তবে ইউনিট পরীক্ষায় এবং সাধারণভাবে প্রয়োগের ক্ষেত্রে পাস করার পক্ষে আদর্শ হবে কারণ এতে ন্যূনতম নির্ভরতা থাকবে।
কাঠামোর ক্ষেত্রে বিভিন্ন সেটআপের জন্য কনফিগারগুলি ভিন্ন ভিন্ন ক্ষেত্রে আপনাকে সম্ভবত বিভিন্ন ধরণের ব্যবহার করতে হবে। এটি স্বীকৃত যে আপনি যখন ডান (উপ) কনফিগারেশন ক্লাসে কাস্ট করার জন্য মানটি পড়েন তখন আপনাকে কোনও সময়ে ডায়নামিক কাস্ট লাগাতে হবে এবং কোনও সন্দেহ নেই যে এটি অন্য কোনও কনফিগারেশন সেটিংয়ের উপর নির্ভর করবে।
ক্ষেত্র হিসাবে সমস্ত সেটিংসে টাইপ করার ক্ষেত্রে আপনার কেবল অলস হওয়া উচিত নয়:
class Config {
Dictionary<string, string> values;
};
এটি লোভনীয় কারণ এর অর্থ আপনি একটি সাধারণীকৃত সিরিয়ালাইজ ক্লাস লিখতে পারেন যা এটি কোন ক্ষেত্রগুলি নিয়ে কাজ করে তা জানা দরকার নেই তবে এটি ভুল এবং আমি কেন একটি মুহুর্তে ব্যাখ্যা করব।
কনফিগার সিরিয়ালাইজেশন সম্পূর্ণ পৃথক শ্রেণিতে করা হয়। আপনি এটি করতে যা কিছু এপিআই বা লাইব্রেরি ব্যবহার করুন না কেন, আপনার সিরিয়ালাইজেশন ফাংশনের মূল শৃঙ্খলে এমন ফাইলগুলি থাকা উচিত যা মূলত ফাইলের পথ / কী থেকে অবজেক্টের ক্ষেত্রের মানচিত্রের পরিমাণ। কিছু ভাষাগুলি ভাল আত্মনির্বাচনা সরবরাহ করে এবং এটি আপনার জন্য বাক্সের বাইরে করতে পারে, অন্যগুলি আপনাকে ম্যাপিং স্পষ্টভাবে লিখতে হবে, তবে মূল বিষয়টি হ'ল আপনাকে কেবল একবার ম্যাপিংটি লিখতে হবে। উদাহরণস্বরূপ, সি ++ বুস্ট প্রোগ্রাম অপশন পার্সার ডকুমেন্টেশন থেকে আমি যে রূপান্তরটি গ্রহণ করেছি তা বিবেচনা করুন:
struct Config {
int opt;
} conf;
po::options_description desc("Allowed options");
desc.add_options()
("optimization", po::value<int>(&conf.opt)->default_value(10);
নোট করুন যে শেষ লাইনটি মূলত কনফিগার :: অপ্টকে "অপ্টিমাইজেশন" মানচিত্রগুলি বলেছে এবং আপনার প্রত্যাশার ধরণের একটি ঘোষণাও রয়েছে। আপনি চাইছেন কনফিগারেশনটি পড়া ব্যর্থ হয় যদি টাইপটি আপনি যা প্রত্যাশা করেন তা যদি না হয় তবে যদি ফাইলটিতে প্যারামিটারটি আসলেই ভাসা বা কোনও int হয় না বা উপস্থিত না থাকে। উদাহরণস্বরূপ, আপনি যখন ফাইলটি পড়েন তখন ব্যর্থতা দেখা দেয় কারণ সমস্যাটি ফাইলের ফর্ম্যাট / বৈধতার সাথে সম্পর্কিত এবং আপনার / রিটার্ন কোড ব্যতীত নিক্ষেপ করা উচিত এবং সঠিক সমস্যার প্রতিবেদন করা উচিত। প্রোগ্রামে আপনার এটি পরে বিলম্ব করা উচিত নয়। এ কারণেই উপরে উল্লিখিত সমস্ত অভিধান স্টাইল কনফারেন্সের জন্য আপনাকে প্রলুব্ধ করা উচিত নয় যা ফাইলটি পড়ার সময় ব্যর্থ হবে না - যেমন মান প্রয়োজন না হওয়া পর্যন্ত কাস্টিং বিলম্বিত হয়।
আপনার কিছুটা ফ্যাশনে কনফিগার ক্লাসটি কেবল পঠনযোগ্য করা উচিত - আপনি যখন এটি তৈরি করবেন তখন ক্লাসের বিষয়বস্তুগুলি সেট করে ফাইলে শুরু করুন। আপনার অ্যাপ্লিকেশনটিতে পরিবর্তনশীল সেইসাথে পরিবর্তিত কনস্টের দরকার থাকলে আপনার কনফিগার ক্লাসের বিটগুলি কেবল পঠনযোগ্য না হওয়ার পরিবর্তে ডায়নামিকগুলি পরিচালনা করার জন্য আপনার একটি পৃথক ক্লাস থাকা উচিত ।
আদর্শভাবে আপনি ফাইলটিতে আপনার প্রোগ্রামের এক জায়গায় পড়েন অর্থাৎ আপনার কাছে কেবলমাত্র একটি উদাহরণ রয়েছে " ConfigReader
"। যাইহোক, আপনি যদি কনফিগারেশন উদাহরণটি আপনার প্রয়োজনের পাশ দিয়ে কাটাতে লড়াই করে যাচ্ছেন, তবে একটি বিশ্বব্যাপী কনফিগার চালু করার চেয়ে দ্বিতীয় কনফিগার রিডার রাখাই ভাল (যা আমি অনুমান করছি যে "স্থির দ্বারা ওপি মানে কী "), যা আমার পরের পয়েন্ট সম্পর্কে এনেছে:
সিঙ্গলটনের প্রলোভনমূলক সাইরেন গানটি এড়িয়ে চলুন: "আমি আপনাকে এই ক্লাসের ক্লাসটি পাশ করার মাধ্যমে বাঁচিয়ে দেব, আপনার সমস্ত নির্মাতা সুন্দর এবং পরিষ্কার থাকবেন। এগিয়ে যান, এটি এত সহজ হবে" " সত্য একটি ভাল নকশাযুক্ত পরীক্ষাযোগ্য আর্কিটেকচারের সাথে আপনার নিজের কপিরাইট ক্লাসটি বা তার কিছু অংশ আপনার অ্যাপ্লিকেশনটির অনেকগুলি ক্লাসের মধ্য দিয়ে পাস করতে হবে না। আপনার শীর্ষ স্তরের শ্রেণিতে, আপনার মূল () ফাংশন বা যা কিছু আপনি খুঁজে পাবেন, আপনি স্বতন্ত্র মানগুলিতে আবদ্ধ হবেন, যা আপনি আপনার উপাদান শ্রেণিগুলিকে যুক্তি হিসাবে প্রদান করবেন যা আপনি আবার একসাথে রেখেছিলেন (ম্যানুয়াল নির্ভরতা ইনজেকশন)। একটি সিঙ্গলটন / গ্লোবাল / স্ট্যাটিক কনফার্ট ইউনিট আপনার প্রয়োগকে পরীক্ষা করা বাস্তবায়ন করা এবং বোঝার জন্য আরও শক্ত করে তোলে - যেমন এটি আপনার দলে নতুন বিকাশকারীকে বিভ্রান্ত করবে যারা জানেন না যে তারা স্টাফের পরীক্ষার জন্য গ্লোবাল স্টেট স্থাপন করতে হবে।
যদি আপনার ভাষা বৈশিষ্ট্যগুলিকে সমর্থন করে তবে আপনার সেগুলি এই উদ্দেশ্যে ব্যবহার করা উচিত। কারণটি হ'ল এর অর্থ এটি 'উত্পন্ন' কনফিগারেশন সেটিংস যুক্ত করা খুব সহজ হবে যা এক বা একাধিক অন্যান্য সেটিংসের উপর নির্ভর করে। যেমন
int Prop1 { get; }
int Prop2 { get; }
int Prop3 { get { return Prop1*Prop2; }
যদি আপনার ভাষা মূলত সম্পত্তি আইডিয়মকে সমর্থন করে না, তবে একই প্রভাবটি অর্জনের জন্য এটির কাজ হতে পারে, বা আপনি কেবল একটি মোড়কের ক্লাস তৈরি করেন যা বোনাস সেটিংস সরবরাহ করে। আপনি অন্যথায় যদি সম্পত্তিগুলির সুবিধা প্রদান করতে না পারেন তবে অন্যথায় Oশ্বরকে সন্তুষ্ট করার উদ্দেশ্যে নিজে নিজে লেখার জন্য এবং গেটর / সেটটারগুলি ব্যবহার করা সময় নষ্ট করা। আপনি সরল পুরানো মাঠের সাথে আরও ভাল থাকবেন।
অগ্রাধিকারের ভিত্তিতে আপনার একত্রিত হতে এবং বিভিন্ন স্থান থেকে একাধিক কনফিগার নিতে সিস্টেমের প্রয়োজন হতে পারে। অগ্রাধিকারের ক্রমটি সমস্ত বিকাশকারী / ব্যবহারকারীর দ্বারা যথাযথভাবে সংজ্ঞায়িত করা এবং বোঝা উচিত eg উদাহরণস্বরূপ উইন্ডোজ রেজিস্ট্রি HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE বিবেচনা করুন। আপনার এই কার্যকরী শৈলীটি করা উচিত যাতে আপনি আপনার কনফিগারগুলি কেবল পঠন রাখতে পারেন:
final_conf = merge(user_conf, machine_conf)
বরং:
conf.update(user_conf)
আমার অবশেষে অবশ্যই যুক্ত করা উচিত যদি আপনার নির্বাচিত কাঠামো / ভাষা তার নিজস্ব অন্তর্নির্মিত, সুপরিচিত কনফিগারেশন প্রক্রিয়া সরবরাহ করে তবে আপনার নিজের ঘূর্ণায়মানের পরিবর্তে এটি ব্যবহারের সুবিধাগুলি বিবেচনা করা উচিত।
So. অনেকগুলি দিক বিবেচনা করতে হবে - এটি সঠিকভাবে পান এবং এটি আপনার অ্যাপ্লিকেশন আর্কিটেকচারকে গভীরভাবে প্রভাবিত করবে, বাগগুলি হ্রাস করবে, জিনিসগুলি সহজেই পরীক্ষারযোগ্য করে তোলা হবে এবং সাজানোর জন্য আপনাকে অন্য কোথাও ভাল ডিজাইন ব্যবহার করতে বাধ্য করবে।