vibe coding は、最初は速い。
意図を投げれば動くコードが返ってくる。ハッピーパスはすぐ通る。主要な機能もそれなりに動く。週末に思いついたアイデアが、その晩のうちにデモ可能なところまで来てしまう。
しかし、そこから本番品質に近づけようとすると急に遅くなる。
体感では「9 割できているのに、最後の 1 割で同じ時間がもう一度かかる」、ひどいときには「半分の時間で 9 割まで来たのに、残りの 1 割に倍以上かかる」。 vibe coding を経験した人なら、誰でもこの非対称性に覚えがあるはずだ。
この現象を、簡単な確率モデルで書いてみた。すると、構造として面白いインサイトが得られた。前半が速いほど、後半の遅さは際立つ。これは構造の問題として言い換えられる。
ついでに白状しておくと、こんなことを書きたくなったのは、最近カントの『道徳形而上学の基礎づけ』を読んでいたからだ。形而上学観がどこに反映されているかは、あとでわかる。
非理想点の集合#
システムには、本来修正されるべき「非理想点」が有限個あると仮定する。なお「非理想点」というのは僕の造語である。
$$ D = \{d_1, d_2, \dots, d_n\}. $$
冒頭で予告した形而上学的なところは、まさにここである。実物を見たこともない $D$ を、いきなり有限集合として書き下してしまっている。そのあたりはまあ、目をつぶる。
ここで $d_i$ は、狭義のバグだけではない。
- 仕様と違う挙動
- UI の違和感
- ボタン位置の悪さ
- エラーハンドリング不足
- レイテンシ
- 文言の不自然さ
- 運用上の不便さ
などを含む。つまり $D$ は、理想状態からのズレの集合である。
システムを試すことを「試行」とみなす#
システムを 1 回試すことを、1 回の試行とみなす。 vibe coding の文脈で言えば、生成されたコードを動かしてみる、デプロイしてみる、ユーザーに触ってもらう、その一回一回が試行である。各試行では、ある非理想点 $d_i$ に遭遇するかもしれない。
まず単純化して、各試行で $D$ のうちひとつに等確率で遭遇するとする:
$$ P(d_i \text{ に遭遇する}) = \frac{1}{n}. $$
これはかなり粗いモデルだが、まずは本質を見るには十分である。
未発見の非理想点#
時点 $t$ で、すでに発見済みの非理想点集合を $C_t \subseteq D$ とする。未発見集合は
$$ U_t = D \setminus C_t, $$
その個数を $|U_t| = m$ とする。
次に新しい非理想点を見つける確率#
1 回の試行で、新しい非理想点に遭遇する確率は
$$ P(\text{新しい非理想点に遭遇}) = \frac{m}{n} $$
である。全体 $n$ 個のうち、未発見が $m$ 個あるからだ。
次の発見までの待ち時間#
未発見が $m$ 個ある状態で、次に新しい非理想点を見つけるまでの試行回数を $X_m$ とする。各試行で新しい非理想点に当たる確率は
$$ p_m = \frac{m}{n} $$
である。各試行は独立で、当たる確率も毎回 $p_m$ だから、初めて当たるまでの試行回数 $X_m$ は幾何分布に従う。すなわち、
$$ P(X_m = k) = (1 - p_m)^{k-1} \cdot p_m = \left(1 - \frac{m}{n}\right)^{k-1} \cdot \frac{m}{n}, \quad k = 1, 2, 3, \dots $$
期待値は
$$ \begin{aligned} E[X_m] &= \sum_{k=1}^{\infty} k \cdot (1 - p_m)^{k-1} p_m \\ &= \frac{1}{p_m} \\ &= \frac{n}{m}. \end{aligned} $$
全部見つけるまでの期待試行回数#
最初は未発見が $n$ 個。そこから $n-1, n-2, \dots, 1$ と減っていく。したがって、全部見つけるまでの期待試行回数 $E[T_n]$ は
$$ \begin{aligned} E[T_n] &= \sum_{m=1}^{n} E[X_m] \\ &= \sum_{m=1}^{n} \frac{n}{m} \\ &= n \sum_{m=1}^{n} \frac{1}{m}. \end{aligned} $$
つまり
$$ E[T_n] = n H_n, $$
ここで $H_n = \sum_{m=1}^{n} \frac{1}{m}$ は調和数である。近似すると、 $H_n \approx \log n + \gamma$ なので、
$$ E[T_n] \approx n \log n + \gamma n. $$
つまり、 $n$ 個ある非理想点を全部見つけるまでに、平均して $n \log n$ 程度の試行が必要になる。
後半が遅くなる理由#
非理想点が $n$ 個あるなら、単純に $n$ 回試せば全部見つかるわけではない。期待値は $n \log n$ オーダーになる。これは、発見済みのものに何度も遭遇するからである。
未発見が $m$ 個のとき、次の発見までの期待試行回数は $\frac{n}{m}$ である。例えば $n=100$ とすると、
| 未発見数 $m$ | 次の発見までの期待試行回数 |
|---|---|
| 100 | 1 |
| 50 | 2 |
| 10 | 10 |
| 5 | 20 |
| 1 | 100 |
最後の 1 個は、平均して 100 回試さないと見つからない。最後の 1 つが重いという感覚は、こうして並べてみると、まあそういうものなのだろう、と納得できる。
vibe coding がこの現象を際立たせる理由#
ここまでの話は、ソフトウェア開発全般に当てはまる。それでも vibe coding でこの非対称性が体感的に強く出るのには、理由がある。
vibe coding は、前半の生産性を桁違いに上げる。意図を投げれば動くコードが返ってくる。未発見が多いうちは、試せばたいてい新しい非理想点に当たり、最初の数試行で次々と潰れていく。
ここまでは速い。
ここで、非理想点をユーザーが踏みうるルートのように見立ててみる。修正済みのものは、もう「ふつうに動く」だけのルートだ。すると、未発見が減るにつれて、システムを試してもすでに直したルートばかりを通ることになる。残った未発見は少ないから、ランダムに選んでも辿り着くのは、直し終えた理想点ばかりだ。
ここで vibe coding ならではの事情が効いてくる。生成されたコードは、書いた本人ですら細部を把握しきれていないことが多い。だから自分が踏んでいない経路は、人間のレビューではショートカットできない。残った非理想点に出会うには、ひたすら試行を増やすしかない。
しかも、前半が速いことそのものが、後半の遅さの感じ方を増幅する。同じ「未発見が 1 個残った状態」でも、そこに至るまでが 1 時間なら、最後の 1 個に 100 試行かかることが致命的に遅く感じられる。前半の速度は、後半の遅さの感覚的な分母になる。
要するに、 vibe coding はこの構造的な遅さを解消するわけではない。解消するどころか、前半の急加速によって後半の遅さを露わにする。
まとめ#
本番化とは、既知のタスクを順番に消化する作業ではない。未発見の非理想点に確率的に遭遇するまで、試行を繰り返す作業だ。 vibe coding で「もう動いてるじゃん」と思ったあとに、もう直したところを何度もなぞるあの時間は、その試行回数を定義通り消化しているだけである。
ここまで来てようやく言えるのだが、これはまさにクーポンコレクター問題の構造そのものだ。 $n$ 種類のおまけを全部集めるのに $n H_n$ 回くじを引く、あの古典的な問題である。一言でいえば、
vibe coding の本番化とは、非理想点のクーポンコレクター問題である。
そして、最後が重いのは、最後だから重いのではなく、引いても引いても直し終えたルートばかりを通るから重いのである。
おわり
