はじめに
私はプログラムを書くよりも読む方が好きです。最近になって「プログラムは文学だ。作者の心情がそこに表れている」と思うようになりました。
というわけでいろんなソフトウェアを読んできたわけですが、代表的なものとしては以下があります。
- C言語
- CRuby(1.9初期)
- mruby(2012年当時)
- CPython(3.5.1、3.6.3)
- Ruby
- Ruby on Rails(1.2.3)
- Mastodon(1.3.2)
- Python
- Django(1.10.5)
読んだソフトウェアの読解記事は個人サイトに上げています。10年近く前に読んですでに過去の遺物(失礼)なものもありますが。
さて、そんな感じに多くのソフトウェアを読んできたわけですが、どうやって読んできたか(ツール、方法)を紹介していきたいと思います。
コードリーディングのツール
まずは読む際のツールです。
なおOSはWindowsです。以下で説明しているEmacsとgrepはgnupackを利用しています。
Emacs
複数のファイルを素早く切り替えられる、ファイルを開くときにディレクトリ内に他にどんなファイルがあるか確認しやすい、インクリメンタルサーチ、必要に応じて画面を2つに分割できる(同じファイルの別の部分が見たい)ということでコードを読む際にはほぼEmacsを使っています。多分、Vimでも同じことはできるのだと思いますが昔からEmacs使ってるのでEmacsで読んでます。
後述するように物書きには使ってません。
grep
「あれ?この関数どこに書かれているの?」と思ったときの最強ツール。grep -r
etagsとか便利なものがあると思うのですがあまり使ったことないので探すときにはgrepしてます。grep最強。
Chrome
標準関数だったり、使われてるパッケージだったりをググるときに使っています。最近だと使っているパッケージのソースをgithubで見たりもしてます。
サクラエディタ
読んでわかったことの読解記事はサクラエディタで書いてます。まあこれもサクラエディタでなくてもいいのですが昔から使っているので。1ファイルの分割表示(まとめを書く際の振り返り用)、タブ(大きめのソフトウェアで記事を分割したときの前記事参照用)は必須です。
読むエディタと分けているのはソースを見ながら書くためです。Alt-Tab使えばウィンドウを切り替えるのは苦にならないので。
コードリーディングの方法
当然と言えば当然ですがmainにあたる部分から読んでいきます。その際、そのソフトウェアの典型的な利用方法(コマンドラインオプション)を設定し(言語処理系の場合は食わせるプログラムも)、それに沿ってプログラムがどのように動いているか考えながら読みます。デバッガなどで動的に追っかけることはまずしません。
ソースコードの半分以上はオプションが指定されたときの処理、エラーが発生した場合の処理です[要出典]。そういうものは初めに読むときは「あーオプション処理してんなー」とは眺めますがそれ以上は深入りしません。「このオプションの場合はこう動いて・・・」と考えながら読むのはなかなか大変です。このテクニックは昔RHGを読んで覚えました。
慣れは必要ですが多くのソースコードを読むと(というかソフトウェア工学がわかってくると)「こういうプログラムならこういう手順が行われているだろう」とわかってきます。そうすると、その推論に沿って読み進めることができるようになります。例えば、言語処理系であれば構文解析→コード生成→コード実行のような流れになります。
後、著名なオープンソースソフトウェア級のソースコードであれば関数名がちゃんとしているので関数の中身に行かなくても大体何をしているかがわかります。「うーむ、これは重要じゃなさそうだしパス」としてもそんなには外れません。
言語別読むテクニック
C
完全に個人的な読み方ですが、ヘッダファイルは必要になるまで見ません。つまり、先に構造体にどんなメンバがいるかは確認しません。プログラムをmainから追いかけていって実際にそのメンバに何が代入されているか、どう使われているかを見ることでどういう構造体であるのかを把握しています。
Python
Pythonコードを読む際にいいのは「そのファイルに出てきている名前(関数名、変数名)は必ずそのファイル内に存在している」ということです。謎の名前がありそれは実は別ファイルで定義されているグローバル変数だったということはありません。
また、モジュールについてもディレクトリの構造と一致しているので次のファイルを開くときに迷うことありません。
Ruby
昔のころのRubyは必要なものはrequireしてたのでわかりやすかったのですがRailsがconst_missingからの自動読み込みという秘儀を編み出したせいでなかなか読むのが大変です。まあそれについてはクラス名とファイル名が対応付いているので大体わかります。
ここにgemが絡んでくるとさらにめんどくさいです。特にRailsの場合は複数のgemに別れているので「このクラスはどこに書かれているんだ」ということになります。
こういうときはそう、伝家の宝刀「grep -r」です。grep最強。
ひどいコードの読み方
さてここまではオープンソースソフトウェア、それも世界的に有名なオープンソースソフトウェアについてどう読んでいけばいいか説明してきました。初めに「プログラムは文学だ」とお話ししたのを覚えていますか?そう、メジャーなオープンソースソフトウェアは例えていうなら名著と言われるような文学作品です。
もちろん作品の中にはそうではないものもあります。プログラムに話を戻すと「小学生が書いたのかこれ」というようなク○コードです。私もそのようなプログラムはそこそこ見てきたのでどのようにしてそれを読んだかを最後に説明します。
とりあえず全部流し読む
プログラムを構成しているファイルを全部開き、意味を考えるのは頭の片隅に押し込んでざーっと一通り読みます。どんな関数やクラスがあるのか、この作者(プログラマ)はどのような感じのプログラムを書くのかなどの傾向を把握します。
ひどいことを楽しむ
「なんだこのひどいプログラムは・・・(憂鬱)」ではなく、「なんだこのひどいプログラムは!(歓喜)」と思いながら読みましょう。気の持ちようというわけではないですが陰鬱な気持ちで物事に取り組むよりも楽しんでやる方が効率が上がります。声に出して「ク○コードだな~、ヒャッハー!!」というのもいいでしょう(周りにおかしな人と思われないように気をつけて)
繰り返しになりますがプログラムは文学です。ひどい作品の中にも作者(プログラマ)の気持ち(書いたときの心境)が込められておりそれを読み解くのはなかなか楽しいものです。
※個人差があります