62

現在、私はレガシーバージョン管理システムから移行し、グループのプロジェクトをMercurialに移行しています。移動するコードの種類の一例として、25以上のプロジェクトのVisual Studioソリューションがあり、すべて共通のコードに依存するいくつかの個別のアプリケーション領域が含まれています。Stack Overflowを見ると、私が見つけた最も近い質問はこれでしたが、バージョン管理についてのみ言及していました。Mercurialを使用してこれらの依存関係を管理する特定の実装手法について、もう少しアドバイスを探しています。

依存関係の簡略化されたビューは、次のようになります。(これは説明と例にすぎません。実際の依存関係はかなり複雑ですが、本質的に類似しています。)

                     Common Lib 1
                    /      |      \
                ----       |       -----   
               /           |        \   \
            App 1    Common Lib 2    \ App 2
                       /   |   \      \
                -------    |    ------ |
               /           |          \|
             App 3       App 4      App 5

Common Libモジュールは共有コードになります-これは、コンパイル時と実行時の両方で、すべてのアプリ間で同時に使用されるDLLまたはSOまたはその他のライブラリになります。そうでなければ、アプリケーションは互いに独立して実行できます。

Mercurialリポジトリの設定にはいくつかの目標があります。

  • 重要な各アプリケーションまたはコンポーネントグループに独自のリポジトリを提供します。
  • 各リポジトリを自己完結型にします。
  • プロジェクトの合計を自己完結型にします。
  • コードベース全体を一度に簡単に構築できるようにします。(最終的に、これらのプログラムとライブラリはすべて1つのインストーラーになります。)
  • 単純にする。

もう1つのポイントは、これらのプロジェクトごとに個別のリポジトリがあるサーバーをセットアップしていることです。

これらのプロジェクトをレイアウトする方法はいくつかあります。

1.すべてを含む「シェル」リポジトリを作成します。

これは、URLベースのサブリポジトリを使用します(たとえば、.hgsubでは、次のようにします)。レイアウトすると、次のようになります。App1 = https://my.server/repo/app1

+---------------------------+
| Main Repository           |
| | +---------------------+ |
| +-| Build               | |
| | +---------------------+ |
| | +---------------------+ |
| +-| Common Lib 1        | |
| | +---------------------+ |
| | +---------------------+ |
| +-| Common Lib 2        | |
| | +---------------------+ |
| | +---------------------+ |
| +-| App 1               | |
| | +---------------------+ |
| | +---------------------+ |
| +-| App 2               | |
| | +---------------------+ |
| | +---------------------+ |
| +-| App 3               | |
| | +---------------------+ |
| | +---------------------+ |
| +-| App 4               | |
| | +---------------------+ |
| | +---------------------+ |
| +-| App 5               | |
|   +---------------------+ |
+---------------------------+

シェルリポジトリの各メインフォルダには、プロジェクト領域ごとに1つずつサブリポジトリが含まれます。依存関係は相対的です。たとえば、App4はCommonLib 2を必要とするため、相対パスを使用してその共通ライブラリを参照します。

このアプローチの長所:

  • 各ライブラリは一度だけプルダウンされます。
  • Mercurialのサブレオは、同じバージョンのライブラリがすべてのプロジェクトで自動的に使用されるようにします。これは、そのサブリポジトリの1つのバージョンのみがプロジェクトに存在するためです。
  • 各リソースを見つけるのは簡単です。

このアプローチの短所:

  • アプリを単独で操作することはできません。たとえば、アプリ2で作業していて、共通ライブラリを変更する必要がある場合、他のすべてのアプリは今すぐそれらの変更を行う必要があります。
  • アプリリポジトリを単独でプルする場合、それを構築する場合は、他にどのような依存リポジトリが必要かを手動で把握(または把握)する必要があります。
  • 依存関係は強く分離されていません。すべての機能を簡単に取得できるため、どこにでも新しい機能を挿入したくなるでしょう。

2.依存するサブリポジトリを完全に封じ込めます。

