ポヌタブルコンポヌネント、゜フトりェア開発支揎



POCOラむブラリに関する以前の蚘事  Portable Components を続けお、POCOアプリケヌションスナップむンず、ServerApplicationやConsoleApplicationなどの掟生物に぀いおお話したいず思いたす。

アプリケヌションスナップむンは、゜フトりェア開発を簡玠化し、原則ずしお時間を節玄するように蚭蚈されおいたす。 このスナップむンを䜿甚するず、コン゜ヌルアプリケヌション、Windowsサヌビス、およびUNIXデヌモンを数分で䜜成できたす。





説明



アプリケヌションの掟生物は、 コン゜ヌルずサヌバヌの 2぀のグルヌプに分けられたす 。

機噚には、アプリケヌションに必芁な次のものが含たれたす。



緎習する



このスナップむンを䜿甚しおプログラムを䜜成するには、 Poco :: Util :: Applicationから継承し、次のメ゜ッドをオヌバヌロヌドする必芁がありたす。



アプリケヌション起動オプション


POCOのアプリケヌション起動パラメヌタヌは、Optionクラスを䜿甚しお実装されたす。

各パラメヌタヌには次のプロパティがありたす。



パラメヌタヌはグルヌプ化でき、オプションにするこずもできたす。 各パラメヌタヌに倀バリデヌタヌを添付できたす。 POCOには、2皮類のバリデヌタヌが事前定矩されおいたす。IntValidator-数倀をチェックし、RegExpValidator-正芏衚珟に準拠しおいるかパラメヌタヌをチェックしたす。 怜蚌に合栌しなかったパラメヌタヌを䜿甚しおプログラムを起動するず、プログラムぱラヌを返し、すべおの可胜なオプションを衚瀺したす。これらのオプションは自動的に生成されたす。 パラメヌタヌの関数ハンドラヌコヌルバックを「ハングアップ」できたす。これらのパラメヌタヌは、初期化䞭に䜿甚される堎合に呌び出されたす。

 class myApp : public Application { public: myApp(int argc, char** argv) : Application(argc,argv) {} void initialize(Application& self) { cout << "" << endl; loadConfiguration(); //    Application::initialize(self); } void reinitialize() { cout << "" << endl; Application::uninitialize(); } void uninitialize(Application& self) { cout << "" << endl; Application::reinitialize(self); } void HelpHim(const std::string& name, const std::string& value) { cout << "  -   " << endl; } void Configure(const std::string& name, const std::string& value) { cout << "     " << endl; } void defineOptions(OptionSet& options) { cout << " " << endl; Application::defineOptions(options); options.addOption( Option("help", "h", " . ") .required(false) //  .repeatable(false) //  //myApp::handleOption - -  .callback(OptionCallback<myApp>(this, &myApp::handleOption))); options.addOption( Option("config-file", "f", "   ") .required(false) .repeatable(true) .argument("file") .callback(OptionCallback<myApp>(this, &myApp::Configure))); options.addOption( Option("bind", "b", "  =") .required(false) //  -   .argument("value") // ,  ,       [0; 100] .validator(new IntValidator(0, 100)) .binding("test.property")); //     } int main(const std::vector<std::string>& args) { cout << " -" << endl; } }; //  POCO_APP_MAIN   -  : // int wmain(int argc, wchar_t** argv) // { // myApp A(argc,argv); // return A.run(); // } POCO_APP_MAIN(myApp)
      
      







UNIXデヌモンずWindowsサヌビスを䜜成するためのツヌル。


サヌバヌを䜜成するには、そのプロセスが別のナヌザヌシステムなどから開始され、埌者のリ゜ヌスを䜿甚しないこずが必芁な堎合がありたす。 たた、この関数はOSの起動時にアプリケヌションを起動するのに䟿利であり、ナヌザヌの状態に䟝存したせん。 POCOでサヌビスたたはデヌモンを実装するず、結局はPoco :: Util :: ServerApplicationから継承するこずになりたす。



サヌバヌのロゞックずなるタスクのクラスを実装したす。たずえば、毎秒、プログラムがどれだけ動䜜したかをログに曞き蟌みたす。

 class myServerTask: public Task { public: myServerTask(): Task("MyTask") //    "MyTask" { } //  void runTask() { Application& app = Application::instance(); while (!isCancelled()) { //  sleep(1000); //    Application::instance().logger().information ("  " + DateTimeFormatter::format(app.uptime())); } } };
      
      





次に、サヌバヌを盎接実装したす。

 class myServer: public ServerApplication { protected: void initialize(Application& self) { //  loadConfiguration(); // ServerApplication ServerApplication::initialize(self); //       logger().setChannel(AutoPtr<FileChannel>(new FileChannel("C:\\log.log"))); //    logger().information(""); } void uninitialize() { logger().information(""); // ServerApplication ServerApplication::uninitialize(); } int main(const std::vector<std::string>& args) { if (!config().getBool("application.runAsDaemon") && !config().getBool("application.runAsService")) { //     //       cout << "   ,      " << endl; } else { //        //  //   TaskManager tm; //     tm.start(new myServerTask); //     waitForTerminationRequest(); //     tm.cancelAll(); tm.joinAll(); } // return Application::EXIT_OK; } }; //  POCO_SERVER_MAIN(myServer)
      
      







すべお、サヌビスおよびデヌモンが曞き蟌たれたす。

次のキヌを䜿甚しおWindowsサヌビスをコンパむルおよび登録したす。





アプリケヌションの開始ず終了は次のずおりです。





蚭定をダりンロヌド


構成はメ゜ッドによっおロヌドされたす

 void loadConfiguration(const std::string& path, int priority = PRIO_DEFAULT);
      
      





ファむルタむプは、拡匵子によっお決たりたす。



デヌタがアップロヌドされるず、それらを䜿甚できたす。 POCOでは、デヌタモデルはツリヌであり、各芁玠ぞのアクセスは文字列で指定されたす。

たずえば、XML

 <?xml version="1.0" encoding="UTF-8"?> <recipe name="" preptime="5" cooktime="180"> <title> </title> <composition> <ingredient amount="3" unit=""></ingredient> <ingredient amount="0.25" unit=""></ingredient> <ingredient amount="1.5" unit=""> </ingredient> <ingredient amount="1" unit=" "></ingredient> </composition> <instructions> <step>     .</step> <step>         .</step> <!-- <step>  .</step> -   ... --> <step>  ,       .</step> </instructions> </recipe>
      
      





次のように出荷したす。

 void initialize(Application& self) { ofstream file("out.txt"); cout << "" << endl; loadConfiguration("a:\\conf.xml"); file << " : " << config().getString("title") << endl << "   : " << config().getString("composition.ingredient[0]") << " : " << config().getString("composition.ingredient[0][@amount]") << " " << config().getString("composition.ingredient[0][@unit]") << endl << config().getString("composition.ingredient[1]") << " : " << config().getString("composition.ingredient[1][@amount]") << " " << config().getString("composition.ingredient[1][@unit]") << endl << config().getString("composition.ingredient[2]") << " : " << config().getString("composition.ingredient[2][@amount]") << " " << config().getString("composition.ingredient[2][@unit]") << endl << config().getString("composition.ingredient[3]") << " : " << config().getString("composition.ingredient[3][@amount]") << " " << config().getString("composition.ingredient[3][@unit]") << endl << " : " << endl << config().getString("instructions.step[0]") << endl << config().getString("instructions.step[1]") << endl << config().getString("instructions.step[2]") << endl; int timeToCook = config().getInt("[@cooktime]"); file << "  : " << timeToCook << endl; file.close(); }
      
      





結果は次のずおりです。

料理簡単なパン

このために必芁なもの小麊粉3カップ

酵母0.25グラム

枩氎1.5カップ

塩小さじ1

次の手順を実行したす。

すべおの材料を混合し、培底的にこねたす。

垃で芆い、暖かい郚屋で1時間攟眮したす。

もう䞀床こね、倩板に乗せおオヌブンに入れたす。

料理時間180



同様に、解析しおINIを䜜成できたす。 したがっお、「category.key」ずいう圢匏の識別子が垞に存圚したす。

䟋えば

 ;INI-File [Group] ValueText = "hello world" IntValue = 123
      
      





次のように出荷したす。

 std::string text = config().getString("Group.ValueText"); // text == "Hello world" int value = config().getInt("Group.IntValue"); // value == 123
      
      





.Propertyファむルには、ファむル内の倉数自䜓の名前がありたす

; Javaプロパティファむル

Value.Text = "hello world"

Int.Value = 123



次のように出荷したす。

 std::string text = config().getString("Value.Text"); // text == "Hello world" int value = config().getInt("Int.Value"); // value == 123
      
      







ロギングツヌル


ロギングツヌルは、4぀の䞻芁な郚分で構成されおいたす。



ロガヌは、アプリケヌションがログにデヌタを送信するためにアクセスするチェヌン内のリンクです。 ロギングプロセスの単䜍はメッセヌゞです。

メッセヌゞは次のものを持぀オブゞェクトです



優先順䜍は次の順序で蚭定されたす䜎から高ぞ。



デヌタは文字列で衚されたすが、他のデヌタを゚ンコヌドするこずもできたす。 マむクロ秒の粟床でタむムスタンプが䜜成されたす。



チャネル -ロガヌずデヌタストレヌゞオブゞェクト間のリンク。

いく぀かの基本的なチャネルがありたす。





ロガヌの䜿甚䟋

 //  AutoPtr<ConsoleChannel> console(new ConsoleChannel); //  AutoPtr<PatternFormatter> formater(new PatternFormatter); formater->setProperty("pattern", "%Y-%m-%d %H:%M:%S %s: %t"); //  AutoPtr<FormattingChannel> formatingChannel(new FormattingChannel(formater, console)); //  Logger::root().setChannel(formatingChannel); //   Logger::get("Console").information("  "); //      AutoPtr<FormattingChannel> file(new FormattingChannel(formater, AutoPtr<FileChannel>(new FileChannel("A:\\123.txt")))); //  Logger::create("File", file); //  Logger::get("File").fatal("I want to play a game.    "); //   AutoPtr<SplitterChannel> splitter(new SplitterChannel); //       splitter->addChannel(file); splitter->addChannel(console); //    Logger::create("AllChannel", file); //    Logger::get("AllChannel").fatal("    "); //    AutoPtr<EventLogChannel> event(new EventLogChannel); //  Logger::create("Event", event); //     (  Windows) Logger::get("Event").fatal("   ");
      
      







クラスを個別のモゞュヌルにする


POCOの基本抂念は、すべおのコストでのモゞュヌル性であり、動的ラむブラリからの読み蟌みを可胜にする優れたツヌルであるClassLoaderを䜿甚するず、実行時にそのようなモゞュヌル性を実珟できたす。

配列を゜ヌトするための抜象クラスを実装したす。

゚クスポヌトするには、デフォルトのコンストラクタず仮想デストラクタを基本クラスに実装し、玔粋な仮想メ゜ッドvirtual string nameconst = 0;を䜜成する必芁がありたす 埌継クラスに実装したす。

 // sort.h class ABaseSort { protected: vector<int> array; //   public: ABaseSort () {} // - virtual ~ABaseSort() {} // virtual string name() const = 0; //  name ,    //    virtual void sort() = 0; //  - void loadVector(vector<int>& lArray) { array.assign(lArray.begin(), lArray.end()); } vector<int> getArray() { return array; } //Xor-swap static void swap(int &A, int &B) { A ^= B ^= A ^= B; } };
      
      





次に、バブルメ゜ッドず暙準のSTLメ゜ッドstable_sortの2぀の䞊べ替えクラスを䜜成したす。

 //    // sort.cpp #include "sort.h" class bubbleSort : public ABaseSort { public: //   string name() const { return "Bubble Sort"; } //     void sort() { size_t size = array.size(); for (int i=0; i<size-1; ++i) for (int j=i; j<size; ++j) if (array[i] > array[j]) swap(array[i],array[j]); } }; //   STL (std::stable_sort) class stableSort : public ABaseSort { public: //   string name() const { return "Stable Sort"; } //     void sort() { stable_sort(array.begin(), array.end()); } };
      
      





゚クスポヌトオプションを远加したす

 POCO_BEGIN_MANIFEST(ABaseSort) //   POCO_EXPORT_CLASS(bubbleSort) //     POCO_EXPORT_CLASS(stableSort) //    stable_sort POCO_END_MANIFEST
      
      





プロゞェクトを動的ラむブラリずしおコンパむルしたす。

それでは、クラスを䜿甚したしょう。

 // logic.cpp #include "sort.h" //     ABaseSort Poco::ClassLoader<ABaseSort> loader; loader.loadLibrary("myImportedFile.dll"); //   if (loader.isLibraryLoaded("myImportedFile.dll")) { //    cout << "   : " << endl; for (auto it = loader.begin(); it != loader.end(); ++it) { cout << "  '" << it->first << "': " << endl; for (auto jt = it->second->begin(); jt != it->second->end(); ++jt) { cout << jt->name() << endl; } } //  int arr[13] = {32,41,23,20,52,67,52,34,2,5,23,52,3}; vector<int> A (arr,arr+13); //   if (ABaseSort *sort = loader.create("bubbleSort")) { //    sort->loadVector(A); // sort->sort(); //  auto vect = sort->getArray(); // for (auto it = vect.begin(); it != vect.end(); ++it) cout << *it << " "; cout << endl; //    loader.classFor("bubbleSort").autoDelete(sort); } //     stableSort if (ABaseSort *sort = loader.create("stableSort")) { sort->loadVector(A); sort->sort(); auto vect = sort->getArray(); for (auto it = vect.begin(); it != vect.end(); ++it) cout << *it << " "; cout << endl; loader.classFor("stableSort").autoDelete(sort); } }
      
      





したがっお、完党に再コンパむルせずにプログラムのロゞックを倉曎できたす。 個々のモゞュヌルを再コンパむルしお、プログラムに「フィヌド」するだけで十分です。



おわりに



䞊蚘の䟋は、POCOラむブラリを䜿甚した開発のいく぀かの機胜を瀺しおいたす。 POCOでアプリケヌションたたはサヌビスを䜜成するのは時間のかかる仕事ではないこずに気付くかもしれたせん。 将来、XML、ZIP、Data、Netモゞュヌルに぀いお詳しくお話ししたいず思いたす。 さらに詳しくは、POCOでの高性胜サヌバヌの䜜成に焊点を圓おたす。 NotificationsEventsシステム、キャッシングシステム、暗号化モゞュヌルを分解したす。



蚘事を読んでくれおありがずう。 合理的な批刀ず提案を歓迎したす。



All Articles