6

この質問に対する私の答えは「いいえ」です。しかし、私の同僚は同意しません。

私たちは製品を再構築しており、近いうちに多くの重要な決定を下す必要があります。

私自身の作業のいくつかを行っているときに、POSIX API (スレッド、ミューテックス、セマフォ、および rw ロック) およびその他のユーティリティ クラスの一部を抽象化するために、いくつかの社内 C++ クラスがあることに気付きました。これらのクラスは基本的なものであり、Linux から移植されていないことに注意してください (移植性は再構築の要因です)。POCO C++ ライブラリも使用しています。

私はこれを同僚に知らせ、POCO に相当するクラスを優先して社内クラスを捨てることを提案しました。すでに使用しているライブラリを最大限に活用したい。彼らは、特定の C++ ライブラリに依存しないように、POCO を使用して社内クラスを実装し、必要に応じて追加の POCO クラスをさらに抽象化する必要があることを提案しました (将来の未知数を引用して、次のような別のライブラリ/フレームワークを使用したい場合はどうでしょうか)。 QTかBoostか、選んだものがダメだったり開発が不活発になったりしたらどうしよう…)

また、レガシー コードのリファクタリングも望んでおらず、独自のクラスで POCO の一部を抽象化することで、追加機能 (従来の OOP) を実装できます。これらの議論はどちらも高く評価できます。ただし、再コード化を行う場合は、大きくするか、家に帰る必要があると私は主張します。今がリファクタリングの時であり、特に私たちのクラスと POCO のクラス (スレッドなど) との類似性を考えると、それほど悪くはないはずです。機能が必要な拡張クラス?

私の同僚も、POCO 名前空間をいたるところに散らかしたくありません。ライブラリ/フレームワーク/ツールキットを選択し、それに固執する必要があると私は主張します。その機能を十分に活用してください。これは典型的なやり方ではないでしょうか?フレームワーク全体を抽象化する唯一のプロジェクトは、Freeswitch (APR への独自のインターフェイスを提供します) です。

1 つの提案は、私たちがお互いに公開する API、および潜在的な顧客に POCO を含めないようにすることですが、実装には存在します (これは理にかなっています)。

私たちの誰も、この種の設計上の決定を実際に経験したことはなく、それが現在の製品に現れています。幼い頃からこの仕事に携わってきたので、ここまで来るに至った直感はありますが、実践的な経験もありません。すでに解決された問題の貧弱な解決策は本当に避けたいです。

私の質問は次のようなものだと思います: 製品を構築するとき、a) ほとんどのコードのベースとなる主要なフレームワークを選択し、b) そのフレームワークが製品と密接に結合されていることを期待する必要がありますか? それがフレームワークのポイントではないでしょうか。(フレームワークとライブラリのどちらが POCO に適していますか?)

4

2 に答える 2

4

独自のラッパーを用意する価値があると思う状況は2つあります。

1)さまざまなシステム/ライブラリでのいくつかの異なるミューテックスの実装を確認し、それらがすべて満たすことができ、ソフトウェアに十分な共通の要件セットを確立しました。次に、その抽象化を定義し、柔軟性を事前に計画していることを確認して、それを1回以上実装します。コードの残りの部分は、現在の実装の付随的なプロパティではなく、抽象化のみに依存するように記述されています。私は過去にこれを行いましたが、コードではありませんが、お見せすることができます。

この「最も一般的でないインターフェイス」の典型的な例はrename、Windowsが既存のファイルに対するアトミックな名前変更を実装できないことに基づいて、ファイルシステムの抽象化を変更することです。したがって、将来、現在の* nix実装をそれができない実装に交換する可能性がある場合は、コードがアトミックな名前変更-置換に依存してはなりません。最初からインターフェースを制限する必要があります。

この種のインターフェースを正しく実行すると、新しいシステムへの、またはサードパーティのライブラリの依存関係を変更したいために、将来のあらゆる種類の移植が大幅に容易になります。ただし、フレームワーク全体はおそらく大きすぎてこれをうまく行うことができません。基本的に、独自のフレームワークを発明して作成することになります。これは簡単な作業ではなく、実際のソフトウェアを作成するよりも大きな作業になると考えられます。

2)モック/スタブ/シャム/スプーフィング/盗用/次の巧妙なテクニックが何であれ、テストでミューテックスをモックできるようにし、独自のラッパーを投げた方が簡単だと判断します。サードパーティのライブラリからのシンボル、または組み込みのシンボルをいじろうとしています。

関数を正確に模倣し、まったく同じパラメータを使用するwrap_pthread_mutex_init、などと呼ばれる独自の関数を定義すると、(2)を満たす可能性がありますが、(1)を満たさないことに注意してください。とにかく、(2)を適切に実行するには、ラッパーだけでなく、通常、依存関係をコードに挿入する必要があります。wrap_pthread_mutex_lockpthread_*

実際に柔軟性を提供せずに、柔軟性という見出しの下で余分な作業を行うことは、かなり時間の無駄です。あるスレッド環境を別のスレッド環境で実装することは、非常に困難であるか、またはおそらく不可能である可能性があります。将来、pthreadからstd::threadC ++に切り替えることにした場合、異なる名前でpthread APIとまったく同じように見える抽象化を使用しても、(ほぼ)何の助けにもなりません。

別の可能な変更として、Windowsに完全なpthreads APIを実装することはある程度可能ですが、実際に必要なものだけを実装するよりもおそらく難しいでしょう。したがって、Windowsに移植する場合、すべての抽象化により、残りのソフトウェアのすべての呼び出しを検索して置き換える時間を節約できます。それでも、(a)Windows用の完全なPosix実装をプラグインするか、(b)実際に必要なものを理解するための作業を行い、それだけを実装する必要があります。あなたのラッパーは実際の仕事には役立ちません。

于 2012-09-11T16:44:18.633 に答える
4

まず、公開する API には、POCO、boost、qt、または標準 C++ ライブラリの一部ではないその他の型が含まれていないことを確認してください。これは、ベース ライブラリには独自のリリース サイクルがあり、ライブラリのリリース サイクルとは異なるためです。ライブラリのユーザーがブーストも使用しているが、互換性のない別のバージョンを使用している場合、非互換性を解決するために時間を費やす必要があります。このルールの唯一の例外は、より広いフレームワークの一部としてリリースされるライブラリを設計する場合です。たとえば、POCO ツールキットへの追加です。この場合、ライブラリのリリースはツールキット全体のリリースに関連付けられています。

ただし、内部的には、抽象化しているライブラリが真の「コモディティ ライブラリ」でない限り、独自のラッパーの使用を避ける必要があります1 。. これは、外部ライブラリをクラスの背後に隠すと、ほとんどの場合、隠しているライブラリの抽象化レベルを模倣するためです。ラッパーを使用するコードは、外部ライブラリによって指定された抽象化のレベルに合わせてプログラムされます。ラッパーの背後にある実装を別のフレームワークに交換する場合、(1) 古いフレームワークの抽象化レベルに合わせて新しいフレームワークを適応させるか、(2) 実装方法を変更する必要がある可能性が非常に高くなります。ラッパーを使用します。どちらの場合も非常に疑わしいです: (1) を行う場合、おそらくそもそも切り替えるべきではなく、(2) を行う場合、ラッパーは役に立たないことがわかります。


1「商品ライブラリ」とは、同様の目的を果たす他のライブラリで一般的に見られる抽象化レベルを提供するライブラリを意味します。

于 2012-09-11T15:33:05.713 に答える