メインコンテンツへスキップ
AI を使った開発は素早くて楽しいものですが、何かがうまくいかなくなると状況が一変します。エラーや予期しない挙動、「AI が変なことをした」という瞬間は、プロセスの一部です。このガイドでは、Lovable における AI ベースのデバッグワークフローを進める方法を紹介します。シンプルな問題をすばやく修正する方法、より難しいバグに対する戦略、Lovable のチャットを使ったデバッグ方法、さらには系統立ててバグをつぶすためのプロンプトレシピまで取り上げます。AI アシスタントとのデバッグは新しいスキルですが、適切な進め方とプロンプトを使えば、問題を効率よく解決し、学びの機会に変えることもできます。

高度なデバッグ用プロンプト

問題を深掘りしたり、プロジェクトの健全性を確認したりするには、より強力なプロンプトが必要になることがあります。ここでは、詳細なデバッグや最適化のシナリオ向けに、構造化されたプロンプトの例をいくつか紹介します。これらは Chat mode で使用して、コードをすぐに変更せずに徹底的な分析を行うことができます。

システム全体の見直し(コードベース監査)

プロジェクトが大きくなってきた場合や、構造的な問題がありそうだと感じる場合には、コードベース全体の監査用プロンプトが役立ちます。これは、AI に対してプロジェクト全体を分析し、コードの整理状況やアーキテクチャが適切かどうか、コードの配置に問題がないかを確認するよう依頼するものです。イメージとしては、「すべて本来あるべき場所に整理されているか?」と尋ねるようなものです。 プロンプト例 – コードベース監査:
アーキテクチャがクリーンでモジュール化され、最適化されているかを確認するため、**コードベース全体の包括的な監査**を実行してください:

- 誤った場所にあるファイル、コンポーネント、またはロジックを特定し、より適切に整理できるものがないか確認してください。現在のファイルに属していないコード(配置ミスのロジック)はありますか?
- 関心の分離が明確に行われているか(例:データ処理 vs UI vs 状態管理)を評価してください。過度に結合されているコードのセクションがあれば指摘してください。
- 過度に複雑な箇所や、ベストプラクティスに従っていないコード領域を強調してください。
- 構造と保守性を向上させるための具体的な推奨事項を含むレポートを提供してください。**ただし、この段階ではコード変更は行わないでください**。 

提案を、最も重要なものからオプションの改善まで、実行可能なステップの順序付きリストに分解してください。

*(これは読み取り専用の分析です。この監査中はコードを変更しないでください。)*
このプロンプトは長いですが、AI にコードレビュアーやアーキテクトのように振る舞うよう指示しています。配置が適切でないコードを見つけたり、モジュール性をチェックしたり、さらには修正の優先順位付けまで依頼しています。AI は次のように返してくるかもしれません:
  • _「1. API 呼び出しをコンポーネントから分離する: _ProjectListコンポーネントが直接データをフェッチしています。提案: データ取得処理を専用のフックまたはコンテキストに移動し、コンポーネントを純粋な UI に保ちましょう。​
  1. タスク処理ロジックの結合度を下げる: タスク完了トグルが state を更新すると同時に、直接 localStorage に書き込んでいます。これは単一の信頼できる情報源を持つようにリファクタリングすべきです。​
  2. ユーティリティ関数を整理する: App.tsx にあるユーティリティ関数は、utils フォルダ(例: 日付フォーマット関数)に置いたほうがよいでしょう。
  3. …」*
それぞれのポイントには、説明や特定のファイルへの参照が付くこともあります。このようなレポートは、細部にとらわれず全体像を把握するのに役立ちます。特に、しばらくの間 1 つの機能に集中していて、全体構造を見直していなかった場合に有用です。
汎用的で大雑把なプロンプトは避ける
Nothing works, fix it!
プロンプトはもっと具体的かつ詳細にする
Now the screen has gone blank and I am no longer able to make edits.
Can you check what happened?
この出力を得たら、どのリファクタリングタスクに取り組むかを決められます(AI にプロンプトを送って、それぞれの提案を一つずつ実装させることもできます)。

壊れやすい更新に対する安全なアプローチ

変更しようとしている箇所がデリケート(複雑な認証フローや中核となるアルゴリズムなど)の場合、プロンプトの冒頭に注意喚起のガイドラインを付け加えるのがおすすめです。これはバグ自体を見つけるものではありませんが、AI に「特に慎重に対応する」よう指示することで、バグの発生を防ぎやすくなります。ファイルをロックするための例は、Prompt ライブラリのセクションですでに紹介しました。ここでは、壊さないことにフォーカスした同様のパターンを紹介します。 プロンプト例 – 壊れやすい更新のためのガイダンス:
次の変更は**アプリの重要な部分**に関わるため、**細心の注意**を払って進めてください。

