Part 2 開発の基本動作・動画

第8章 既存コードを小さく読む

動画台本ナレーション全文

Slide 01. 既存コードを小さく読む

Chapter 8では、すでに動いているWebアプリの不具合を題材にします。画面で起きたことを再現し、HTTP通信を観察し、コードの入口を探し、原因候補を絞ります。最後は、小さな修正としてPull Requestにまとめます。多くの実務では、新しく書くことだけでなく、既存コードを読んで安全に直す時間も長くなります。ここでは、その最初の型を作ります。

Slide 02. この章で持ち帰ること

この章で覚えてほしいのは、デバッグの順番です。再現する。観察する。読む場所を絞る。仮説を立てる。小さく直す。もう一度確認する。最後に、Pull Requestで調査と判断を共有する。この流れがあると、焦って条件式を変える前に、今どこで何が起きているのかを説明できます。

Slide 03. 前の章の道具を使う

第5章のローカル実行ログは、アプリが手元でどう動いているかを示す事実です。第6章のPull Requestは、修正をレビューしてもらう場です。第7章のHTTP観察は、画面、API、サーバーのどこを見るかを絞る道具です。第8章では、この3つを組み合わせて、既存コードの中から変更すべき場所を探します。

Slide 04. 題材は未提出者フィルタ

今回の題材は、メンター向け進捗一覧の不具合です。未提出者フィルタを選んでも、提出済みの受講者が一覧に残る、という状態を扱います。期待する結果は、提出日時を表す submittedAt が空、つまり null の受講者だけが表示されることです。実際には、submittedAt に日時が入っている受講者も表示されています。

Slide 05. 目的を持って読む

既存コードを読むときは、先に知りたいことを決めます。今回は、未提出者フィルタを選んだとき、どのAPIが呼ばれ、どこで提出済みの受講者が混ざるのかを知りたい。そう決めると、読む範囲を小さくできます。project-overview.md、HTTP観察ログ、過去のPull Requestも、入口を探す手がかりになります。

Slide 06. 直す前に再現する

デバッグの最初の成果物は、修正コードより先に作る、再現できる説明です。どの画面を開いたのか。どの操作をしたのか。期待結果は何か。実際の結果は何か。入力値、URL、HTTPのステータスコード、ログには何が出たのか。ここを先に書くと、修正後に同じ手順で直ったかを判断できます。

Slide 07. 再現ログの型

reproduction-log.md には、対象の不具合、実行環境、再現手順、期待結果、実際の結果を書きます。さらに、Networkタブで見たリクエスト先のURL、方法、結果の番号、返ってきた内容の抜粋、サーバーログも残します。観察した事実と、まだ分からないことを分けると、次の調査が進めやすくなります。

Slide 08. 観察結果で場所を絞る

第7章のHTTP観察を使うと、見る場所を絞れます。まず通信が成功しているかを見ます。次に、返ってきた中身が期待と合っているかを見ます。今回、GET /api/progress?filter=unsubmitted が200で返るなら通信は成功です。それでも提出済みの受講者が混ざるなら、API側やデータを作る処理が候補になります。

Slide 09. URLとNetworkから始める

画面で起きた不具合は、まずURLとNetworkタブに結びつけます。進捗一覧のURLは何か。未提出者フィルタを選んだとき、どのAPIが呼ばれたか。条件を表す query に filter=unsubmitted が入っているか。statusは200か、500か。返ってきた内容は期待に合っているか。画面の印象より、観察できる通信を先に見ます。

Slide 10. コード探索の入口

コードを探す入口は、画面の文字、URL、APIのパス、データ名、エラーメッセージです。今回なら、/mentors/progress、/api/progress、submittedAt、unsubmitted、filter が検索語になります。component名やhandler名は、その後の手がかりです。勘で深い実装に飛ぶ前に、見えている言葉から始めます。

Slide 11. 検索を使い分ける

ファイル名検索と全文検索を使い分けます。エディタの検索でもよいですし、ターミナルなら rg が便利です。rg は ripgrep の略で、プロジェクト内の文字列を速く探せる道具です。画面、API、処理、テストの候補を分けて書くと、どこまで読んだか、どこがまだ不明かを共有できます。

Slide 12. 呼び出しの流れを追う

入口が見つかったら、呼び出し先と呼び出し元を少しずつ追います。画面からAPI、APIから処理、処理からデータ、必要ならテストへ進みます。ここで大事なのは、全部のファイルを一気に読むことより、今回の不具合に関係する流れをつなぐことです。関係が薄い場所は、メモして後回しにします。

Slide 13. ログとエラーを読む

ログとエラーメッセージは、次に見る場所を絞るための情報です。最後の行だけで判断せず、最初に失敗した箇所、呼び出し元、自分が触るコードを分けて見ます。借りているライブラリの中で起きたエラーなら、自分たちのコードからどう呼んだかを見ます。入力値、ID、ステータスコードは、Networkタブや再現ログと照らし合わせます。秘密情報は必ず伏せます。

Slide 14. スタックトレースを見る

