🦔

大規模なソースコードを理解する

2021/04/30に公開

比較的大規模なソースコードを読む時に自分が気をつけていることをまとめます。

明確な目的をもって処理を追う

  • 「○○の処理ってどうなってるんだろ」から始める
  • メインの処理から順番に追っていくのは効率が悪いし骨が折れる

すべてを1行1行理解するのは諦める

  • 実際に関数の中身を読んでいく時には、後述のように全体感や依存関係を把握して、ある程度どこにどんな処理が書いてあるか当たりをつけてから読み始めたほうが効率が良い
  • すぐにコードの詳細を読み始めるのは、いきなり応用問題に取り掛かるようなものである
  • ただ、単純に興味があるときは、1行1行順番に追っていくのも結構楽しいのでやったりする

ディレクトリ名、ファイル名を眺める

  • 大規模なソフトウェアにはなんらかのアーキテクチャが用いられていることが多く、ディレクトリやファイル名には意図がある

エントリーポイントを探す

  • 外部向けAPIのエントリーポイント、内部向けパッケージのエントリーポイント、パッケージ内でのみ使われる処理のエントリーポイント、etc

パッケージの依存関係を把握する

  • 前述の過程では、各パッケージの依存関係をざっくり掴んでいくことを意識する
  • インターフェイスや責務を注視すると良い
  • ARCHITECTURE.md や wiki 、ドキュメントがあればそれをみる
  • 全体感を掴むことで、いまここでなにをしているのか?が理解しやすくなり、詳細なコードリーディングにもかえって良い効果がでる

パッケージ内部の依存関係を把握する

  • 実際の関数やクラスなどの依存グラフを把握する。ツールなどがあれば自動化する
  • 特に名前(関数名、クラス名)に着目する

特殊な処理を理解する

  • ソフトウェアによっては、なにか特殊なアルゴリズムやデータ構造を使っている時がある
  • まずはドキュメントを見ることだが、それだけで理解できないことも多いので、別途ググったりする

ユビキタス言語を把握する

  • 一般的な言葉であっても、そのソフトウェアでは別の意味で用いられているなどの場合がある
  • ドキュメントや wiki 、あるいは Grocery などがあれば見る
  • コード内を検索することでざっくりと意味を把握できることもある

実際に動かしてみる

  • OSSでもアプリケーションでも同じ
  • デバッガを挟んだりしながら、いつどんな挙動が起こっているのかを調べる
  • プログラムを小さく動かすことになれておく
  • CONTRIBUTING.md などをみてリポジトリの環境構築をすることになれておく
  • 動かす目的を明確にするといい
    • eg. ある馴染みのない言葉がソースコード中にでてきて、それが特定の機能を表していることがわかった、と仮定する。実際に動かしてそれがどんな機能なのか把握すると、ただコードを眺めて悩んでいるよりも、クラスやメソッドの意味がすっと腑に落ちてくる時がある
    • eg. より詳細な挙動を追っているとき、ある処理がどのタイミングで実装されるのか正確に知りたい、のようなケース。実際の挙動を知ることで、自分の理解が間違っていることに気付いたり、理解を深めることができる

テストを見る

  • テストには重要な情報が詰まっている
  • まずは、テストケースを見ることで、プログラムの仕様を把握できる。結合レベルのものはもちろん、特定のパッケージや関数の挙動も把握できるコードは嬉しい
  • 次に、プログラムを小さく動かす方法がわかる。テストを書けばアプリケーションを立ち上げなくてもプログラムを動かせるほか、テストのアーキテクチャを理解すると、そのソフトウェア(あるいは一部のパッケージ)を動かすにはどういうランタイムが必要なのかが理解できる

git blame する

  • 処理の意図がわからなかったり、理解ができないときは git blame する
  • 処理の変更履歴をみることはもちろんだが、GitHubを使っている場合、特定のコミットがはいったPRを確認できるのが大きい
  • PR単位で見ると、プログラムの塊を把握することができるし、また、背景や元のissueが記載されていることが多いので、実装の意図を把握することもできる

PRをwatchする

  • GitHubではPRだけwatchすることができる
  • 意味のあるプログラムの塊をPR単位で見ることができる
  • 興味があるソフトウェアのコードを、受動的に把握したい時に便利である
  • 1-2ヶ月位真面目に見ると、PRを出してマージされるまでの流れや、誰が主体となって開発をしているかなどがなんとなくわかる
  • ポイントとしては、ファイル名や関数名を中心にみて、処理の詳細は興味があれば、くらいの雰囲気でみることである。これによって、PRのたびにどこになにがあるかざっくり把握することができるし、興味があれば「PRに関連するがそのPRでは差分のない」パッケージやディレクトリ、ファイルや関数をみにいくことができる
  • また、member や collaborator などの、コアなメンテナを把握することもできる。これによって、後述の「issueを見る」時に、重要度を判別しやすくなる

issueを見る

  • リアクションやコメント数でソートする
    • 単純にたくさんのリアクションが集まっているissueは、要望が多い機能、根本的な課題、大きめのロードマップやクールな実装の提案などが多い
    • そういう中心人物同士の会話を見ることでソフトウェア自体にも興味が出てくる
  • ラベルでソートする
    • eg. バグ、新規機能、ロードマップ、難易度、コアチームが作成、パッケージ名、アルゴリズム名、ディスカッション用、RFC、etc

キーボードだけでエディタを操作できるようにしておく

  • ジャンプ、型参照、処理のリファレンス、検索、ツリーとエディタの切り替え、カーソル移動、関数のアウトライン、依存グラフ、etc
  • キーのリピートをMAXにしておくのが個人的にはおすすめ

基礎をやっておく

  • そもそもの前提でつまずくことが減る
  • クリーンコード、デザインパターン、各種アーキテクチャ、プログラミングパラダイム、言語仕様、ランタイム、通信、コンパイラ、アルゴリズム、etc
  • 読みたいコードの言語に精通しているに越したことはないが、そうではないケースも多い。抽象度の高い概念を理解しておくと役に立つ

読みたい箇所をリストアップしておく

  • コードを読んでいると、ひとつの処理が複数の箇所に依存し、その先でまた複数の処理を呼び出して・・・みたいなことがある
  • 読みたい箇所をメモしておくと後で見返すことができていい(エディタでブックマーク的な機能があればそれもいい)
  • ひとつひとつ読めば追うことはできる。しかし、コードを読むのは時間がかかることを理解する

その他

  • いい椅子と机を買う

Discussion