私がgemのコードを読むときに使う小ネタを紹介します。
コードリーディング時の流れ
おおまかに下記のように進めます。
- gem内の実行箇所を把握
- ステップ実行でコードの流れを把握
- 用途不明のオブジェクトはそのコードを読む
- ある程度理解できるまで 2-3を繰り返す
gem内の実行箇所を把握
リーディング対象の機能の実装箇所を特定するためにbyebugを利用します。
byebugを仕込む箇所は、テストやそれ用に追加した小さい機能に対して仕込むと良いでしょう。
byebugで止めた箇所からステップ実行を繰り返すことで、gem内のファイルにたどり着けます。
この時gemにたどり着くまでにステップ実行の回数が多いならgemのコード内にbyebugを仕込む事をおすすめします。
そうしておくと、次に実行したときにgem内のファイルにたどり着くまでにステップ実行回数が少なく済みます。
gemのソースを直接いじるのは危険が伴いますが、bundler
の--path
オプションを利用すれば安全に扱えます。
RDocが整備されているgemなら、ドキュメントからGitHubの実装箇所に飛べるので、そこからコードの場所を特定可能です。
ステップ実行でコードの流れを把握
ステップ実行でコードの流れを把握します。
この時、ある程度理解したら自分の脳内スタックをメモか何かに書き出すことをおすすめします。
私の場合はこれをやらないとコードをどこまで読み、理解したかがわからなくなるからです。
用途不明のオブジェクトはそのコードを読む
途中でよくわからない処理やオブジェクトが出てきたら、そのオブジェクトをputsやppなどで出力し、クラス名を把握します。
クラス名をヒントにgem内の実装を特定、確認します。
それでもわからなければそのクラスの初期化コードにbyebugを仕込み、どこでどのように使われているかを把握します。
ある程度理解できるまで 2-3を繰り返す
あとは繰り返しです。
がんばりましょう。
その他の小ネタ
bundle install --path vendor/bundle
gemのインストール先を変更するオプションです。
gemのソースにbyebugやputsなどをを仕込む時、通常のGEM_PATHにあるgemのソースコードを修正してしまうのは危険です。
デバッグ用の修正を戻し忘れたに別プロジェクトに影響が出てしまいます。
なので、コードリーディング時の影響はコードリーディングを行っているプロジェクトに限定したいと思います。
--pathオプションを利用すると、そのプロジェクトで使用するgemのインストール先を特定のディレクトリ直下に指定できます。
これにより、修正を戻し忘れた時に別プロジェクトに影響を与えずにすみます。
bundle open
gemのインストール先のディレクトリを開くコマンドです。
gem中のソースにprintなどのデバッグコードを仕込む際に利用できます。
RubyMineのコードジャンプ
ちなみに、gemのコードの特定などはRubyMineのコードジャンプ機能で一発で特定可能です。
コードリーディングときに非常に便利なのでオススメです。
終わりに
この方法は我流な読み方なので、もっとスマートな別の方法もあるかと思います
もしそのようなやり方や別のやり方があればコメント欄でご指摘いただけると幸いです。
参考リンク
https://bundler.io/v1.17/man/bundle-install.1.html
https://qiita.com/jnchito/items/bcb2bb5311a44113fdd9
https://www.jetbrains.com/ruby/