আমি একটি সি ++ অ্যাপ্লিকেশন লিখছি। বেশিরভাগ অ্যাপ্লিকেশনগুলি ডেটা উদ্ধৃতি পড়তে এবং লেখার প্রয়োজন এবং এটি কোনও ব্যতিক্রম নয়। আমি ডেটা মডেল এবং সিরিয়ালাইজেশন লজিকের জন্য একটি উচ্চ স্তরের নকশা তৈরি করেছি। এই প্রশ্নটি এই নির্দিষ্ট লক্ষ্যগুলি মাথায় রেখে আমার নকশাটির পর্যালোচনা করার অনুরোধ করছে :
স্বেচ্ছাসেবী বিন্যাসে ডেটা মডেলগুলি পড়ার এবং লেখার একটি সহজ এবং নমনীয় উপায় হ'ল: কাঁচা বাইনারি, এক্সএমএল, জেএসএন, ইত্যাদি। অল। ডেটা ফর্ম্যাটটি নিজেই ডেটা থেকে কোড কোড হিসাবে সিরিয়ালাইজেশনের জন্য অনুরোধ করছে dec
নিশ্চিত করার জন্য যে সিরিয়ালাইজেশন যথাসম্ভব ত্রুটিমুক্ত। I / O বিভিন্ন কারণে স্বভাবগতভাবে ঝুঁকিপূর্ণ: আমার ডিজাইনটি এটি ব্যর্থ হওয়ার জন্য আরও কীভাবে প্রবর্তন করে? যদি তা হয় তবে কীভাবে আমি এই ঝুঁকিগুলি হ্রাস করার জন্য ডিজাইনের রিফ্যাক্টর করতে পারি?
এই প্রকল্পটি সি ++ ব্যবহার করে। আপনি এটি পছন্দ করুন বা ঘৃণা করুন, ভাষার জিনিসগুলি করার নিজস্ব নিজস্ব পদ্ধতি রয়েছে এবং ডিজাইনের লক্ষ্য এই ভাষাটির সাথে কাজ করা নয়, এর বিপরীতে নয় ।
শেষ অবধি , প্রকল্পটি ডাব্লুএক্সউজেডসের শীর্ষে নির্মিত । আমি আরও সাধারণ ক্ষেত্রে প্রযোজ্য সমাধানের সন্ধান করছি, এই নির্দিষ্ট প্রয়োগটি সেই সরঞ্জামকিটটির সাথে সুন্দরভাবে কাজ করা উচিত।
এরপরে সি ++ তে লিখিত ক্লাসগুলির একটি খুব সাধারণ সেট যা নকশাটি চিত্রিত করে। এগুলি আমি এখনও অবধি আংশিকভাবে লিখেছি এমন প্রকৃত ক্লাস নয়, এই কোডটি আমি যে নকশাটি ব্যবহার করছি তা কেবল চিত্রিত করে।
প্রথমে কিছু নমুনা ডিএও:
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
// One widget represents one record in the application.
class Widget {
public:
using id_type = int;
private:
id_type id;
};
// Container for widgets. Much more than a dumb container,
// it will also have indexes and other metadata. This represents
// one data file the user may open in the application.
class WidgetDatabase {
::std::map<Widget::id_type, ::std::shared_ptr<Widget>> widgets;
};
এরপরে, আমি ডিএও পড়তে এবং লেখার জন্য খাঁটি ভার্চুয়াল ক্লাস (ইন্টারফেস) সংজ্ঞায়িত করি। ধারণাটি হ'ল ডেটা ( এসআরপি ) থেকে ডেটা সিরিয়ালাইজেশন বিমূর্ত করা ।
class WidgetReader {
public:
virtual Widget read(::std::istream &in) const abstract;
};
class WidgetWriter {
public:
virtual void write(::std::ostream &out, const Widget &widget) const abstract;
};
class WidgetDatabaseReader {
public:
virtual WidgetDatabase read(::std::istream &in) const abstract;
};
class WidgetDatabaseWriter {
public:
virtual void write(::std::ostream &out, const WidgetDatabase &widgetDb) const abstract;
};
শেষ অবধি, এখানে কোডটি পছন্দসই I / O প্রকারের জন্য উপযুক্ত পাঠক / লেখক পায়। পাঠক / লেখকের উপশ্রেণীও সংজ্ঞায়িত হবে তবে এগুলি নকশা পর্যালোচনায় কোনও যোগ করে না:
enum class WidgetIoType {
BINARY,
JSON,
XML
// Other types TBD.
};
WidgetIoType forFilename(::std::string &name) { return ...; }
class WidgetIoFactory {
public:
static ::std::unique_ptr<WidgetReader> getWidgetReader(const WidgetIoType &type) {
return ::std::unique_ptr<WidgetReader>(/* TODO */);
}
static ::std::unique_ptr<WidgetWriter> getWidgetWriter(const WidgetIoType &type) {
return ::std::unique_ptr<WidgetWriter>(/* TODO */);
}
static ::std::unique_ptr<WidgetDatabaseReader> getWidgetDatabaseReader(const WidgetIoType &type) {
return ::std::unique_ptr<WidgetDatabaseReader>(/* TODO */);
}
static ::std::unique_ptr<WidgetDatabaseWriter> getWidgetDatabaseWriter(const WidgetIoType &type) {
return ::std::unique_ptr<WidgetDatabaseWriter>(/* TODO */);
}
};
আমার নকশার বর্ণিত লক্ষ্য অনুযায়ী, আমার একটি নির্দিষ্ট উদ্বেগ রয়েছে have সি ++ স্ট্রিমগুলি পাঠ্য বা বাইনারি মোডে খোলা যেতে পারে, তবে ইতিমধ্যে খোলার স্ট্রিমটি চেক করার কোনও উপায় নেই। কোনও এক্সএমএল বা জেএসএন পাঠক / লেখককে বাইনারি স্ট্রিম সরবরাহ করা প্রোগ্রামার ত্রুটির মাধ্যমে এটি সম্ভব হয়েছিল। এটি সূক্ষ্ম (বা এত সূক্ষ্ম নয়) ত্রুটিগুলির কারণ হতে পারে। আমি কোডটি দ্রুত ব্যর্থ হওয়ার পক্ষে পছন্দ করব, তবে আমি নিশ্চিত নই যে এই নকশাটি এটি করবে।
এর চারপাশের একটি উপায় হ'ল পাঠক বা লেখকের কাছে স্ট্রিমটি খোলার দায়িত্বটি অফলোড করা যেতে পারে তবে আমি বিশ্বাস করি যে এসআরপি লঙ্ঘন করে কোডটি আরও জটিল করে তুলবে। ডিএও লেখার সময় লেখকের স্ট্রিমটি কোথায় চলছে সেদিকে খেয়াল করা উচিত নয়: এটি কোনও ফাইল, স্ট্যান্ডার্ড আউট, এইচটিটিপি প্রতিক্রিয়া, একটি সকেট, যে কোনও কিছু হতে পারে। সিরিয়ালাইজেশনের যুক্তিতে এই উদ্বেগটি একবারে সংশ্লেষিত হয়ে গেলে এটি আরও জটিল হয়ে ওঠে: নির্দিষ্ট ধরণের প্রবাহ এবং কোন নির্মাণকারীকে কল করতে হবে তা অবশ্যই তা জানতে হবে।
এই বিকল্পটি বাদ দিয়ে, আমি নিশ্চিত নই যে এই বিষয়গুলি সহজ, নমনীয় এবং মডেলগুলি ব্যবহার করে এমন কোডগুলিতে যুক্তি ত্রুটিগুলি রোধ করতে সাহায্য করার জন্য এর চেয়ে ভাল উপায় কী হতে পারে।
ব্যবহারের ক্ষেত্রে যার সমাধানটি একীভূত করতে হবে তা হল একটি সরল ফাইল নির্বাচন ডায়ালগ বাক্স । ব্যবহারকারী ফাইল মেনু থেকে "ওপেন ..." বা "হিসাবে সংরক্ষণ করুন ..." নির্বাচন করে এবং প্রোগ্রামটি উইজেটডাটাবেস খুলে বা সংরক্ষণ করে। স্বতন্ত্র উইজেটগুলির জন্য "আমদানি ..." এবং "রফতানি ..." বিকল্পগুলিও থাকবে।
ব্যবহারকারী খোলার বা সংরক্ষণের জন্য কোনও ফাইল নির্বাচন করেন, ডাব্লুএক্সউজেডস কোনও ফাইলের নাম ফিরিয়ে দেবে। এই ইভেন্টটির প্রতিক্রিয়া জানানো হ্যান্ডলারটি অবশ্যই সাধারণ উদ্দেশ্য কোড হতে হবে যা ফাইলের নাম নেয়, একটি সিরিয়ালাইজার অর্জন করে এবং ভারী উত্তোলন করার জন্য একটি ফাংশনকে কল করে। আদর্শভাবে এই নকশাটিও কাজ করবে যদি অন্য কোনও টুকরো কোডটি নন-ফাইল I / O সম্পাদন করে, যেমন সকেটের উপর দিয়ে কোনও মোবাইল ডিভাইসে উইজেটডাটাবেস পাঠানো।
একটি উইজেট তার নিজস্ব ফর্ম্যাট সংরক্ষণ করতে পারে? এটি বিদ্যমান ফর্ম্যাটগুলির সাথে হস্তক্ষেপ করতে পারে? হ্যাঁ! উপরের সবগুলো. ফাইল ডায়লগে ফিরে গিয়ে মাইক্রোসফ্ট ওয়ার্ড সম্পর্কে চিন্তা করুন। মাইক্রোসফ্ট তারা নির্দিষ্ট বাধা থাকা সত্ত্বেও ডওএক্সএক্স ফর্ম্যাটটি বিকাশ করতে মুক্ত ছিল। একই সাথে ওয়ার্ডটি উত্তরাধিকার এবং তৃতীয় পক্ষের ফর্ম্যাটগুলি (যেমন পিডিএফ) পড়ে বা লিখতে পারে। এই প্রোগ্রামটি আলাদা নয়: আমি যে "বাইনারি" ফর্ম্যাটটির কথা বলি তা গতির জন্য নকশাকৃত একটি এখনও নির্ধারিত অভ্যন্তরীণ বিন্যাস। একই সময়ে, এটির ডোমেনে (প্রশ্নের অপ্রাসঙ্গিক) ওপেন স্ট্যান্ডার্ড ফর্ম্যাটগুলি পড়তে এবং লিখতে সক্ষম হতে হবে যাতে এটি অন্যান্য সফ্টওয়্যার দিয়ে কাজ করতে সক্ষম হয়।
শেষ অবধি, উইজেটের এক প্রকার রয়েছে। এটিতে চাইল্ড অবজেক্ট থাকবে তবে সেগুলি এই সিরিয়ালাইজেশন যুক্তি দ্বারা পরিচালিত হবে। প্রোগ্রামটি কখনই উইজেট এবং স্প্রোকেট লোড করবে না । এই নকশাটি কেবল উইজেট এবং উইজেট ডেটাবেসগুলির সাথে সম্পর্কিত হতে হবে।