web-dev-qa-db-ja.com

サイズ変更へのバイナリ依存を回避する方法

class A { public: int i; }; // A.h and defined in project libA.vcxproj (libA.dll)

以下のように、さまざまなプロジェクトで複数の場所でクラスAを使用しています。約100のプロジェクト。

include "A.h"
class UseA { public: A *a; UseA(){ a = new A(); } ~UseA() {delete a;} }

私の問題は、クラスAにメンバー変数を追加するたびに、クラスAのサイズが変更され、100プロジェクトの構築に時間がかかるため、すべてのプロジェクト(〜100)を構築する必要があることです。

単一のクラスのサイズ変更でこれほど多くのプロジェクトを構築することを回避するにはどうすればよいですか?また、libA.vcxprojで定義されているクラスAのような多くのクラスがあります。

2
user3136061

PIMPLイディオム に精通していますか?場合によっては、この正確な問題を解決できます。短いバージョンでは、すべてのプライベートメンバー変数を型への1つの不透明なポインターにラップするため、新しいプライベートメンバーを追加するときに、それほど多くの再コンパイルは必要ありません...

5
J Trana

まず、これが本当に必要であることを確認します。100回以上再利用される中央ライブラリがあると、そのライブラリのパブリックインターフェイスが頻繁に変更されない場合、または特定の時点でのみ変更される場合に、より適切に機能します。ライブラリを小さな部分に分割して、ある部分の変更が他の部分の依存プロジェクトに影響を与えないようにすることが可能かどうかを確認します。また、最初に「プライベート」でそのライブラリへの変更を開発し、そのライブラリの新しい「メジャーリリース」に対してのみ(明らかに依存プロジェクトの大部分に対して)それらを公開できるかどうかを確認します。

ただし、プロジェクトの依存関係が正しく、システムに必要であり、その中央ライブラリ(または中央クラス「A」)のパブリック部分を頻繁に拡張する必要があると仮定しましょう。次に、すべての依存プロジェクトを再コンパイルする必要があることを回避することはできません。ただし、通常は100個のプロジェクトすべてに同時に変更を加えることはないため、すべてを再コンパイルする必要はありませんローカルワークステーションで

この状況で必要なのは build server --SCCSからのすべての変更を自動的にチェックアウトし、バックグラウンドでの100個のプロジェクトすべてのフルビルド。このようなシステムをセットアップするには、適切に構造化された 自動ビルドプロセス も必要になります。うまくいけば、100個のプロジェクトをプロジェクトのグループに分割して、個別にコンパイルしてテストすることができます。そうでない場合は、最初にその問題を解決する必要があります。

少し時代遅れですが、よく読んでください: JohnLakosによる大規模C++ソフトウェア設計 。この本では、PIMPLイディオム Jtranaが言及 についても詳しく説明しますが、これはクラスのプライベート部分でのみ役立ち、例のようなパブリック部分では役立ちません。

5
Doc Brown

Doc BrownJ Trana による回答に加えて。

  • Doc Brownの回答は、ソフトウェア開発ではプロジェクト全体の再構築が非常に必要であると指摘しています。したがって、ビルドの自動化を回避するのではなく、使用して痛みを軽減するようにしてください。

  • Jトラナの答えは、カプセル化または 情報隠蔽 の形式です。クラスAのほとんどのユーザーが新しいメンバーにアクセスする必要がない場合は、次の手順を実行できます。

    • 新しいメンバーを非公開にする
    • 新しいメンバーをクラスAのプライベートサブメンバー内に配置し、Aのコンストラクターで初期化します。
    • 新しいメンバーにアクセサメソッド(ゲッターとセッター)を提供します。
    • C++ではヘッダーファイルを変更すると再構築が必要になるため、これでもプロジェクト全体を再構築する必要があることに注意してください。
  • 私の提案#1(ベンダー固有)

    • 一部のC++コンパイラには、ビルドプロセスのパフォーマンスを向上させるためのオプションがあります。
    • 例: "インクリメンタルビルド"、 "複数のプロセスでビルド" など。
  • 私の提案#2:
    新しいメンバーを含む多くの小さな実験的変更を行うときに再構築に費やす時間を本当に削減する必要がある場合は、データメンバーをプロパティバッグに変換することを検討してください

    • プロパティバッグは、文字列からバリアント値までの辞書( std :: map )です。
    • クラスAがこのディクショナリのget/setメソッドを提供する場合、新しいキーの追加と削除には再構築は必要ありません。
    • ただし、欠点は次のとおりです。
      • クラスメンバーにアクセスする場合と比較して、ディクショナリの値の読み取りと書き込みが非常に遅くなります。
      • コンパイラはプロパティバッグに格納されているキーと値に対して名前チェックと型チェックを実行できないため、プロジェクト全体でエラーが発生しやすくなります。
      • 例:
        コンパイラは、存在しないクラスメンバーにアクセスしようとするバグをキャッチできます。
        コンパイラは、存在しない辞書キーにアクセスするバグを自動的にキャッチしません。プログラマーは、この状況を処理するためのコードを作成する必要があります。
4
rwong