このアプローチでは、各アプリケーションは(以前と同様に)独自のリポジトリを持ちますが、今回はサブリポジトリも含まれます。1つは独自のソース用で、もう1つは依存するサブリポジトリごとです。全体的なリポジトリには、これらの各プロジェクトリポジトリが含まれ、ソリューション全体を構築する方法がわかります。これは次のようになります。

+-----------------------------------------------------------------------+
| Main Repository                                                       |
| +--------------------+ +--------------------+ +--------------------+  |
| | Build              | | Common Lib 1       | | Common Lib 2       |  |
| +--------------------+ | | +--------------+ | | | +--------------+ |  |
|                        | +-| Lib 1 Source | | | +-| Common Lib 1 | |  |
|                        |   +--------------+ | | | +--------------+ |  |
|                        |                    | | | +--------------+ |  |
|                        |                    | | +-| Lib 2 Source | |  |
|                        |                    | |   +--------------+ |  |
|                        +--------------------+ +--------------------+  |
| +--------------------+ +--------------------+ +---------------------+ |
| | App 1              | | App 2              | |  App 3              | |
| | | +--------------+ | | | +--------------+ | |  | +--------------+ | |
| | +-| Common Lib 1 | | | +-| Common Lib 1 | | |  +-| Common Lib 2 | | |
| | | +--------------+ | | | +--------------+ | |  | +--------------+ | |
| | | +--------------+ | | | +--------------+ | |  | +--------------+ | |
| | +-| App 1 Source | | | +-| App 2 Source | | |  +-| App 3 Source | | |
| |   +--------------+ | |   +--------------+ | |    +--------------+ | |
| +--------------------+ +--------------------+ +---------------------+ |
| +--------------------+ +--------------------+                         |
| | App 4              | | App 5              |                         |
| | | +--------------+ | | | +--------------+ |                         |
| | +-| Common Lib 2 | | | +-| Common Lib 1 | |                         |
| | | +--------------+ | | | +--------------+ |                         |
| | | +--------------+ | | | +--------------+ |                         |
| | +-| App 4 Source | | | +-| Common Lib 2 | |                         |
| |   +--------------+ | | | +--------------+ |                         |
| +--------------------+ + | +--------------+ |                         |
|                        | +-| App 5 Source | |                         |
|                        |   +--------------+ |                         |
|                        +--------------------+                         |
+-----------------------------------------------------------------------+

長所:

  • 各アプリケーションは、互いに独立して、単独で構築できます。
  • ライブラリの依存バージョンは、グローバルではなく、アプリごとに追跡できます。新しい依存関係を追加するには、プロジェクトにサブリポジトリを挿入するという明示的な操作が必要です。

短所:

  • 最終ビルドを行うとき、各アプリは異なるバージョンの共有ライブラリを使用している可能性があります。(一般的なlibサブリポジトリを同期するためのツールを作成する必要があるかもしれません。Eww。)
  • ソース全体を構築したい場合は、共有ライブラリを複数回プルダウンすることになります。Common Lib 1の場合、8回(!)プルする必要があります。

3.依存関係をサブリポジトリとして含めないでください-ビルドの一部としてそれらを取り込みます。

このアプローチは、共通ライブラリがビルドの一部としてのみプルされることを除いて、アプローチ1とよく似ています。各アプリは、必要なリポジトリを認識し、それらを共通の場所に配置します。

長所:

  • 各アプリはそれ自体で構築できます。
  • 共通のライブラリは一度だけプルする必要があります。

短所:

  • 各アプリで現在使用されているライブラリのバージョンを追跡する必要があります。これはサブレポ機能を複製します。
  • これをサポートするインフラストラクチャを構築する必要があります。つまり、ビルドスクリプトにさらに多くのものを投入する必要があります。うーん。

4.他に何がありますか?