スタックトレースは、エラーがどの呼び出しの流れで起きたかを示す一覧です。全部を暗記する必要はありません。まず、自分たちのアプリのファイル名を探します。次に、最初に失敗した行と、その行を呼んだ場所を見ます。借りているライブラリの中だけを追い続けるより、自分が修正できる場所を探します。

Slide 15. 仮説を複数出す

観察したら、原因候補を複数出します。APIがfilterを読んでいない。filterは読んでいるが条件が逆になっている。画面側で結果を上書きしている。テストデータのsubmittedAt、つまり提出日時が想定と違う。候補は3つ程度で十分です。1つに決めつける前に、それぞれをどう確認するかを考えます。

Slide 16. 仮説ログを書く

hypothesis-log.md には、観察した事実、原因候補、確認方法、確認結果、残った仮説を書きます。仮説が外れたことも成果です。その確認によって、次に見なくてよい場所が分かったからです。AIに原因候補を出してもらった場合も、候補として扱います。実際のコード、実行結果、テストで確かめた内容だけを採用します。

Slide 17. 最小修正を考える

原因が見えたら、修正範囲を小さくします。不具合修正とリファクタリングを同時に広げると、レビューが難しくなります。今回なら、filter=unsubmitted のときに、submittedAt が空の受講者だけを返す条件をどこに入れるかを考えます。既存の処理の流れに合う場所を選び、仕様を変える場合は仕様変更として説明します。

Slide 18. 再現手順で確認する

修正後は、最初に書いた再現手順をもう一度実行します。未提出者フィルタで、未提出者だけが表示されるか。APIが返した内容に、提出済みの受講者が残っていないか。サーバーログに新しいエラーがないか。コードを書いた時点で終わりにせず、再現条件で直ったことを確認します。

Slide 19. 回帰確認を見る

回帰確認は、直した場所の近くで、今まで動いていたものが壊れていないかを確認することです。フィルタなしでは全件が表示されるか。提出済みフィルタがあるなら、提出済みだけが表示されるか。既存テストがあるなら実行します。この章ではテスト設計を深掘りせず、再現手順と関連する正常系を大事にします。

Slide 20. 修正PRの型

バグ修正のPull Requestには、再現手順、期待結果、実際の結果、原因、修正内容、確認方法、影響範囲、リスク、レビューしてほしい点を書きます。たとえば、原因はAPI側の絞り込み条件が未適用でした、と短く書けます。レビュアーが見たいのは、コード差分に加えて、この修正でよいと判断した理由です。第6章と第7章の成果物を材料にします。

Slide 21. 良いデバッグの形

良いデバッグでは、「たぶん条件式が違う」で終わらせません。事実、仮説、次に見る場所を残します。たとえば、APIは200で返っているが、返ってきた内容にsubmittedAtが入った受講者が含まれている。画面側の追加絞り込みは見つかっていない。だから次はAPI側の条件を見る。このように書くと、相談された人も次の行動を取りやすくなります。

Slide 22. AIに相談する

AIは、検索すべき文字列、原因候補、ログの読み方、テスト観点、PR本文の抜け漏れ確認に使えます。入力前には、Cookie、token、個人情報を伏せます。採用前には、AIの提案を差分、再現手順、テストで確認します。共有前やPR前には、自分で確認できたことと、まだ不安なことを分けて書きます。

Slide 23. 演習1 再現ログ

演習1では、不具合を再現して reproduction-log.md を書きます。サンプルアプリを起動し、メンター向け進捗一覧を開き、未提出者フィルタを選びます。期待結果と実際の結果を分けて記録します。Networkタブでは、APIのリクエスト先、方法、結果の番号、返ってきた内容の概要も確認します。

Slide 24. 演習2 コード探索

演習2では、関連コードを探して code-reading-note.md を書きます。検索語は、/mentors/progress、/api/progress、submittedAt、unsubmitted、filter です。まず画面、API、処理、テストの候補ファイルを分けます。次に、呼び出しの流れと、まだ読めていない場所を残します。

Slide 25. 演習3 仮説ログ

演習3では、原因候補を仮説として書きます。APIがfilterを読んでいないのか。条件が逆なのか。画面側で上書きしているのか。テストデータの提出日時が想定と違うのか。それぞれ確認方法を書き、確認結果によって残す仮説と消す仮説を分けます。成果物は hypothesis-log.md です。

Slide 26. 演習4と5 修正からPRへ

演習4では、作業用ブランチを作り、最小修正を入れ、再現手順と関連する正常系を確認します。確認したことは fix-verification-log.md に残します。演習5では、差分を確認し、コミットして、Pull Requestの準備をします。再現、原因、修正内容、確認方法、リスク、レビューしてほしい点を bug-fix-pr-note.md にまとめます。

Slide 27. 次は要件とドメインへ

第8章では、Part 2で学んだ道具をつなげました。手元で動かし、HTTPを観察し、既存コードを読み、小さく修正し、レビュー可能なPull Requestにする。この流れは、個人開発でも既存プロダクト改善でも使います。期待結果と実際の結果を分けて言葉にすることは、次の章にもつながります。第9章では、要件とドメインモデリングへ進みます。

GitHub で台本を見る

教材を検索