リファクタリング & プロダクト化 — Vibe Coding 時代の心得

前半:動きを変えずに「読みやすく・直しやすく」するリファクタリングの原則後半:ブラウザだけで動く試作を、安全に段階を踏んで「プロダクト対応」にする実践ロードマップ。 通底する合言葉は「動きは変えない/小さく刻む/テストで守る」。ゴールは 人間(と AI)が短時間で把握できるコード。


1. 基本の原則(まず「人間が把握できる」コードに)

🧪 テストできる形に書く

  • 「テストを書く」→ 「テストが“書ける”ように書く/直す」
  • テストしにくい=密結合・副作用まみれのサイン。テストのしやすさ=設計の良さの物差し
  • コツ:入力→出力が決まる純粋関数に切り出す/DB・API・時刻・乱数などの外部依存は引数で渡す(中で直に呼ばない)。

♻️ 重複を消す(DRY)

  • コピペ=関数化/似た処理=共通化して関数化・抽象化
  • 同じ知識が2か所にあると直し忘れでバグる。「1つの知識は1か所」に集約。
  • ⚠️ 「たまたま似てるだけ」を無理に1つにしない(早すぎる抽象化に注意)。目安は「3回目に出たら共通化を検討」。

📏 小さく保つ

  • 1関数 20行以下 / 1ファイル 400行以下(目安)。
  • 人間がひと目で把握できる大きさに。長い=責務を持ちすぎのサイン。
  • コツ:長い関数は「意味のまとまり」で小関数に分け、良い名前で説明する(コメントより良い名前)。

🔌 疎結合にする(依存をなくす)

  • 部品どうしの絡みが少ないほど、1か所の変更が他へ波及しない=安全に直せて、テストもしやすい。
  • コツ:直接 new せず引数で受け取る(依存性注入)/具体でなく“約束(interface)”に依存する。

🔀 条件を整理する

  • 深いネスト・複雑な if読み違い=バグの温床
  • コツ:早期 return(ガード節)で入れ子を浅く/条件は名前付きにする(例:const isAdult = age >= 18)。

2. Vibe Coding 時代に、さらに効くこと

AI(LLM)は、ざっくり言えば 「学習データをもとに“もっともらしい次のトークン”を、速く大量に生成する」 道具です。ここから素直に導けるのが、次の効きどころ。上の基本原則が さらに重要になる理由 でもあります(各項目=事実 → だから)。

🤖 速い・大量・でも間違える → 機械で検証する

  • 事実:確率で生成するので、存在しない API や微妙にズレたコードを自信満々に出す(幻覚)。しかも人間より速く大量に積み上がる。
  • だから型(any を避ける)で矛盾を早期に落とし、テストで“動き”を固定し、diff を必ず読む。AI にテストを書かせてもよいが、「通るだけの空テスト」になっていないか人間が確認する。未読でマージしない

🧠 見えるのはコンテキスト内だけ → 読める文脈を渡す

  • 事実:AI は渡された範囲(コンテキスト)しか見られない。大きく散らかったコードは全体を把握できず、部分だけ見て矛盾を生む。
  • だから小さく・良い名前・型付きにするほど AI の精度も上がる(=人間向けの整理は、そのまま AI 向け)。CLAUDE.md / AGENTS.md・doc で決まりと文脈を明示的に渡すライブラリ構成を先に指定すると、AI の共通化(DRY)が的確になる。

🌱 学習データに多いほど正確 → 枯れた定番を選ぶ

  • 事実:学習データに多く登場する“枯れた”技術ほど AI は正確。マイナー・新しすぎる技術は知識が薄く、幻覚が増える。
  • だから:ネットに情報が多い定番を選ぶ(AI がよく知っている=手戻りが減る)。

🪓 律速はレビュー帯域 → 小さく刻む

  • 事実:生成は速いが、人間が読んで確かめられる量が律速。大きな差分ほど間違いが埋もれる。
  • だから細粒度のコミット/PRにして、各段でテスト・レビュー。大改造を一気にやらせない。すぐ戻せる粒度に。

🧾 AI は What を書くが Why を持たない → 意図と prompt を残す

  • 事実:AI は指示から生成するだけで、その判断の理由は残らない。渡した指示(prompt)が実質のソース。
  • だから非自明な“なぜ”はコメント/PR 説明/決定記録に残す。AI に渡す md・指示もすべて git 管理(text=context がすべて)。

🛡✂️ AI は「動く」を優先 → セキュリティと“やりすぎ”を人間が締める

  • 事実:AI は動くコードを優先し、鍵の直書き・危険な依存・不要な抽象/重複を出しがち。
  • だから秘密・インジェクション・依存(サプライチェーン)を点検し、要らない抽象・重複は削る(YAGNI)。「動く」で満足せず、“ここが危ない/ここが安全”を読む目を持つ。

3. 「気をつける」をやめて、ルールで自動化

