バグ修正や新規機能の追加などコードリーディングが必要となる場面は様々ですが、動作や役割がよくわからないクラスや関数、メソッドについて調べなければいけない場合に「テストコードを先に読む」というテクニックを身につけているとコードリーディングが楽になります。
ここではAWS Cloud9 IDEのもととなっているAce(Ajax.org Cloud9 Editor)というJavaScript製のコードエディタ(=テキストエディタ)のソースコードを使って「テストコードを先に読む」というテクニックのポイントを紹介していきます。
コードリーディング前の推測
AceはDocument, EditSession, Editor, VirtualRenderer, Layer, Modeという6つのクラスが中心となって構成されたコードエディタです。[1]今回は、これらのクラスのうちVirtualRendererの役割を調べなければならないというケースを想定します。
この時点での背景知識が
- Aceはコードエディタ(テキストエディタ)である
-
Document,EditSession,Editor,VirtualRenderer,Layer,Modeという6つの中心となるクラスがある
だけあれば、コードリーディングを始める前にできることはVirtualRendererというクラス名からその役割を類推するくらいでしょう。最終的なレンダリングはブラウザが行うので、VirtualRendererはその直前の状態までレンダリングする役割を担うクラスといったところでしょうか?
テストコードを先に読んでみる
軽く当たりをつけたところでコードリーディングに着手します。VirtualRendererクラスが定義されたvirtual_renderer.jsを開くと1,886行もあります。これだけ規模の大きなコードをさらっと読み切って理解することは難しいでしょう。先頭から順番に読み進めていくとすぐに情報量が多すぎて混乱する と思います。「VirtualRendererとは何者であるか?」を知りたいのであれば、そのソースコードを1行1行読んでいく以外にも有用な情報やヒントを得る手段はあります。そこで「テストコードを先に読む」というテクニックの出番になります。
ここでvirtual_renderer.jsを読み進めるのは一旦止めて、VirtualRendererクラスのテストが書いてあるvirtural_renderer_test.jsを読むことにします。virtural_renderer_test.jsは236行のファイルであり、VirtualRenderer本体よりは少し楽な気持ちで読み始められます。
setUp: function() {
if (editor)
editor.destroy();
var el = document.createElement("div");
el.style.left = "20px";
el.style.top = "30px";
el.style.width = "300px";
el.style.height = "100px";
document.body.appendChild(el);
var renderer = new VirtualRenderer(el);
editor = new Editor(renderer);
editor.on("destroy", function() {
document.body.removeChild(el);
});
},
テストコードの冒頭部分に上記のようなsetUpというメソッドが定義されています。document.createElementによってdiv要素のDOM(el)を生成し、left, top, width, heightといったスタイルを直接設定(代入)したあとでこのDOMをVirtualRendererに引数として渡していることがわかります。さらにこうして生成されたrendererオブジェクトがEditorに引数として渡されてeditorオブジェクトが生成されています。
このsetUpメソッドがテストを行う上での準備となっており、このコードから
-
VirtualRendererはDOMを引数として受け取って生成され、そのVirtualRendererオブジェクトがEditorへ引数として渡される
ことがわかります。このテストコードから得られた情報を
DOM -> VirtualRenderer -> Editor
というようにオブジェクトの受け渡しのフローとしてメモしておいても良いでしょう。UMLのような正確な表現方法ではありませんが、自分の理解の助けになる表現であれば何でも構いません。
テストコードには、テスト対象となるクラスやメソッドを使うための前提条件が書き出されています。別の言い方をすれば、 テストコードは、クラスやメソッドの内部の実装ではなく外部のインターフェースや入出力を見ている と言えます。そのため、テストコードのコードリーディングは、「クラスやメソッドの役割を知りたい」というような 概要を掴みたいケースに適している のです。
今回の例ではVirtualRendererがDOMとEditorをつなぐ役割を果たしていることがわかりました。勘の良い方ならeditor.renderer.doSomthingのような形でEditorからVirtualRendererを経由してDOMを操作するという使い方まで頭に浮かんでいるかもしれません。
テストのタイトルから情報収集する
もう少しテストコードを眺めてみましょう。
"test: screen2text the column should be rounded to the next character edge" : function(done) {
var renderer = editor.renderer;
renderer.setPadding(0);
renderer.setSession(new EditSession("1234"));
var r = renderer.scroller.getBoundingClientRect();
function testPixelToText(x, y, row, column) {
assert.position(renderer.screenToTextCoordinates(x+r.left, y+r.top), row, column);
}
renderer.characterWidth = 10;
renderer.lineHeight = 15;
testPixelToText(4, 0, 0, 0);
testPixelToText(5, 0, 0, 1);
testPixelToText(9, 0, 0, 1);
testPixelToText(10, 0, 0, 1);
testPixelToText(14, 0, 0, 1);
testPixelToText(15, 0, 0, 2);
done();
},
テストフレームワークによって多少の違いはありますが、テストコードには、"test: screen2text the column should be rounded to the next character edge"のようなテストの内容を説明するタイトルがついています。VirtualRendererクラスの役割(概要)を把握するために、このタイトルだけを拾い読みしていくことにします。
- "test: screen2text the column should be rounded to the next character edge"
- "test: handle css transforms"
- "test scrollmargin + autosize"
- "test invalid valus of minLines"
- "test line widgets"
- "test wrapped text rendering"
- "test resize"
- "test placeholder"
200行を超えるテストコードが書かれていますが、タイトルだけを読めばたったこれだけです。概要を掴むだけならhandle css transforms, scrollmargin + autosize, wrapped text renderingなどのキーワードから具体的なイメージを描くことができます。VirtualRendererはCSSの変換や表示領域の調整に関する機能を持っていそうです。
このようにテストコードのタイトルには、クラスやメソッドの持つ機能の一部が描かれています。これらの情報は、クラスやメソッドの役割を把握するためのヒントとして十分に有用です。丁寧に書かれたドキュメントやコメントにはかないませんが、短時間でさっと頭に入れるための情報源として非常に便利です。
テストコードに目を通したことによって、VirtualRendererがDOMとEditorをつなぐ役割を担っていること、CSSの変換や表示領域の調整に関する機能を持っていることなどの情報を比較的容易に得ることができました。改めてVirtualRendererのソースコードを読んだ際に、これらの情報が背景知識として頭に入っているため、読むべきコードの選別やコードリーディングの取っ掛かりとなるポイントをうまくおさえることができるはずです。
終わりに
「テストコードを先に読む」というテクニックを使うことで短い時間でヒントとなる情報を集め、コードリーディングを楽にする方法について紹介しました。
最も重要なのは、 わからないコードや圧倒されるような膨大な量のコードを目の前にしたときに「テストコードを先に読む」という選択肢を思い浮かべて方向転換できる ことです。テストコードを読んで少しでもヒントを掴むことができれば、元のコードに戻ったときに呆然と立ち尽くしてしまうことはなくなるでしょう。
ソースコードを読むために必要な情報や背景知識が不足していれば、コードリーディングによってプログラムを理解することが苦痛だと感じるのは当然です。少しでもヒントを得て、不足している情報を補うことでコードリーディングの際の負担を軽くしていきましょう。