数日前、JoyConfというツールを作りました。リアルタイムの観客フィードバックシステムで、話し手が話している間に、プレゼンのコーナーに絵文字のリアクションが浮かび上がって見えるようにするものです。楽しくてシンプルな発想で、かなりワクワクしていました。
ElixirとPhoenix LiveViewで作りました。これは意図的な選択です。最近は主にRubyを書いていますが、このプロジェクトはElixirとLiveViewに深く踏み込む良い口実だと感じました。新しいことを学ぶ。役に立つものを作る。二兎を追う者は一兎をも得る、です。
私は全体の設計と実装の計画を主導し、積極的にコードレビューを行い、できる限りあらゆる面で貢献しました。しかし、ElixirとLiveViewの具体的な部分については、Claudeに大きく頼りました。文法、アーキテクチャの判断、デバッグはClaudeの領域でした。なぜなら、私はそれらをまだ十分に理解できていなかったからです。ツールは動きましたし、うまく動いているように見えました。ですが、最後まで作業してコードベースを見返したとき、「Claudeが作った部分を、実際には自分はあまり理解できていない」と気づきました。できる限り丁寧にコードをレビューしましたが、知らない言語で書かれたコードをレビューすること、馴染みのないアーキテクチャを実装することは、そこまでしか理解を前に進めてくれません。それらのパーツの理解は、ほとんどClaudeの手元に残ったままだったのです。
それが認知的負債(cognitive debt)です。そしてLLMは、これを生み出すことにとても長けています。
認知的負債とは実際に何か
認知的負債は、今すぐ行われるべき考える作業を先送りしたときに積み上がります。コードそのものに関する技術的負債(手抜き、テストの省略、うまく噛み合わなかった抽象化)とは異なります。認知的負債は、行われなかった推論です。構築されなかったメンタルモデルです。理解されないまま下された判断です。
金融の負債と同じで、最初は大したことないように感じます。とにかく速く進み、物事は動いていて、出荷しています。請求書は後から来ます。自分で理由を説明できないもののデバッグが必要になったとき、理解していないシステムを拡張する必要が出たとき、実際には自分が下していない判断を説明しなければならなくなったときです。そして明確に言うと、認知的負債はLLMよりずっと前から存在していました。LLMはただ、その問題を拡大しているだけです。
LLMがこれを不気味なほど簡単にする
LLMが生成したコードは、たいてい正しいです。だからこそ危険なのです。
コードが明らかに間違っていれば見つかります。掘り下げて、何がうまくいかなかったのかを突き止め、その過程で何かを学べるでしょう。ですが、LLMの出力は通常、もっともらしい—多くの場合正しい—しかも、雰囲気チェックを通過するのに十分なだけ筋が通っています。テストを回します。通ります。そこで終わりです。動き方のメンタルモデルは構築されません。必要になるまで、そもそも必要だと感じないからです。
ここで名前をつける価値がある特定の失敗パターンがあります。理解しているものをより速く進めるためにLLMを使うのはレバレッジ(てこ)です。理解をすっ飛ばすためにLLMを使うのは負債です。短期的には、どちらも同じに見えます。どちらもコードが書かれる結果になります。前者は、それに積み上げていける理解を残します。後者は、抜け出せなくなる出力だけを残します。
そして、それは誰にでも起きます。ジュニア開発者は、疑うだけの知識がないのでLLMの出力を受け入れます。シニア開発者も受け入れます。今日はPRが100本あってコードは見た目きれいなので、大丈夫だと思い込むからです。どちらも推論のステップを飛ばします。結果として、チームの誰もその判断を擁護できない決定で満たされたコードベースができあがります。
ふたたびJoyConfへ
自分が十分に理解していないものを作ってしまったと気づいたとき、Claudeに説明文書を書いてもらいました。要約ではありません。アーキテクチャ、重要なコンセプト、なぜ特定の判断がされたのか、部品同士がどう噛み合っているのか—それらを実際に説明してもらうのです。自分が読んで学び、後でまた戻ってこられるようなものです。
それは魔法の薬ではありません。私はElixirとLiveViewについてほぼゼロから始めていたので、1つの文書で専門家になれるわけではありません。ですが、その1文書は重要なギャップを埋めてくれました。作ったコードを以前よりずっとよく理解できました。参照できるものが手元にできました。そして、コードベースが本当に自分のものになったように感じ始めました。
この経験は、コーディングのためにLLMを使うことについて考えるときの方向性を形作りました。ツール自体はちゃんと動きます。違いを生むのは、どう関わるかです。
負債を抑えるための実践的な方法
コードを受け入れる前に、説明を求める。 ただ動かすだけではダメです。LLMに「何をしたのか」「なぜそうしたのか」を説明しながら案内してもらってください。余計に1分かかるだけですが、コードが技術的には正しいのに、共有していない前提に基づいて作られているケースを驚くほど多く見つけられます。
大きな判断のために、説明文書を求める。 アーキテクチャの選択、分かりにくいパターン、しばらく付き合う必要があるものすべてに対して、LLMに平易な言葉で書き起こしてもらいましょう。リポジトリに残します。未来の自分が、今の自分に感謝するはずです。
Simon Willisonの「showboat」アプローチで、作られたものをドキュメント化する。 showboat ツールは「エージェントの成果を示し、証明する実行可能なデモ文書を作成する」ものです。(Jupyter notebookのようなものですが、markdownだけです。)LLMが、その出力を説明と文脈付きで順を追って案内します。コードが「何をするか」だけでなく「なぜその形で書かれたのか」まで捉えた、いきたドキュメントを作るのにとても良い方法です。優れたツールですが、あらゆるユースケースに向いているわけではありません。
デバッグのとき特に、LLMの「考え」を読む。 多くのLLMは推論プロセスを開示できます。バグで詰まったり、判断を理解しようとしていたりするとき、答える前にLLMに口に出して考えさせることは、単に答えをもらうよりも本当の理解を素早く作る方法の一つです。
テストは自分で書く。 たとえLLMに実装を書かせるとしても、テストを書くことで「自分が実際に望む振る舞い」について考えざるを得なくなります。メンタルモデルが構築されることを保証する最良の方法の1つです。もちろん、時間がかかりますし、JoyConfのようにElixir環境について十分知らないため効果的なテストが書けない場合もあります。ですが、可能なときは、運転席に居続けるためのとても良い手段です。
判断の分岐点では立ち止まる。 LLMは速い。これが売りです。ですが、速さは負債を加速させます。分かれ道にぶつかったら(アーキテクチャの選択、トレードオフ、「これにはいくつかのやり方がある」みたいな場面)一度止まって、自分で推論してください。LLMを使って考える補助にするのは構いませんが、です。
目的はLLMを減らすことではない
LLMは本当に役に立ちますし、使うのをやめるつもりはありません。目的は、思考の代わりとしてではなく、レバレッジとして使いながら、メンタル面で運転席に居続けることです。
健全なLLMワークフローと、負債を生みやすいワークフローは、外から見るとまったく同じに見えることがあります。違いが後から現れます。自分が作ったものを理解し、保守し、拡張する必要が出てきたときです。それぞれのセッションを終えるときに、「何を作ったのか」と「なぜそうしたのか」を理解できているなら、そのツールをうまく使っています。理解できていないなら、ローンを組んでいるだけです。
そして金融の負債と同じように、認知的負債は返済するよりも避けるほうがはるかに簡単です。




