意味的競合(セマンティックコンフリクト)
2011年8月4日
同僚や私がフィーチャーブランチについて話すのを聞いたことがある人は、私たちがこのパターンをあまり好んでいないことを知っているでしょう。私たちの反対意見の重要な部分は、分岐は簡単だが、マージは難しいという観察です。時々耳にする議論は、最新のバージョン管理ツールはマージを十分に容易にするため、フィーチャーブランチは価値があるというものです。
確かに、現代のツールは私の若い頃よりもはるかに優れたマージ機能を備えています。この能力の良い例は、私がlorem.rb
の内容の一部を変更し、Jezがその名前をipsum.rb
に変更するという状況を適切にマージできる、名前変更を伴うマージです。
これはすべて非常に良いことですが、テキストの競合のみを解決し、意味的競合の解決には役立ちません。意味的競合とは、Jezと私がテキストレベルでは安全にマージできる変更を加えるものの、プログラムの動作が異なってしまう状況を指します。
最も簡単な例は、関数の名前変更です。たとえば、clcBl
というメソッドは、calculateBill
という名前にした方が使いやすくなると考えたとします。最新のリファクタリングツールを使用すれば、これは簡単です。Shift + F6キーを押し、新しい名前を入力するだけで、ツールはすべての呼び出し元を変更します。しかし、Jezが自分のフィーチャーブランチでこのメソッドへの呼び出しを追加した場合、問題が発生します。2つがマージされると、テキストのマージは正常に機能しますが、プログラムは同じように実行されません。

メソッドの名前変更は単純な例であり、静的型付け言語ではコンパイルに失敗するため、簡単に見つけることができます。しかし、それほどきれいにマージされない、より微妙な意味的競合がたくさんあります。calculateBill
メソッドを見て、請求書の計算だけでなく、会計システムに会計エントリを送信していることに気付いたとしましょう。副作用が気に入らないので、notifyAccounting
という別のメソッドに抽出します。その後、calculateBillのすべての呼び出し元を見つけて、notifyAccounting
の呼び出しを追加できます。しかし、Jezは自分のブランチでそれについて知りません。
つまり、ここでの最初のポイントは、ツールがどれほど強力であっても、テキストの競合から保護することしかできないということです[1]。特に厄介な点は、意味的競合は発見が難しく、修正も難しいことです。
意味的競合を自動的に解決することはできません。いつかツールがそれらの一部に対処できるようになるかもしれませんが、厄介なものは常につきまとうのではないかと思います。少なくとも、コンピューターが私たちの心を読み、私たちの意図を自動的に推測できるようになるまでは。しかし、それらに対処するのに役立つ戦略がいくつかあります。
その1つは、自己テストコードです。テストは、コードのセマンティクスに関する見方が、コードの実際の動作と一致しているかどうかを確認するために、コードを効果的に調査しています。Jezが呼び出しているコードで特定のことが起こることを期待していて、そのためのテストがある場合、彼が統合するときにそれらは壊れます。もちろん、それは完璧な対応策ではありません。テストは決して完璧になることはできませんが、実際には多くの意味的競合を捉えます。また、競合を発見した後に修正するのには役立ちませんが、発見することは戦いの大きな部分を占めます。
役立つもう1つの手法は、より頻繁にマージすることです。Jezの困難は、数日後ではなく数時間後に私の変更を発見すれば、はるかに少なくなります。そうすれば、彼はもはや古いセマンティクスに基づいて多くのコードを構築することはありません。これが、私たちが継続的インテグレーションを強く推奨する理由です。
ツールによってフィーチャーブランチが許容できるものになると主張する人々には、2つのグループがあるようです。1つは「エンタープライズグレード」のVCSの提供者です。私たちは彼らについてはあまり気にしません。もう1つのグループは、DVCS(分散バージョン管理システム)のファンです。私は後者のグループについてもう少し懸念しています。フィーチャーブランチをどのように容易にするかによって、DVCSを正当化しようとする人がよくいます。しかし、それは意味的競合の問題を見落としています[2]。DVCSを使用する正当な理由はたくさんあるので、優れたツールを問題のある手法に結び付ける理由はありません。
注記
1: また、まったく同じテキストを変更した場合、git rerereのようなものがない限り、マージツールは通常役に立ちません。しかし、その問題は意味的競合よりもはるかに小さいです。
2: フィーチャーが数日以内に迅速に構築される場合、意味的競合は少なくなります(1日未満の場合、CIと同じです)。しかし、そのような短いフィーチャーブランチはあまり見られません。