NuGetを使った解決法
NuGetを使うと、ライブラリの破壊的変更への対応手順は次のようになります(図5)。
1. 提供者が新たなバージョンのNuGetパッケージをアップする
ライブラリ提供者は、破壊的変更を加えたライブラリについて新たなバージョン番号を付与し、NuGetパッケージを作成します。そして、旧バージョンと同じように、NuGetのプライベート・リポジトリに配置します。
この段階では、まだ各機能は旧バージョンのライブラリを参照しているため、ビルドエラーは発生しません。
2. 利用者がNuGetパッケージをアップデートする
利用者側でNuGetのUpdate-Packageコマンドを使い、ライブラリのNuGetパッケージをアップデートします(リスト1)。
PM> Update-Package (パッケージ名)
すると、プライベート・リポジトリより新たなバージョンのNuGetパッケージを取得し、packagesフォルダーへの展開と参照設定が行われます。この段階で、初めてライブラリの破壊的変更により、ビルドエラーが発生します。しかし、変更前のNuGetパッケージを参照している他の機能への影響はありません。
3. 利用者がソースコードの修正を行う
ライブラリ提供者側ではなく、利用者の側でライブラリ変更に伴うソースコード修正を行い、ビルドエラーを解消します。
4. 修正後のソースコードをコミットする
ビルドエラーを解消した後のソースコードをVCSにコミットします。このとき、使用しているNuGetパッケージのバージョン情報も一緒にコミットされます。そのため、他のメンバーが同じ機能をチェックアウトすると、新たなバージョンのNuGetパッケージを使用して作業を続けることができます。
以上の2~4の手順を、ライブラリを参照している機能すべてに対して行っていきます。この方法により、dll直接配布する際の問題点が、次のように解消されます。
1) ビルドエラーが局所的になる
各機能は、それぞれが持つpackagesフォルダーの中のdllファイルを参照するため、ライブラリの変更が他の機能に影響しません。
2) 順番に対応作業が行える
1)の結果、ライブラリ変更への対応を一度に行う必要がなくなり、徐々に進めることができるようになります。
NuGet採用時の問題点
NuGetを使った対応はいいこと尽くめのように見えますが、一点注意が必要です。
チーム開発において、定期的にリポジトリから最新のソースファイルを取得してビルドを行う、いわゆる自動ビルド環境を用意することがあると思います。その自動ビルドには大きく分けて次の2つのやり方があります。
①フルビルド
ライブラリを含む全モジュールを一からビルドする。当然、各機能をビルドするときのライブラリは、このビルドの結果生成されたdllファイルを参照する。
②差分ビルド
前回のビルドから変更された部分のみビルドする。各機能のビルドはそれぞれがインストールしたNuGetパッケージに含まれるdllを参照する。
このうち①のフルビルドを行う際、ライブラリの破壊的変更にまだ対応が追い付いていない機能があると、そこでビルドに失敗してしまいます(図6)。
この問題への対処は単純ではなく、例えば次のような対応が必要となるでしょう。
1) 差分ビルドを導入する
もしフルビルドしか行っていないようなら、①の差分ビルドを導入します。これにより、差分ビルドだけ行う場合は、ライブラリの破壊的変更で自動ビルドを壊すことはなくなります。
2) フルビルドの頻度を下げる
とはいえ、差分ビルドだけでは心元ありません。ですので、普段は差分ビルドを行い、フルビルドは頻度を下げて行えばよいでしょう。例えば日次やVCSのコミットを起点に行うビルドは差分ビルド、週次やVCSのブランチ、タグを起点に行うビルドはフルビルドにする、といったやり方が考えられます。
あくまでこの対応は一例です。実際にチーム開発を行うときの自動ビルドは、そのプロジェクトの前提条件によって構成や運用を調整しなくてはなりません。この記事の内容を参考に、自らの環境ではどのように対応すればよいか、検討してみてください。
前回も少し紹介しましたが、Visual Studioにはビルド時に自動的にNuGetパッケージを復元する機能が備わっています。しかし、.NETアプリケーションの自動ビルドにはMSBuildを使うのが一般的です。したがって、ただMSBuildでビルドするだけでは、NuGetパッケージは復元されません。
MSBuildによる自動ビルド時にNuGetパッケージを復元するには、「NuGetパッケージの復元の有効化」をした際に作成される、NuGet.targetsファイルの変更や環境変数の設定等が必要です。詳しくは、参考資料1)、2)のページなどを参考にしてください。


