「継続的インテグレーション」について

id:Ewigkeitのブログで、CIについてはここのブログ読んでね、と言及されたんですが、対象記事はCIについてあまり書かれておらず、しかも、古い記事を調べてみてもいい内容がなかったので、ここで改めて「継続的インテグレーション」について説明します。


継続的インテグレーション(以降、CI*1)」とはXPのベストプラクティスの一つです。
原典として、マーチン・ファウラーの論文があります。
ここでは頻繁にインテグレーション作業を行うと、少し難しく表現されていますが、ものすごく簡単に言いますと、デイリービルドやナイトリービルドのように1日に1回ビルドするのではなく、1日に何回もビルド*2を行う、ということです。
また、プロジェクトの後期に行われるモジュールの結合やシステムテストといったことも1日に何回も行います。
具体的な例として、

ということを上から順に何回もぐるぐる行います。
そして、そのサイクルを自動で行い、コンパイルやテストが失敗すると何かしらの手段で知らせてもらうようにすれば、すぐに問題箇所にとりかかる、ということを行います。


なぜ、CIを行うことがいいことなのでしょうか?
それは、コミット漏れやビルドを壊す修正が早期発見されるからです。
これらのことがずっと後に見つかったら、どうなりますか?
早期発見できれば、簡単な修正で済みますが、問題が先送りされればされるほど修正が困難になり、コストが増大しリスクが高まります。
問題を早期発見するためには自動で実行されやすいようにするため、ビルドはコマンド一発で出来る必要があり、テストの充実度が品質を左右します。
また、小まめに結合を行うため、プロジェクトの最後の最後でビックバン結合を行うよりも、数段リスクが低減されます。
こういった特徴から、多人数での開発や、複数拠点での分散開発に有効なります。


しかし、なぜ最近になるまであまり注目されてこなかったのでしょうか?
それはものすごく手間がかかるからです。
されど、達人プログラマーたちは、CIという概念がまだ確立する前からも、CIのようなことをやっていました。
自分たちでシェルスクリプトを書いて、コマンド一発でソースコードをチェックアウトしてビルドできるようにしたり、OSの機能を使ってビルドのスケジューリングを行ったり、メールを使ったビルドが壊れた場合通知する、そんなシステムを個々人が作っていました。
扱うツールが変わると作り直しということもあり、また、作った人でないとメンテナンスがしにくい問題もありました。


ここ数年でCIをとりまく状況は変わりました。
CIを行うためのツール類が出回り、一から作るよりも簡単にCI環境を作れるようになったからです。
第一世代CIツールの代表格のCruiseControlや、そのあとの世代のHudsonやContinuum、TeamCityやBanboo、BuildBotなどなど、商用、OSSともに数多く存在するようになりました。
また、CIを行う上で大事な点として、我々を取り巻く計算機の価格が低下している点です。
長いスパンでみると、人件費は緩やかな右肩上がりなのに対し、計算機はずっと下がり続けています。
計算機にできる仕事を人にさせるのは、費用対効果としてよろしくないですよね?
CIツールを使うことで、ビルドなどの自動で行える作業については計算機に大いに働いてもらう、ということが可能になります。
また、ツールを使うことで、トラックナンバーを増やせるというメリットもあります。
この人がいないとビルドできない、この人がいないとメンテナンスしにくい、ということから解放されます。


CIはあくまでもXPのベストプラクティスの一つです。
それ単体でも有効ですが、他のTDDやスクラムといったプラクティスと一緒に行うと、効果は倍増すると考えています。
そして、そのXPのマインドがなければ、CIは単なる儀式になり下がり、コミット漏れなどのミスを行った人を断罪するための手段になってしまうかもしれません。
そういうことになるなら、やらないほうがマシです。


長くなりましたが、まとめると、

  • CIは頻繁にビルドや結合、テストを行う
  • CIをすることで、問題の早期発見を行い、先送りしない→結果としてコストやリスクの抑制
  • CIをするために、コマンド一発のビルドとテストが大事
  • CIは多人数、分散開発に有効
  • CIツールを使うことで、簡単に環境を作れる
  • ツールを使うことで、トラックナンバーを減らせる
  • CIは他のプラクティスと組み合わせよう
  • CIもマインドが大事

拙いながらもCIについての説明は以上です。
とっつきにくいものかもしれませんが、そんな大層なものではないし、Hudsonのように導入がものすごく簡単なものがあるので、小さいところから始められてはどうでしょうか?

*1:Continuous Integration、略してCI

*2:ここでは、一連の複数の成果物(jarなど)が作成され、Unitテストを通す作業を指しています