バグ修正や新規機能の追加などコードリーディングが必要となる場面は様々ですが、動作や役割がよくわからないクラスや関数、メソッドについて調べなければいけない場合に「テストコードを先に読む」というテクニックを身につけているとコードリーディングが楽になります。
ここでは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
のソースコードを読んだ際に、これらの情報が背景知識として頭に入っているため、読むべきコードの選別やコードリーディングの取っ掛かりとなるポイントをうまくおさえることができるはずです。
終わりに
「テストコードを先に読む」というテクニックを使うことで短い時間でヒントとなる情報を集め、コードリーディングを楽にする方法について紹介しました。
最も重要なのは、 わからないコードや圧倒されるような膨大な量のコードを目の前にしたときに「テストコードを先に読む」という選択肢を思い浮かべて方向転換できる ことです。テストコードを読んで少しでもヒントを掴むことができれば、元のコードに戻ったときに呆然と立ち尽くしてしまうことはなくなるでしょう。
ソースコードを読むために必要な情報や背景知識が不足していれば、コードリーディングによってプログラムを理解することが苦痛だと感じるのは当然です。少しでもヒントを得て、不足している情報を補うことでコードリーディングの際の負担を軽くしていきましょう。