疎結合の暗黙的な変換 質問する

疎結合の暗黙的な変換 質問する

暗黙的な変換は、型が意味的に同等である場合に非常に役立ちます。たとえば、型をまったく同じように実装しているが、名前空間が異なる 2 つのライブラリを想像してください。または、あちこちに意味的な砂糖を除いてほとんど同一の型があるとします。この場合、その関数がテンプレートでない限り、一方の型をもう一方の型を使用するように設計された関数 (これらのライブラリの 1 つ) に渡すことはできません。そうでない場合は、何らかの方法で一方の型をもう一方の型に変換する必要があります。これは簡単なはずです (そうでなければ、型は結局それほど同一ではありません!) が、変換を明示的に呼び出すと、ほとんど意味のない関数呼び出しでコードが膨れ上がります。このような変換関数は実際にはいくつかの値をコピーするかもしれませんが、高レベルの「プログラマ」の観点からは基本的に何もしません。

暗黙的な変換コンストラクタと演算子は明らかに役立ちますが、結合が導入されるため、いずれかの型が他の型について認識する必要があります。通常、少なくともライブラリを扱う場合は、これらの型の 1 つが存在すると、他の型が冗長になるため、これは当てはまりません。また、常にライブラリを変更できるわけではありません。

現在、ユーザーコードで暗黙的な変換を機能させる方法については 2 つのオプションがあります。

  1. 1 つ目は、関係するすべての型に対して変換演算子と変換コンストラクター (および割り当て) を実装するプロキシ型を提供し、常にそれを使用することです。

  2. 2 番目は、ライブラリへの変更は最小限で済みますが、柔軟性が大幅に向上します。つまり、関係する各型に対して、オプションで外部から有効にできる変換コンストラクターを追加します。

たとえば、型にAコンストラクターを追加します。

template <class T> A(
  const T& src,
  typename boost::enable_if<conversion_enabled<T,A>>::type* ignore=0
)
{
  *this = convert(src);
}

テンプレート

template <class X, class Y>
struct conversion_enabled : public boost::mpl::false_ {};

デフォルトで暗黙的な変換を無効にします。

次に、2 つの型間の変換を可能にするために、テンプレートを特殊化します。

template <> struct conversion_enabled<OtherA, A> : public boost::mpl::true_ {};

convertADL を通じて見つけられる関数を実装します。

個人的には、強い反対意見がない限り、2 番目の方法を使用することを好みます。

さて、実際の質問に移りましょう。暗黙的な変換のために型を関連付ける推奨される方法は何ですか? 私の提案は良いアイデアですか? どちらのアプローチにも欠点はありますか? そのような変換を許可することは危険ですか? ライブラリ実装者は、その型が使用される可能性が最も高いソフトウェアで複製される可能性がある場合、一般に 2 番目の方法を提供する必要があります (ここでは、ほとんどのパッケージが 3D ベクトルを実装する 3D レンダリング ミドルウェアを考えています)。

ベストアンサー1

もし私がそれを気にするなら、他のオプションよりも「プロキシ」アプローチを好みます。

実のところ、私はこれが開発のあらゆる分野で大きな問題であることに気付き、特定のライブラリとのやり取り以外ではライブラリ固有の構造の使用を避ける傾向にあります。1つの例は、さまざまな異なるライブラリのイベント/シグナルの処理です。私はすでにboostを選択しました。積分自分のプロジェクト コードに、すべての通信に意図的に boost::signals2 を使用するようにしています。次に、使用している UI ライブラリへのインターフェイスを記述します。

もう 1 つの例は文字列です。世の中のあらゆる UI ライブラリは文字列を再発明しています。私のモデルとデータ コードはすべて標準バージョンを使用しており、そのような型で動作する UI ラッパーへのインターフェイスを提供しています... UI コンポーネントと直接対話する時点でのみ、UI 固有のバージョンに変換します。

これは、さまざまな独立した類似した構造によって提供される多くのパワーを活用できないことを意味し、これらの変換を処理するために多くの追加コードを記述しますが、これらのものがあらゆるものに浸透することを許可していないため、より優れたライブラリを見つけたり、プラットフォームを切り替える必要がある場合に、切り替えがはるかに簡単になるので、それだけの価値はあります。

つまり、私はすでにプロキシ アプローチを実践しているので、その方が好ましいです。使用している特定のライブラリから距離を置く抽象レイヤーで作業し、その抽象化を、そのライブラリとやり取りするために必要な詳細でサブクラス化します。私は常にそれを実行しているので、2 つのサード パーティ ライブラリ間で情報を共有したい小さな領域について疑問に思うことは、基本的にすでに答えが出ています。

おすすめ記事