自分の記憶頼りにレビューしていないか?
ソースコードを読むときに必要となる記憶力
前回「RHELを題材にソースが見える環境を作る」の記事に従ってソースコードを手元に置くと、段々ソースコードを読む習慣がついてきます。習慣がつくに従い徐々に読む範囲をひろげ、量を増やしていくことでしょう。しかし、いずれ壁にぶつかることになります。少なくとも筆者はぶつかりました。
局所的で少量のソースコードであれば、プログラミング言語の文法知識程度があれば理解できますが、規模を拡大するとたちまち理解が追いつかなくなります。困難を乗り越えるには以下の2つの能力について、より高いものが読解者に要求されます。
1つ目が、イディオム、デザインパターンやアリゴリズム、数学などにおける、より高位の概念や、ライブラリAPI、ソフトウエアが対象とするドメインに関する知識をすでに持っていることです。
2つ目が、ソースコードを読んで得られた大小の知見や、読解の進行状態を記憶しておくこと、同時に記憶と照らし併せながら読めることです。
短いC言語で書かれた、間違いのあるソースコードを例に2つの能力を説明します。コンパイラが教えてくれる程度の間違いですが、ここではそれについて考えないことにします。
ソースコードの間違いを読み解く
この短いソースコードであっても、C言語の文法だけではわからない点があります。
A:stdio.hの内容
B:fputsの意味
もちろん、先に述べた1つ目の能力として、すでに標準Cライブラリ、標準入出力について知っていれば、A、Bともにまったく読解の支障になりません。程なく引数の順序があやしいこと気付くことでしょう。
次に2つ目の記憶の能力を考えてみましょう。先頭からソースを読んでいくところを想像してください。
a:main関数の中でfooとbarという関数を呼んでいること
b:foo関数、bar関数の宣言や定義を確認する必要があること
c:foo関数はスタブであり、何もしないこと
d:bar関数にてfooとfputsという関数を呼び出していること
dを記憶しようとしたときに、記憶cを参照すれば、foo関数について読む必要がないことがわかるので、dのかわりに以下の2つを記憶すれば良いでしょう。
e:fputsという関数を呼び出していること
f:fputs関数について関数の宣言や定義を確認しなければならないこと
実際にこのようなことを意識してやることはなく、無意識に、瞬間的に読んだ内容について、すでにある記憶と照らし併せて、理解を進めると同時に新たな知見を記憶しています。
プログラミング言語に基づくさまざまな要素は、すべて記憶の対象の候補です。C言語であれば変数の名称、スコープ、寿命、変数の型、関数の型、対象とする関数を呼び出す関数の集合、対象とする関数が呼び出す関数の集合などです。
ソースコードの規模が大きくなると、どのコードをすでに読んだか、どのコードをこの後読まないといけないか、といった読解の進行状態の関する記憶が重要になってきます。
上で列挙した「記憶しておくべきこと」の中では、bとfが進行状態に関する記憶になります。「どのコードをすでに読んだか」ということを覚えていないと、複数の関数に跨(また)がる再帰呼び出しなどの場合は、読解作業が終わらなくなってしまうでしょう。再帰呼び出しになっていると気付いたとしても、「どのコードから再帰呼び出しが始まったか」を覚えていなければ、読解を継続できません。
最初に述べた2つの能力のうち、1つ目の能力に関しては簡単に拡大することはできません。日ごろの努力不足を悔いながら、勉強するしかないでしょう。そこで次ページから2つ目の能力を拡張を目的とするツールを紹介します。