はじめに
新人やジュニアエンジニアの中で初出勤にて初めて見るコードとき、どこから読めばいいかわからなくなることありませんか?
一ファイルに何千行。ファイルが多い。関数を開いたら、さらに別の関数が呼ばれている。最初の一行から律儀に読もうとして、30分後には何を読んでいたのかわからなくなってパンクしちゃう。
実は、僕は初見のコードを読むとき、全部を順番に理解しようとはしていません。
今回はそこをふくめ「コードリーディング」についてお話ししていきます。
こんにちは。現役8年目のエンジニア兼PMをやってる、やむぅ。です。
実務では既存の機能を直したり、仕様を考えたり、メンバーと認識をそろえたりするために初めて見るコードを読む場面があります。僕自身もチームとして、コードを書くだけでなくすでにあるコードを読んだり変更できる力、あとは説明できる力を意識してやっています。
若干ずれますが、ProFactでは、コードを書くだけじゃなく、読む・理解するといった「見る順番」も、1on1の中で一緒に身につけていきます。
初見のコードは「何をしているか」より、「なぜ今これ読むか」を意識すべし
コードリーディングで迷う大きな理由は、目的がないまま読み始めてしまうことです。
たとえば、次のように目的がはっきりしていれば見る場所は変わります。
- ログインボタンが反応しない原因を調べたい
- 表示されている文言を変えたい
- 新しい入力項目を追加したい
- このアプリ全体が何で作られているか知りたい
言われてみれば「そんなの当たり前じゃん」と思うかもしれませんが、新人やまだ開発に慣れていないことはそもそもこの意識がなく、「頑張って読んで覚えなきゃ」が先行してしまいパンクしてしまうケースが多いです。
「アプリを全部理解する」は、最初の目的としてデカすぎます。まずは、「今は何を知るために読むのか」をざっくり一文で洗い出してから着手するようにしましょう。
例えば業務システムを読んでいく際、
タスクを追加したとき、どこで保存され、どこで一覧に表示されるかを知る
こう決めると、関係ないファイルまで読まなくてよくなります。コードを読む力は、たくさんの行を読む力というより、必要な行をざっくり読んで流れを把握する力に近いです。
入り口はユーザーが触る場所から
Webアプリなら、最初に探すのはユーザーが触る画面やボタンです。「タスク追加」を調べたいなら、画面に表示されている文字、ボタンの文言、入力欄の名前などでコード上検索します。タスクを追加やAdd task、onClickといった単語が入口にあたりますね。
入口を見つけたら、次のように追います。
- どの画面・コンポーネントが表示しているか
- ボタンを押したとき、どの関数が呼ばれるか
- その関数は、次にどこへ処理を渡すか
- 結果はどの画面に戻るか
最初からフォルダ全体を全部覚えようとしなくて大丈夫です。調べる入口を一つ決めて、そこから必要な場所だけをたどっていきましょう。
一つの操作を最後まで追いかける
次に僕がするのは、ユーザーの一回の操作を最後まで一旦追うことです。ボタンを押した瞬間に何が起きるか。その入力値はどこへ渡るか。データはどこで変わるか。画面は何を見て表示を更新するか。
たとえば、次のように紙にざっくりメモしてみるといいでしょう。
入力欄
→ 追加ボタン
→ addTaskという関数
→ タスク一覧のデータを更新
→ 一覧コンポーネントが再表示
こんな風に書ければ、コード上の細かい文法とかを理解していなくても(本当は理解して欲しいですが)、処理の骨組みはつかめています。
わからない行が出てきたら、そこで一旦止まって「何がわからないか」を具体的にします。
- この関数は何を受け取っているのか
- この値はどこで作られたのか
- この非同期処理が終わるまで、画面はどうなるのか
- この条件分岐は、どんな場合に必要なのか
「このファイルがわからない」より、調べるべき内容や自分が何に理解できないのかがずっとはっきりします。
入力・出力・状態の変化を分けて考える
初見のコードを読むときは、一つの関数を次の3つに分けて見ると整理しやすいです。
- 入力:何を受け取るか
- 処理:受け取ったものに何をするか
- 出力:何を返すか、何を変えるか
たとえばtodoアプリがあったとして、addTaskという関数なら入力はタスク名。処理はタスク一覧に追加すること。出力は新しい一覧で、画面の状態を変える。
特に初心者のうちは、「関数は何を返すか」だけではなく、「画面のどの状態を変えているか」も意識してみてください。Webアプリでは、値を返さずに、画面に必要なデータだけを更新している処理も多いからです。
「わかったこと」と「まだわからないこと」を分ける
初見のコードを一度で全部理解しようとすると、読むこと自体でパンクします。僕は、読んでいる途中で次の二つを分けるようにしています。
- 今わかったこと
- 次に調べること
たとえば、こんなメモです。
わかったこと:
- ボタンを押すとsubmitTaskが呼ばれる
- submitTaskはAPIにタスク名を送っている
- 成功すると一覧を再取得している
次に調べること:
- API側ではどの項目を必須にしているか
- 通信に失敗したとき、エラーをどこに表示しているか
こうやって書き出してみると、自分の頭の中を整理することができます。また、理解できないことが出てきてもそれはしょうがないことです。初見のコードには、読み手が知らない前提が必ずあります。大事なのは、わからない部分を放置せずに周りに聞いたり次の調査に組み込むことです。
ファイルを上から下まで読むのは最終手段
初心者のときほど多いのが、真面目にファイルの一行目から読み始めたくなっちゃうやつです。でも、初見のコードではそれは後回しでいい部分がほとんどです。
- 今調べている機能と関係のない共通設定
- 使われていない古い処理(化石)
- 詳しい見た目だけを決めるスタイル
- ライブラリの内部的な処理
もちろん、あとで必要になることはあります。たけど、目的に関係する処理の流れをつかむ前に全部へ手を出すと、あれもこれも全部やりたくなっちゃってパンクしてしまいます。
なのでまずは一本の操作を追う。必要になったら、その周辺を広げる。この順番のほうが理解・把握がしやすいです。
もっと大事なのは、
- 処理の流れを把握、処理のイメージを掴む
- 重要そうな処理を深ぼる
- 関連の部分を深ぼる
- 処理全体が読めてた
という流れでやってくと自然と「この機能読めた・把握できたわ」でコードリーディング・システム把握できるようになります。
初心者が今日からできる20分のコードリーディング手順
今やってる教材の課題でもいいですし、作ったアプリなどあればそれを対象に次の順番を試してみてください。
- 今日読みたい・把握したい機能を一つだけ決める
- 画面の文言やボタン名で、その機能の入口を検索する
- 押したときに呼ばれる関数を見つける
- 入力・処理・出力、または状態の変化をメモする
- 一つの操作が画面に戻るまで矢印でつなぐ
- わからないことを一つだけ選んで調べる
今回は「処理を理解」するというよりは「流れや詳細を書き出す練習」として挑戦して欲しいです。ここで慣れを作っていけば初見コードもある程度読み進められるようになっていけます。
まとめ
- 読む目的を、一文で決める
- ユーザーが触る画面やボタンを入口にする
- 一つの操作を、入力から結果まで追う
- 入力・処理・出力、または状態の変化に分ける
- わかったことと、次に調べることを分ける
コードを読む力は、特別な記憶力ではありません。目的を絞り、処理の流れを一つずつ追う習慣で育ちます。いきなり大きなアプリを理解しようとせず、今日作った機能、今日直したい機能から始めてみてください。
あわせて読みたい
詰まってる人向け
試してみたけどしっくり来ない、そもそも独学上手くいってない、エンジニアになってる自分のイメージがふわふわしてるなど、もし困っていることがあれば現役エンジニアとして相談やアドバイスできます。あの、全然お金取ったりとか勧誘とかをするつもりはないので、今つまってる方いたらお力になります。