- 変更を加える*前に*、関連するすべてのコードと依存関係を注意深く確認してください。
- 無関係なコンポーネントやファイルへの**変更は一切避けて**ください。
- 不確実な点がある場合は、一旦停止し、続行する前に思考プロセスを説明してください。
- 変更後は徹底的にテストを行い、他の部分に影響がないことを確認してください。

**タスク:** 既存のメール/パスワード認証フローを壊すことなく、Google経由のOAuthログインをサポートするようにユーザー認証ロジックを更新してください。

*(実装中は極めて慎重に、各ステップを再確認してください。)*
斜体のガイドラインや太字の警告を含めることで、AI の「マインドセット」が慎重になるように設定していることになります。すると AI は、まず何をするか説明してから進めたり、OAuth の追加を実装しつつ「メール/パスワード認証はそのまま残した」ことを明示したりと、より慎重なアプローチを取る可能性があります。このプロンプトはすぐに解決策を出力するのではなく、新しいバグが入り込むのを最小限に抑えられるように、AI がタスクをどのように実行するかに影響を与えます。 この戦略は、認証、決済処理、データ移行など、ちょっとしたミスで大きな問題につながるデリケートな箇所に役立ちます。いわば、事前のデバッグ対策です。

パフォーマンス最適化チェック

アプリが正しく動作しているものの、動作が遅い、またはリソース消費が大きい場合は、プロンプトを使って AI にパフォーマンスを分析させることができます。これには、データ取得パターンの見直し、レンダリングで非効率な部分の確認、あるいは最適化(キャッシュ、メモ化 など)の提案が含まれる場合があります。イメージとしては、「どうすればもっと速く、スムーズにできる?」と尋ねるようなものです。 プロンプト例 – パフォーマンス監査:
アプリは機能していますが、**動作が重い**ようです。**プロジェクトのパフォーマンスボトルネックを分析**し、最適化案を提案してください:

- 不要なデータベースやネットワーク呼び出し(重複したフェッチやN+1クエリパターンなど)がないか確認してください。
- 再レンダリングが頻繁に発生している、またはメインスレッドで重い処理を行っているコンポーネントを特定してください。
- アセット(画像、スクリプト)の使用状況を確認してください:読み込み時間に影響を与える大きなバンドルや最適化されていないアセットはありますか?
- 頻繁に使用されるデータのキャッシュ、適切な箇所でのReact memoや遅延読み込みの使用など、アプリを高速化する改善策を提案してください。

分析と推奨事項をリスト形式で提供してください。まだコードの変更は行わず、パフォーマンス向上のために改善すべき点を教えてください。
Chat mode でこれを実行すると、診断レポートが得られます。AI は例えば次のように言うかもしれません:
  • 「データ取得: ProjectList コンポーネントは、レンダーのたびにデータを取得しています。これはキャッシュを使うか、フェッチ処理をより上位のコンテキストに移動することで、不要な繰り返しを防ぐよう改善できます。一度取得したプロジェクトを保持するために、state や context の使用を検討してください。
  • 再レンダー: TaskItem コンポーネントはメモ化されておらず、親の state が変わるたびに再レンダーされます。タスクが多い場合、これがインタラクションを遅くする原因になります。提案: 不要な再レンダーを防ぐために、TaskItemReact.memo を使用してください。
  • アセット: 2MB の画像(ロゴ)が見つかりました。かなり大きいので、圧縮するか、読み込みを速くするために解像度を下げてください。
  • バンドルサイズ: すべてのページが 1 つのバンドルに含まれています。初期ロードを高速化するために、大きなモジュールには動的な import() を使うなど、コード分割を検討してください。
  • …」*
それぞれの提案は、一般的なパフォーマンスのベストプラクティスに基づいています。そのうえで、どれを実装するかをあなたが決めます。例えば、Lovable に対して次のようにプロンプトするかもしれません: 「提案どおり、context を使ってプロジェクトデータのキャッシュを実装してください。」 これらに対応することで、ユーザー体験が向上し、(呼び出し回数の減少や計算量の削減により)コスト削減にもつながる可能性があります。

永続的なエラーへの対処

