Plastic SCM を開発したCodice Softwareが,セマンティックマージツール (Semantic Merge Tool) のプレビュー版をリリースした。このツールはコードを解析することで,行単位で比較する多くの同種ツールよりも正確なマージを行うことができる。同社の主席ソフトウェア技術者であるPablo Santos Luaces氏に話を聞いた。
InfoQ: セマンティックマージに注目するようになった,そもそものきっかけは何だったのでしょうか?
Pablo: かなり以前のことですので,本当に長い話になります。
実は私たちには,"優れたブランチは優れたマージから" という信念があるのです(笑)。 要するに "タスクごとのブランチ" (http://codicesoftware.blogspot.com/2010/08/branch-per-task-workflow-explained.html) という考え方を強く支持している,ということなのですが,そうすると結果的にたくさんのブランチができてしまいます。ですから常々,もっとよいマージ機構がないものかと思っていました。
DVCSは開発になくてはならない存在ですが,使用しているマージアルゴリズムは未だにテキストベースです。基本的には15年前に使っていた "マージエンジン" から何も変わっていません。
そんな理由から "セマンティックマージ" を考え始めたのです。もちろん簡単なことではありません。ですから最初は "XdiffとXmerge" http://plasticscm.com/features/xmerge.aspx を使って,現在の "テキストベース" diffとマージアルゴリズムを強化することを考えました。これでもそれなりに便利でしたが,私たちはもっとよいものが欲しかったのです。セマンティックマージがいつも目標でした。
その後は "リファクタリングのサポート" 強化を目指して,ファイルやディレクトリのマージ方法の改良に努力してきました。そして Plastic SCMのコア機能に追加したのです: http://plasticscm.com/mergemachine/index.html
必要なパーツがすべて揃ったので (2012年中頃のことです),いよいよセマンティックマージに取りかかりました。それまでのテキストベースの古いファイルマージは捨てて,ソースコードの解析を行って,テキスト行ではなくネームスペースやクラス,メソッドなどを処理するようにしたのです。
経緯としては,ざっとこんな感じですね。
次のような啓示があったのです: ”現在のマージ技術のことはすべて忘れなさい – 開発者として,あなたがマージ処理に望むことは何ですか? どのように動作してほしいですか?" 答は: "マージ処理はコードを理解すべきである",それがすべての始まりなのです。
InfoQ: "マージごとにブランチ"という信条について,もう少し説明していただけますか?
Pablo: タスクごとにブランチ(Branch per Task) というのはよく知られたブランチパターンです。これはイシュートラッカ上のタスク単位で作業用のブランチを作る,というアイデアに基づいています。
そうすると,イシュートラッカのエントリはひとつの変更,ひとつの新機能ごとに作られますから (新規タスク,バグ,パフォーマンス上の問題など何であれ),それぞれにブランチが作られることになります。
メリットとしては:
* メインライン(トランク)だけで行うような(全員が同じブランチで作業するような)開発では,バージョン管理は開発者にとって,単なる "ファイル配信の仕組み" に過ぎません。苦痛,ただそれだけです。
* これに対して,自分自身のブランチ(集中管理であれ,分散環境であれ) があれば,バージョン管理は単なる配信のための仕組みから,生産性ツールに変わります。必要な時にチェックインして(チェックインは単に配信ではなく,自分自身のチェックポイントになります),コードの変更内容を確認できる ... というように,です。
* これまでのCIで最大の問題は "ビルドのブレーク"です。ブレークは作業を逆行させます。ビルドをブレークしたなら,とにかく修正しなくてはなりません。"メインライン” で作業していると,こういったことが起こります。チェックインしたコードが,メインライン上で干渉するのです。タスクごとにブランチを使用すれば,このようなことにはなりません。
* ブランチを多用するとマージの必要も多くなる,というのは事実ではありません。並行的に作業すれば,確かにマージの機会は増えます。ですが,同じブランチで作業したとしても,同じファイルを同時に修正するかも知れません ... その場合は,やはりマージが必要になります。
* タスクは分離するに越したことはありません。私たちが考えるよりも,タスク同士は独立性が高いものなのです。タスクごとにブランチすれば,リリースサイクルは柔軟になると同時に,管理もしやすくなります。
* マージフェーズの間に,安定したベースライン期間を設ける (1日に1回マージする,というようなことです。タスク単位でブランチするというのは,1ヶ月に1回マージすればよいというような意味ではありません!) ことも,タスクごとにブランチを用意すればごく自然に行うことができます。この話の全体は,以下の場所で読むことができます: http://www.plasticscm.com/infocenter/quick-start/intro-task-driven-development.aspx
InfoQ: 最初にサポートする言語として,なぜC#を選択したのでしょう?
Pablo: 理由はいくつかあります。順不同でご説明しましょう。
1) 私たちが .NET屋だから! :-) 毎日C#コードを書いていますし,自分たちでツールを試してみるのが一番だと思ったのです :-)
2) C#はもっともユーザの多い言語のひとつだから。StackOverflowサイトを見てください,一番人気のタグはC#です!(http://stackoverflow.com/tags) TIOBEインデックスではトップ5です (http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html)。 PYPLでは3位上昇中です ... (https://sites.google.com/site/pydatalog/pypl/PyPL-PopularitY-of-Programming-Language) ですから,広く普及した言語であることは間違いありません。
3) C#(とJava)はセマンティックマージの概念を導入するのに好都合な言語です。C++より扱いやすい (技術的に見れば) ので,ごく初期の段階から,セマンティックマージ技術に集中することができました。他の言語では,こうは行かないでしょう。
おもな理由としては,こんな感じですね。
InfoQ: 今後,他の言語やファイル形式をサポートする予定はありますか?
Pablo: 目標としてはVB.NETサポートのリリース,次にJava,それからCとC++に進みたいと思っています。その後はアーリーアダプタを対象に 調査 を行って,次に必要なものを見つけるつもりです。
InfoQ: ほとんどのマージツールは,ファイルを行単位で "見て" います。この製品はどうなのでしょう?関数,ステートメント,あるいはブロックなのでしょうか?ステートメント中の式ですか?
Pablo: semanticmergeでは,ソースファイルをツリー形式で認識しています - ネームスペース,クラス,その中のメソッド ... といった具合です。基本的には構造として捉えているのです。ツールでは "メソッド内のコード" は見ていません。メソッド,プロパティ,あるいはフィールドのレベルです。メソッドあるいはプロパティ本体のマージは,テキストベースの方法で実行しています。例えば "ifステートメント" を "セマンティック" にマージするようなことはしていません。今のところ,ですが ;-)
3ウェイマージをメソッドベースのマージにするようなことも,もちろん可能です。最初にメソッドの "先祖" と2つの継承を見つけ出してしまえば,その後の処理は,テキストベースのマージでメソッドボディを扱うようなシンプルなものになります。
InfoQ: 開発者は折に触れて,ファイル内を "クリーンアップ" するツールを実行します。プロパティからメソッド,その後でアルファベット順,というように,ソートを行うのです。言うまでもありませんが,行ベースのマージツールではそう簡単には成果を上げられません。 このようなシナリオもサポートされているのでしょうか?
Pablo: まさに私好みのケースですね!セマンティックマージツールなら,このようなシナリオでもきれいに対処できます。事実として,要素の位置による影響は受けません。場所に関係なく,メソッドが同じメソッドであることを理解できるのです :-)。これによってリファクタリング機能も大幅に向上しています。ファイルを可能な限り読みやすいものにしても,それを防ぐ人はいません。
今回のクローズドベータについては,http://www.plasticscm.com/sm/index.html で確認することができる。