それを処理する別の方法はありますか?より良い方法は?どのように試みて成功しましたか、どのように試みましたが嫌いでしたか?私は現在1に傾いていますが、アプリケーションの独立性の欠如は、それが可能であるはずなのに、本当に私を悩ませています。(オプション3のように)それを処理するためのスクリプトを書く必要がなく、大規模な重複コードのプルと依存関係の維持の悪夢なしにメソッド2をうまく分離する方法はありますか?

4

3 に答える 3

6

私の目には、依存関係の管理はプロジェクトの組織の重要な側面です。Mercurialのサブリポジトリ機能に基づいて、さまざまなソリューションを詳細に公開しました。私は、あなたが提供したすべての長所/短所に同意します。

SCMは依存関係の管理にはあまり適していないと思います。私はそのための専用ツールを持っていることを好みます(これはあなたの解決策n°3になります)。

私の現在のプロジェクトはJavaです。これはApacheAntで構築されており、最初に依存関係管理ツールとしてApacheIvyをセットアップしました。最終的に、セットアップは、共有ディレクトリ内のいくつかのIvy構成ファイルと、プロジェクトの各モジュールの依存関係をリストした1つのXMLファイルで構成されていました。IvyはAntターゲットから呼び出すことができるため、各モジュールに「依存関係の解決」と「ビルドされたアーティファクトのデプロイ」という2つの新しいアクションを追加しました。デプロイメントは、共有ディレクトリにbuid(アーティファクトと呼ばれる)の結果を追加します。依存関係の解決とは、モジュールの依存関係を推移的に解決し、解決されたアーティファクトをモジュールのソースの「lib」フォルダーにコピーすることを意味します。

IvyはJava依存関係の管理に固有ではないため、このソリューションはC++プロジェクトに適用できます。アーティファクトは何でもかまいません。C ++では、モジュールによって生成されるアーティファクトは次のようになります。

  1. 実行時のso/dll
  2. コンパイル時のヘッダーファイル。

これは完璧な解決策ではありません。Ivyのセットアップは簡単ではありません。ビルドスクリプトに使用する依存関係を指示する必要があり、デバッグ目的で依存関係のソースに直接アクセスすることはできません。しかし、最終的には独立したSCMリポジトリになります。

次に、私たちのプロジェクトでは、Ant +IvyからApacheMavenに切り替えました。これにより、ビルドと依存関係の管理の両方が処理されます。アーティファクトは、共有フォルダーではなく、ApacheArchivaにデプロイされます。これは大きな改善ですが、Javaプロジェクトでのみうまく機能します。

于 2011-05-17T11:36:34.813 に答える
2

(1)のように、各プロジェクトを独自のディレクトリに配置します。次に、依存関係の作業バージョンにタグを付け、次のようなビルド用にタグをファイルに保存します。

App1 / .dependencies:
CommonLib1タグ-20100515
CommonLib2タグ-20100510

App2 / .dependencies:
CommonLib1タグ-20100510
CommonLib2タグ-20100510

次に、ビルドスクリプトを使用して、特定のタグに基づいてライブラリをビルドし、それらのビルドされたライブラリをアプリケーションの派生オブジェクトとして含めます。ビルド時間が問題になる場合は、それらのライブラリで使用されているタグ付きバージョンを事前にビルドしてどこかに保存することができます。

注(データベーススキーマ、オブジェクトモデル、または製品ビルドを設計する場合、設計原則は同じです):

  • 他のプロジェクトのコードにリンクしないでください(カプセル化を解除します)
  • リポジトリにライブラリの複数のコピーを持たないでください(モジュール性)
于 2011-05-17T08:15:24.173 に答える
0

Subversionを使用して同様の問題を解決しました。

各アプリとそれぞれCommon Libに独自のリポジトリがあります。

すべてのアプリにはLibs、依存するdllを含むディレクトリがあります。

Common Libそのため、アプリは、新しいdllのセットが提供された場合にのみ更新を取得します。

ただし、依存するサブdllが正しいバージョンと一致する必要があるため、libフォルダーのアップグレードは簡単ではありません。

于 2011-05-18T12:13:36.637 に答える