なかなか消えなかったり、少し形を変えて何度も現れたりするエラーはどうすればいいでしょうか?これは、根本原因に対処できていない場合に起こりがちです。例えば、ひとつの箇所は直しても、根本的な問題が別の場所で新しいエラーとして現れることがあります。そんなときの戦略は次のとおりです。
  • AI に、これまで試したことを確認する。 「Try to Fix」を何度か実行したり、手動でプロンプトを送ったりしたあとだと、何が変更されたのかわからなくなることがあります。次のように聞いてみてください:_“What solutions have we tried so far for this error?”_​。AI がこれまでの試行内容を列挙してくれるので、同じ修正を繰り返すのを避けられます。
  • AI にエラーをわかりやすい言葉で説明させる。 “Explain in simple terms why this error occurs.” と聞いてみましょう。AI(とあなた)が本当にエラーを理解できているかどうかがわかります。ここで思い違いに気づけることもあります。
  • 別のアプローチを検討する。 次のように聞いてみてください:_“Given this error keeps happening, can we try a different approach to achieve the goal?”_​。AI が、問題のある箇所を回避できる別の実装戦略を提案してくれるかもしれません。
  • 巻き戻してやり直す。 最悪の場合、いくつか前のステップまでロールバックすることもあります。Lovable では、古いバージョンに戻したり、過去のメッセージを編集して別のアプローチを試すことができます。そのうえで、小さな変更を積み重ねていきましょう。
最後に、特定のコンポーネントが「完全に死んでいる」(何をしてもまったく動かない)場合は、切り離してみてください。プロンプトを使って、そのコンポーネントの最小限の新しいバージョンを作成し、それが動作するかを確認してから、少しずつプロジェクトに統合していきます。これは電源のオン・オフに近い考え方ですが、コードでそれをやっているようなイメージです。ひどく壊れてしまったものを無理に修正するより、部分的に作り直したほうが楽なこともあります。 これらすべてを通して、AI との対話を続けてください。共同作業者として扱い、“We fixed X but now Y is acting up. What’s the relationship between X and Y? Could the fix have caused Y’s issue?” のように聞いてみましょう。AI が、あなたが気づかなかったつながりを見つけてくれるかもしれません。

デバッグフローのサンプル

ここまでの内容を定着させるために、代表的なデバッグシナリオを 2 つ取り上げて、フローの例を見ていきましょう。

「エラーの無限ループ」にハマったとき

複雑なことをプロンプトで依頼した結果、アプリがビルドできなくなり、Try to Fix を 2 回試しても失敗してしまいました。 Flow:
1

Chat mode に切り替えます。

2

「このビルドエラーの根本原因は何ですか?」と尋ねます。

3

AI は、API 呼び出しでの型の不一致が原因だと説明します。

4

続けて「関連するコードと、期待される型を見せて」と依頼します。

5

AI は、その関数が ID の数値を期待しているのに、オブジェクトを受け取っていることを示します。

6

原因が分かったので、「関数にはオブジェクト全体ではなく数値の ID だけを渡すようにコードを調整して」とプロンプトします。

7

Default に切り替えてそのプロンプトを実行すると、ビルドは成功します。

8

もし成功しなければ、戻って「ほかに何が原因になりえますか?」などとさらに尋ねます。

この一連の流れでは、エラー内容を具体的に説明し、AI に理解を確認させています。単に「直す」ボタンを闇雲に連打しているわけではありません。

「機能が正しく動作しない」場合

通知機能を追加したのに、メールが送信されません。 Flow:
1

エラーは表示されないので、チャットで「メール通知が動作しません。タスクが期限切れになったときにメールが届くと思っていましたが、何も来ませんでした。どうやってデバッグすればいいですか?」と聞きます。

2

AI は、サーバー関数がトリガーされたかどうか、またメールサービスのレスポンスにエラーが含まれていないかを確認するよう提案します。

3

サーバーログ(おそらく Supabase など)を確認すると、パーミッションエラーが出ていることがわかります。

4

その内容を AI に見せて、「ログには『メール送信時に permission denied と出ています』と書かれています」と伝えます。

5

AI は、メールサービス用の APIキー が設定されていないか、サービス側でブロックされた可能性があると判断します。

6

その後、設定(Lovable の外側)で APIキー を修正するか、別の方法を使うように関数を調整するプロンプトを送ります。

要するに、「期待していること(メールが届く)」と「実際に起きたこと(何も起きていない+ログのスニペット)」を説明することで、AI が調査の進め方を案内できるようになります。

「UI 要素が消えてしまった」

リファクタリングをしたら、UI のセクション全体が丸ごと消えてしまった(いわゆる「死んだコンポーネント」)状態です。 フロー:
1

AI に「プロジェクト一覧セクションがまったく表示されなくなりました。最後の編集までは動いていました。」と伝えます。

2

AI は、そのコンポーネントがまだレンダーされているか、または return 文が抜けていないかを確認するかもしれません。

例えば、リファクタリングで親の JSX から ProjectList が削除されてしまったことに気づくかもしれません。AI は、それを再インポートして含めるよう提案します。あるいは、親コンポーネント側の state の変更によって、意図せずリストがフィルタリングされてしまっている可能性もあります。
3

