複雑なソフトウェアプロジェクトは、外部依存のために複数のリポジトリにまたがっていることがよくある。これはそれ自体で課題だ。GoogleのWebRTCエンジニアであるPatrik Höglund氏は、Chromeのような何十ものサードパーティ製ライブラリを使用したソフトウェアを開発するとき、Googleがどのようにしているか説明した。
マルチリポジトリのプロジェクト管理の複雑さは、外部依存の変更を追いかける必要があることに起因している。それらのコードベースがどんどん変わっているときはなおさらだ。このような場合、依存しているものの更新を単にスキップすることはできない。重要な修正や新機能が取り込まれなくなるためだ。また外部ライブラリをあまり更新していないと、蓄積された変更がアプリケーションを壊し、すべての変更に追従するのに多大な犠牲を払うリスクがある。
Googleでは、新たな依存バージョンにすることを「ローリング」と呼んでいる。ローリングはChromeのコードを新しいAPIに合わせて変更するのに必要なプロセスだが、Chromeのテストスイートを壊してしまうおそれがあった。もちろん、これはテストスイートをフル実行するまでわからない。そして、これには時間がかかりすぎる。そこで、Chromeテストを壊すのを避けるため、開発者は専用のBot (継続的ビルド/テストマシン) を使って、ローリングによって発生するおそれのある問題を検出している。
これは「FYI Bot」と呼ばれ、固定のバージョンを使わないようになっている。WebRTCの場合、WebRTC HEADが使われる。Botを実行すると、次のような結果が得られる。
- 成功 (グリーン): 新しいローリングはスムーズにいきそうだということを意味する。
- コンパイルに失敗: Chromeのコードを新しいAPIに合わせる必要があることを意味する。
- テストに失敗 (レッド): 何らかの意味的変更や、解決すべき新しいバグが見つかったことを意味する。
このプロセスをもっとスムーズに実行するため、Googleの開発者はFYI Botビルドが壊れにくくなるよう、新たなポリシーを追加した。だがこれは、新しいAPIに合わせてChromeのコードを変更するまで、Botは意味のある情報を返さない、という望まない結果をもたらした。この状態は何日も続くおそれがあった。この問題を解決するため、開発者はAPI Prime Directiveに従いはじめた。コンポーネントを進化させるとき、既存のクライアントを壊さないということだ。これを実現するひとつの方法は、既存のAPIを削除せずに、必要に応じて新しいAPIを追加することだ。たとえば、次のようなメソッドシグニチャがあるとする。
class WebRtcAmplifier {
...
int SetOutputVolume(float volume);
}
これを次のように変更しなければならない場合を考えよう。
class WebRtcAmplifier {
...
int SetOutputVolume(float volume, bool allow_eleven1);
}
既存のクライアントを壊さないため、次のようなAPIを追加する。
class WebRtcAmplifier {
...
int SetOutputVolume(float volume);
int SetOutputVolume(float volume, bool allow_eleven);
}
このポリシーのおかげで、Googleの開発者はBotが常にグリーンになるようにし、もしレッドになれば変更をロールバックすべきだとわかるようになった。