原則は根性では続かない。linter / formatter / CI に落として、機械に指摘させる。レビューが「人の好み論争」でなく「客観ルール」になります。

  • ESLintmax-lines-per-function(関数の長さ)/max-lines(ファイル)/complexity(複雑さ)/max-depth(ネスト)/@typescript-eslint/no-explicit-any
  • 重複検出jscpd などでコピペを可視化。
  • Prettier:整形は自動(好みの議論をなくす)。
  • CIlint / typecheck / test通らなければマージをブロック
  • ルールは最初はゆるく、少しずつ厳しく

4. いつ・どう進める?(リファクタリングのタイミング)

基本は「変更のたび、ついでに」。 リファクタリング専用の“いつか”を待たず、日々の変更に混ぜます。

  • 🥾 変更のついでに:機能追加やバグ修正で触ったところを、来たときより少しきれいにして帰る(ボーイスカウト・ルール)。
  • 🧱 機能追加の“前”に(準備):足しづらいと感じたら、先に整えてから足す。「変更を簡単にしてから、簡単に変更する」。
  • 💡 理解できたとき:ぐちゃっとしたコードの意味がやっと分かったら、その理解を名前・構造に刻む
  • 👀 レビュー/PR のとき:気づいた小さな改善はその場で。
  • 🔁 テストのリズム:TDD なら レッド → グリーン → リファクタ(テストが通った直後に整える)。
  • ⚠️ 避けたい:ぜんぶ後回しにして「いつか大改造」。リスクが大きく、たいてい止まります。小さく継続が勝ち。

どう安全に?(動きを変えないための順番)

  1. テストで「いまの動き」を固定する(回帰テスト)。
  2. 小さく直す(1つの意図だけ)。
  3. テストが緑のままを確認 → コミット。
  4. くり返す。

迷ったら:「これは “動き” を変えていないか?」 と自問する。変えるなら、それはリファクタリングでなく 機能変更分けて行う。


5. 実践:ブラウザだけの試作を「プロダクト対応」にする道のり

いま:全部ブラウザで動く(HTML/JS だけ・サーバーなし・データは各自の画面の中)。試作にはこれで十分。でも「人に使ってもらう・課金する」には足りません。

大事なのは、いきなり作り直さないこと。下の順で“地ならし”してから積み上げます。この順番自体に意味があります——各ステップが次のステップの前提になっているからです(前半=リファクタリング、後半=その土台の上にプロダクトの背骨を積む)。

  1. 🧪 現状のまま、ユニットテストを“書ける”ようにする
    • まず動きを変えずに、テストが書ける形へ。これが以降の改造すべての安全網(回帰テスト)になる。
    • テストしにくい場所は、次の分離で「どこを剥がすか」の地図にもなる。
  2. ♻️ 現状のまま、リファクタリングして整理・コンパクトに
    • テストが緑なのを確認しながら、重複を消し・関数を小さく・条件を整理(§1)。動きは変えない
    • 見通しが良くなり、次の分離がやりやすくなる。
  3. ✂️ UI とロジックを分離する
    • 画面(DOM・表示)と、判断・計算・データ処理(ロジック)を切り離す。
    • なぜ先に? ロジックが画面に絡んだままだと、サーバーへ移せない。分離=「移せる形にする」準備であり、純粋関数化(§1)そのもの。
  4. 🖥 サーバーに置くべきロジックを、サーバーへ移す
    • サーバーに置くべき=①秘密(API キー等。ブラウザに出したら盗まれる)②クライアントに任せられない判断(正誤・権限・お金に関わる計算)。
    • 3 で分離済みだから、該当ロジックをまるごと移設できる。ブラウザは「お願いする側」に変わる。
  5. 🧷 サーバーのコードを TypeScript 化し、build / lint / CI を効かせる
    • サーバーは壊れると全員に影響する“正本”。だから型・自動整形・静的チェック・CI で固める(§3)。
    • 試作の緩さを、ここでプロダクト品質へ引き上げる。
  6. 🗄 ユーザーごとにデータを保存できるようにする
    • サーバー+DB+ログイン(認証)を入れ、データに持ち主(user_idを持たせる。
    • なぜここ? サーバー(4・5)と認証が無いと、「誰のデータか」を安全に保てない(ブラウザだけでは守れない)。
  7. 🛡💳 ここで初めて「ユーザーごとの分離」と「課金」が考えられる
    • 分離:他人のデータを見られない・触れない(権限をサーバー側で強制。例:DB の行レベルセキュリティ=RLS)。
    • 課金/使用量制限:誰が・どれだけ使ったかをサーバーで数えるから成立する。
    • つまり分離も課金も、6 までの土台(サーバー+ per-user データ+認証)が前提。順番を飛ばすと必ず穴が空く。

🧭 この順番のキモ安全網(テスト)→ 整理 → 分離 → 移設 → 硬化 → 永続化 → 制御(分離・課金)。 前半(1〜3)はリファクタリングそのもの、後半(4〜7)はその上にプロダクトの背骨(サーバーで「鍵・データ・お金」を守る)を積む流れ。作り直し(rewrite)ではなく、動かしながら段階的に——が、いちばん失敗しにくい道です。