AI は「データはまだフェッチされていますか? コンポーネントはそのデータを受け取れていますか? props を受け取れているか確認するために、render 内に console.log を追加してみましょう」といった可能性を順番に検証してくれます。

4

あなた(または AI がプロンプト経由で)それを実行してみても、何もログが出ないことがわかります ― つまりコンポーネントがマウントされていないということです。

なるほど! そこで、「Dashboard ページの JSX に <ProjectList> を復元してください(誤って削除されました)。」 とプロンプトを送ります。問題は解決です。
このフローでは、「コンポーネントが完全に消えている」ことに気づき、それをきちんと伝えることが重要でした。AI は、「なぜ」そうなったのか(まったくレンダーされていないのか、レンダーはされているが中身が空なのか、など)を特定する手助けをしてくれます。
Dev tools とコンソールログの活用
アプリが動かなくなり、画面が真っ白になってしまいました。
これは Dev tools のコンソールからコピー&ペーストした内容です。問題を修正してもらえますか?

Error occurred:
TypeError: Q9() is undefined  at https://example.lovable.app/assets/index-DWQbrtrQQj.js
: 435 : 39117 index-DWQbrtrQQj.js:435:35112
onerror https://example.lovable.app/assets/index-DWQbrtrQQj.js:435
これらすべてのケースで重要なのは、コミュニケーションと小さなステップの積み重ね です。AI の「詳細を覚えておく力」(以前に何をしたかなど)や、ログやエラーを分析する力を活用しましょう。そして、あなたの「プロセスを舵取りする力」も活かしてください ― あなたは高レベルのゴールを理解しており、いつ別のアプローチを試すべきか判断できます。

根本原因分析、ロールバック、プログレッシブ エンハンスメント

最後に、いくつかアドバイスをお伝えします。

根本原因と症状

「今どうするか?」だけでなく、「なぜこうなったのか?」を必ず自問しましょう。AI は根本原因の特定を手伝ってくれるので、一度修正したらその状態を維持しやすくなります。例えば、AI によるその場しのぎの修正は、エラーを表面的に消すだけで、根本にあるロジックバグを解消していない場合があります。その疑いがあるときは、さらに深掘りしましょう:
null ポインタエラーをチェックの追加で直してくれたのは分かりましたが、そもそもなぜ null だったのでしょうか?その原因自体に対処できませんか?
こうすることで、より堅牢な解決策につながります。

ロールバックを賢く使う:

Lovable では、以前のバージョンにロールバックできます。悪い修正が重なってコードがこんがらがってしまった場合は、ためらわずに使いましょう。巻き戻して別のアプローチを試したほうが早いことはよくあります。ロールバックした場合は、AI にも「今なにをしているか」を伝えてください(そうしないと、急にコードが変わって混乱してしまう可能性があります)。例えば、次のように伝えます:
通知機能を追加する前の状態にプロジェクトを戻しました。もう一度実装しますが、今回はもっと慎重に進めましょう。
こうすることで、AI は「一度加えた変更を元に戻し、もう一度やり直している」というコンテキストを理解できます。

段階的な拡張(プログレッシブエンハンスメント):

新機能(特に複雑なもの)を追加するときは、小さくテストしやすい単位で段階的に実装していきましょう。これは単なるプロンプトのコツではなく、AIと相性のよい開発哲学でもあります。何かが壊れたとしても、どの小さなステップが原因だったのかを正確に特定できます。プロンプトごとにアプリを拡張していくことで、同時にプロンプト単位で個別にデバッグできるようになります。もし一度に複数の機能変更を含む、段落レベルの長いプロンプトを書いている自分に気づいたら、それを複数のプロンプトに分割することを検討してください。後からトラブルシューティングが必要になったとき、きっと助かったと感じるはずです。
  1. 失敗するテストケースを追加する。
  2. 問題を切り分けて依存関係を分析する。
  3. 修正を適用する前に、判明した内容を記録する。
こちらが失敗しているコンソールログです。テストケースを分析し、認証フロー内のエラーを調査して、依存関係を踏まえたうえで解決策を提案してください。

作業しながらドキュメント化する:

メモを取りながら進めると便利です(セッションのあとに AI に「今やったことを要約して」と頼んでもかまいません)。これはリバースメタプロンプトに近いもので、修正の履歴を作ってくれます。たとえば、厄介なバグを解決したあとに、次のようなプロンプトを送ることができます:
問題が何だったか、そしてそれをどのように解決したか要約してください。
AI が作成した要約は README やログに保存できます。将来の自分や、プロジェクトの他のメンバーが何が起きたのか理解するのに役立ちます。

人の助けを求めるべきタイミングを見極める:

どれだけ頑張っても行き詰まってしまうことがあります(Lovable プラットフォーム自体のバグや、あなたや AI のコントロール外の問題など)。そんなときのために、Lovable のコミュニティとサポートがあります。質問があるときに Discord やフォーラムに投稿することは、まったく問題ありません。同じような問題を経験している人は少なくありません。まずは AI を使ってできる限り多くの情報を集めて(詳細を共有できるようにして)から、必要に応じてコミュニティに質問しましょう。

コミュニティ向けデバッグガイドブック

このガイドブックはコミュニティのDiscordで共有されているもので、プロジェクトのデバッグに役立つかもしれません。
エラーを修正するときは、関連するコードセクションのみに集中し、正常に動作している無関係な部分は変更しないでください。エラーメッセージを分析し、その原因を突き止めます。既存のコードベースとの互換性を保ちながら、特定の問題に対処する的を絞った修正を実装してください。どの解決策についても、確定する前に、元の問題を確実に解消し、新たなバグを生んでいないことを検証します。動作している機能は常に維持し、エラーに直接関係しないコードを書き換えることは避けましょう。
既存のコードを変更する場合は、要求された機能や修正を実装するために本当に必要な部分だけを変える、外科的なアプローチを取りましょう。コードベースに存在する変数名、コーディングパターン、アーキテクチャ上の設計判断は維持してください。変更を提案する前に依存関係を分析し、修正によって既存の機能が壊れないことを確認しましょう。変更内容は全面的な書き換えではなく、可能な限り最小限の差分として提示してください。即時のタスクを超える改善点を見つけた場合は、自動で実装せず、別途提案として提示してください。
新しいデータベース構造を提案する前に、既存のスキーマを十分に確認し、すでに存在するテーブルやリレーション、フィールドを把握してください。データモデルを重複させるのではなく、可能な限り既存のテーブルを活用しましょう。データベースに変更が必要な場合は、既存のクエリやデータアクセスパターンと互換性があることを必ず確認してください。スキーマ変更に伴っても既存データを保持できるようなマイグレーション戦略も検討してください。変更を提案する前に、常に外部キーやデータ整合性制約を検証してください。
あらゆる問題には、包括的な診断プロセスで取り組みましょう。まずはエラーメッセージ、ログ、システムの挙動を丁寧に確認し、関連する情報をすべて収集します。性急に結論を出すのではなく、考えられる原因について複数の仮説を立てます。各仮説を体系的に検証し、根本原因が特定できるまで続けます。解決策を提案する前に、分析の過程と結果を必ず記録に残します。考えられるエッジケースと、それらがシステムにどのような影響を与えるかも検討しましょう。
どの解決策も確定する前に、必ず厳密な検証プロセスを実施してください。問題を解決できているか確認するために、元の問題に対してその解決策をテストしてください。関連する機能に予期しない副作用がないか確認してください。パフォーマンスが悪化していないことを確認してください。さまざまな環境や設定との互換性を検証してください。エッジケースを一通り試し、堅牢性を確認してください。これらの検証をすべて完了してはじめて、その解決策を確定したものとして提示してください。
スタイルやパターン、アプローチの面で、既存のコードベースとの一貫性を保ちましょう。コードを分析して、命名規則、フォーマットの傾向、アーキテクチャパターンを把握します。新しい機能や修正を実装する際には、これら確立されたパターンに従ってください。プロジェクト内で使われているものと同じエラーハンドリング戦略、ロギング手法、テスト手法を使用します。そうすることで、開発者の認知負荷を減らしつつ、可読性と保守性を維持できます。
新しい機能を追加する際は、まったく新しいパラダイムを導入するのではなく、既存のアーキテクチャをベースに拡張するようにしてください。現在の設計の中から拡張ポイントを特定し、新しい機能のためにそれらを活用しましょう。コードベースで確立されているパターンや原則に沿う形で変更を実装してください。既存の機能が期待どおりに動作し続けるよう、後方互換性を重視しましょう。新しい追加分が既存システムとどのように統合され、どのようにそれを拡張しているのかを文書化してください。
すべての変更内容と提案について、明確で簡潔な説明を提供してください。どんな変更を行うのかだけでなく、なぜそれが必要なのか、どのように機能するのかも必ず説明してください。解決策に含まれる前提条件や依存関係は、すべて文書化してください。複雑なロジックや一見して分かりにくい解決策を導入する場合は、コード内にコメントを記載してください。アーキテクチャの変更を提案する際は、その影響を視覚的にイメージしやすくするために、図やハイレベルな説明を併せて提供してください。
解決策が技術的負債(テクニカルデット)を生み出しうる場合を見極め、こうしたトレードオフについて率直に共有してください。時間的な制約から理想的とは言えない解決策を選ばざるを得ないときは、将来的にどの部分をリファクタリングすべきかを明確にしておきましょう。場当たり的な応急処置と本質的な解決策を区別し、状況に応じて適切なアプローチを提案してください。技術的負債が避けられない場合は、将来の改善を進めやすくするために、その内容を明確に文書化しておきましょう。
プロジェクト固有のパターンや好みに継続的に適応していってください。これまでの提案に対するフィードバックに注意を払い、その学びを今後の提案に反映させてください。アプリケーションのアーキテクチャについて、時間の経過とともに精度が高まる頭の中のモデルを構築してください。過去の問題とその解決策を覚えておき、同じ間違いを繰り返さないようにしてください。技術的な判断の背景にある根本的なビジネス要件を積極的に理解するよう努めてください。
新しいページ、コンポーネント、またはフローを作成する前に、まずコードベース内にどんな既存要素があるかを徹底的に棚卸ししましょう。関連するキーワードやファイルパターンを使って、類似する機能を検索します。重複を作成するのではなく、既存のコンポーネントを再利用・拡張できる機会を特定してください。似た機能がすでに存在する場合は、それらを分析し、重複させるのではなく、パラメータ化や調整で対応できるかどうかを見極めましょう。提案している解決策が冗長な要素を生み出してしまわないよう、アプリケーション構造を頭の中でしっかりと把握しておきましょう。類似したページやフローが必要な場合は、異なるデータや設定で再利用できる抽象化されたコンポーネントの作成を検討し、DRY(Don’t Repeat Yourself)の原則を徹底しましょう。
使われていないコードを放置して蓄積させるのではなく、積極的に特定して削除してください。機能を置き換える場合は、単にコメントアウトしたり新しいコードの横に残したりするのではなく、古い実装はきれいに削除してください。コードを削除する前に、アプリケーション全体でそのコードが使われていないか、インポートや参照を確認して検証してください。利用可能であれば、依存関係解析などのツールを使って、そのコードが本当に未使用であることを確認しましょう。リファクタリング時には、非推奨メソッドを追跡し、参照されなくなったタイミングで確実に削除してください。孤立したコンポーネント、未使用のインポート、コメントアウトされたブロック、到達不能な条件を定期的にスキャンしましょう。コード削除を提案する際は、それが「デッドコード」と見なされる理由を明確に示し、削除前に見落としている依存関係がないかを確認してください。もはや実行されないコードパスの排除を優先することで、コードベースのクリーンさを維持しましょう。
動作している機能は、変更するには明示的な許可が必要な「ロックされたシステム」として扱ってください。正常に動作しているコンポーネントに変更を提案する前に、その境界と依存関係を必ず明確に特定します。明確な指示がない限り、現在稼働中の機能を削除したり、大きく変更したりしないでください。ある領域でエラーが発生しても、動いている無関係なコンポーネントに対して、念のための変更(“just in case” な変更)を行うことは避けましょう。アプリケーションのどの部分が安定していて、どの部分が開発中なのかを、常にはっきり把握しておきます。変更は特定の機能セットに限定し、他の機能に影響が漏れ出さないようにする「機能単位」のアプローチを取ってください。複数の機能で利用される共通コンポーネントを変更する場合は、依存するすべての機能が引き続き期待どおり動作することを必ず確認します。影響を与えそうな変更を行う前に、機能をまたいだ依存関係を十分にドキュメント化しておくことで、安全策を講じてください。アプリケーション内の、既に確立され正常に動作している部分に変更を提案する際は、常にその変更の意図を明示的に確認するようにします。
複雑なエラーに直面したときは、深く理解しないまま、その場しのぎの修正を加えたい誘惑をぐっとこらえてください。解決策を提案する前に、一歩引いて立ち止まり、複数の視点から問題を検証しましょう。同じ戦略の些細なバリエーションではなく、根本的に異なるアプローチを検討してください。特定のアプローチを推奨する前に、少なくとも 3 つの候補となる解決策を、その長所と短所とともに文書化しましょう。特に標準的な対処法がうまくいかない場合は、エラーの原因に関する当初の前提を疑ってください。環境設定、外部依存関係、一見すると気づきにくいレースコンディションなど、通常とは異なる原因も視野に入れましょう。思考を逆転させてみてください。「なぜこれは動かないのか?」ではなく、「どのような条件であれば、この挙動に実際に納得がいくだろうか?」と自問してみましょう。複雑な問題は、個別に検証できる小さな要素に分解しましょう。エラーの原因が依然として不明なときは、ログ出力、ブレークポイント、状態トレースなど、ピンポイントなデバッグ戦略を実施して、より多くの情報を集めてください。特に原因がつかみにくい問題に取り組む際には、最終的な解決策ではなく学習の機会として、実験的な修正案を提案する姿勢を持ちましょう。
データベースのクエリやスキーマの変更を提案する前に、必ずデータベースの現在の状態を確認してください。既存のテーブル、フィールド、リレーション(テーブル間の関係)を調べて、すでに存在している要素の作成を推奨してしまわないようにします。クエリを提案する際は、まずコードベース内に流用できる類似のクエリがないかを確認してください。既存のデータモデル、マイグレーションファイル、スキーマ定義を確認し、データベース構造を正確に把握します。新しいテーブルの作成を提案する場合は、そのテーブルがすでに存在していないことを明示的に確認し、既存テーブルの変更ではなく新しいテーブルが必要となる理由を説明してください。フィールドの追加を提案する際には、同じ目的を別名で果たしている類似フィールドがすでに存在しないかを確認します。提案するクエリがデータベースパフォーマンスに与える影響を考慮し、必要に応じて最適化された代替案を提示してください。クエリの提案は、常に既存のデータベースアーキテクチャの文脈の中で行い、個別の操作として切り離して扱わないようにします。
アプリケーション全体を通して、確立されたデザインシステムとカラーパレットを厳密に順守してください。新しい UI コンポーネントを作成する前に、既存のコンポーネントを確認し、ビジュアル言語、余白のパターン、インタラクションモデル、テーマ設定のアプローチを理解しましょう。新しいインターフェースを実装する際は、ビジュアルのバリエーションを増やすのではなく、既存のコンポーネントパターンを再利用してください。新しい値を導入するのではなく、既存のコードベースから色の値、タイポグラフィ、余白、その他のデザイントークンを抽出して使用してください。すべてのコンポーネントにわたって、状態(ホバー、アクティブ、無効、エラーなど)を一貫して扱ってください。新しいレイアウトを実装する際は、確立されているレスポンシブ挙動のパターンに従ってください。UI 改善を提案する場合は、アプリケーション全体のビジュアルな一体感を損なうのではなく、高める方向であることを確認してください。カラーコントラスト比、キーボードナビゲーション、スクリーンリーダー対応など、すべてのコンポーネントでアクセシビリティ標準を継続的に満たしてください。コンポーネントのバリエーションとその適切な利用シーンを文書化し、一貫した適用ができるようにしてください。新しいビジュアル要素を導入する際は、それが既存のデザインシステムとどのように統合され、補完し合うのかを明示し、単独で浮いた存在にならないようにしてください。
エラーに遭遇したときは、闇雲に変更を加えるのではなく、系統立てたデバッグ手法を取りましょう。まず、再現性のある制御された環境で、まったく同じ問題を再現することから始めます。コンソールログ、ネットワークリクエスト、コンポーネントの状態、エラーメッセージなどを含む網羅的なデータを収集します。考えられる原因について複数の仮説を立て、それぞれを体系的に検証します。影響を受けているコンポーネントを絞り込み、発生条件を特定することで問題を切り分けます。今後の参考のために、デバッグの手順と結果を必ず記録しておきましょう。ブラウザの開発者ツール、React DevTools、コードレベルのデバッグ手法など、適切なデバッグツールを活用します。解決策がアプリケーションの他の箇所に新たな問題やリグレッション(退行バグ)を生むことなく、問題を完全に解消しているか必ず確認してください。
機能を実装する前に、まずデータベーススキーマと TypeScript のインターフェースの両方について、型定義を徹底的に確認・分析してください。コードベース全体で厳格な型チェックを維持し、逃げ道としての any 型の使用は避けましょう。データ変換を行う際は、パイプラインの各ステップで型安全性を検証してください。特に、数値カラムが文字列として渡されるケース、日付のパースが必要なケース、null になり得るフィールドの扱いなど、よくある型の不一致に注意を払ってください。データベースのカラムと TypeScript インターフェースの間で、一貫した命名規則を適用しましょう。複雑な型の関係や特別な取り扱いが必要な点は、必ずドキュメント化しておいてください。実際のデータの形(シェイプ)を使ってテストを行い、特に null / undefined の扱いなどのエッジケースを検証してください。エラーが発生した場合は、データ変換パイプラインをさかのぼり、型がどこで食い違っているかを正確に特定し、型安全性を維持できる修正を検討してください。
データフローを、データベースから API、ステートを経て UI に至る一連のパイプラインとして捉えましょう。機能を実装するときは、各段階でデータがどのように変換されるかを慎重に追跡してください。適切なクエリのインバリデーションパターンを実装し、UI がデータベースの状態と常に同期した状態を保てるようにします。重要なポイントに戦略的に console.log などのログを追加し、データの遷移を監視しましょう。アクションに応じてデータがいつ、どのように更新されるべきかについて、明確なメンタルモデルを作ってください。キャッシュ戦略と、データの陳腐化(stale data)の問題に細心の注意を払いましょう。フローに問題があるときは、データの流れをソースから最終的な到達点まで、段階的にたどってデバッグします。タイミングの問題、レースコンディション、変換エラーを確認してください。コンポーネントに到達する最終的なデータ構造が、コンポーネントの期待どおりであることを検証しましょう。データフローに障害が発生したときでも UI の安定性を保てるよう、堅牢なエラーバウンダリとローディング状態の管理を実装してください。
アプリケーションのパフォーマンスは、問題が深刻化するのを待つのではなく、あらかじめ積極的に監視しましょう。不要なデータベース呼び出しを最小限に抑えるために、クエリキャッシング戦略を見直します。適切なメモ化や依存関係管理によって、不要なコンポーネントの再レンダーが発生していないか確認し、排除します。データ取得パターンを分析し、潜在的な N+1 クエリ問題、過度なウォーターフォール構造、冗長なリクエストがないか確認します。長いリストには仮想化(virtualization)を導入し、大規模なデータセットにはページネーションを実装します。コード分割や遅延読み込み(lazy loading)によってバンドルサイズを最適化します。画像を含むアセットを圧縮・最適化します。React DevTools、Performance タブ、Network パネル、Memory プロファイラなどの適切なパフォーマンス計測ツールを使用してボトルネックを特定します。読み込み時間、インタラクティブになるまでの時間(time to interactive)、UI の応答性など、ユーザー体験に直接影響する指標に最適化の焦点を当てましょう。闇雲な早期最適化ではなく、狙いを絞ったパフォーマンス改善を実施します。
アプリケーションの安定性を維持しつつ、有益なフィードバックを提供できる包括的なエラー処理戦略を実装してください。問題が発生しそうなコード箇所を中心に、try/catch ブロックを戦略的に配置します。アプリケーション全体がクラッシュするのではなく、特定のコンポーネント内に障害を閉じ込められるよう、エラーバウンダリの階層構造を作成します。コンポーネントが限定的なデータでも動作を続けられるような、グレースフルデグレーデーションパターンを設計します。問題を専門用語なしで説明する、明確でユーザーフレンドリーなエラーメッセージを提供します。リトライロジック、フォールバック、状態リセットなどを含むリカバリ機構を実装します。プライバシーに配慮しつつ、デバッグに十分なコンテキストを取得できる堅牢なエラーロギングを維持します。エラーシナリオを徹底的にテストし、リカバリ機構が期待どおりに動作することを確認します。解決策を提案する際は、症状を単に抑え込むのではなく根本原因に対処していること、そしてすべての関連する環境とエッジケースで機能することを必ず検証してください。
コンポーネントの設計にあたっては、コンポーネントの階層構造と責務を明確に理解しておきましょう。コンポーネントを、適切な親子関係を持つ家系図としてイメージします。必要に応じて context や状態管理を戦略的に用いることで、props の深い受け渡し(prop drilling)を最小限に抑えます。コンテナ(スマート)コンポーネントとプレゼンテーショナル(ダム)コンポーネントの間に、明確な境界を設けます。親子間や兄弟間のやりとりを含め、コンポーネント間のやりとりパターンを一貫して整えます。コンポーネントの問題をデバッグする際は、コンポーネントツリー全体、props のフロー、状態の所在、イベントハンドラーの接続を分析します。コンポーネントは単一責務と明確なインターフェースを持つように設計します。将来の保守を容易にするために、コンポーネント同士の関係性と依存関係をドキュメント化します。メモ化、遅延読み込み、コード分割などのパフォーマンス最適化を、効果が見込める箇所に導入します。コンポーネントの再利用性と特化度のバランスを保ち、重複と過度な抽象化の両方を避けましょう。
API 連携には、リクエスト、レスポンス、エラーハンドリングを包括的に考慮した戦略で取り組んでください。各リクエストごとに、認証ヘッダー、パラメーター、ボディ形式を確認します。すべてのネットワーク処理に対して適切なエラーハンドリングを実装し、エラー種別ごとに個別にハンドリングします。リクエストペイロード、想定されるレスポンス、アプリケーションの状態の間で型が一貫していることを保証します。適切な CORS 設定を行い、すべての環境で正しく動作することを確認します。一時的な失敗に対しては、指数バックオフを用いたインテリジェントなリトライ機構を実装します。レート制限の影響を考慮し、適切なスロットリングを実装します。パフォーマンス向上とサーバー負荷軽減のために、戦略的にリクエストのキャッシュを追加します。リクエストのタイミングやペイロードサイズを含め、ネットワークパフォーマンスを監視します。正常系(ハッピーパス)だけでなく、さまざまな失敗シナリオに対しても API 連携をテストします。将来の開発やデバッグを容易にするために、すべての API エンドポイントについて、その目的、想定パラメーター、レスポンス形式を明確に文書化しておきます。