前回の続きとして
他人のPRを開いたまま、手が止まっていた。差分は表示されている。追加が緑、削除が赤。目は動いている。読んではいない。前回の記事のことを、ずっと考えていた。
「方法を学べ」と書いた。方法の知識、つまり操作・分解・判断の3層が課題認識の範囲を規定する。だから方法を極めることには価値がある、という話だった。書いた。書き終えた。達成感があってもよかった。なかった。何かが足りないという感覚だけが残った。
学んだ。で、どうするのか。
手元にハンマーもドライバーもレンチもある。どれも使える。どれを使うか決められないまま、工具箱を眺めている。PRの差分を眺めているのと、たぶん同じだった。見ているだけで、何も始まらない。
「もっと調べろ」と誰かが言う。「比較表を作れ」「ベンチマークを取れ」「事例を集めろ」。正しい情報があれば正しく選べる。エンジニアの世界では、それが常識になっている。合理的に聞こえる。聞こえるが、その常識こそが、自分の手を止めていた気がする。
先に補足しておきます。前回「複数の方法を知れ」と書きました。今回は「1つを選べ」と書きます。矛盾しているように見えますが、矛盾していません。複数知ることと、同時に複数やることは違います。順番に深める話です。まず学び、次に選ぶ。同時並行で表面をなぞるのとは違います。
今日はその話を書きます。選ぶことについて。書けるかどうかは、正直わかりません。
「選ぶ」とは何か
前回、「方法」を操作・分解・判断の3層で定義しました。今回の「選ぶ」にも構造があります。書きながら整理して、3つに分けました。また3つです。何でも3つに分けたがる習性があるのかもしれません。
1つ目は評価です。選択肢を並べ、それぞれの特性を理解し、現在の文脈でどれが最も適切かを見極めます。前回の「判断」の知識がここで効きます。判断の語彙がなければ、評価の軸が立ちません。
2つ目は宣言です。「私はAを選ぶ。理由はこれだ」と、他者に伝えます。選択を頭の中に留めておくのは、選んでいないのと同じです。宣言によって選択は社会的な事実になります。
3つ目は撤退判断です。選んだ後、「いつ撤退するか」の基準をあらかじめ持っておくこと。撤退ラインのない選択は、ただの賭けです。「3ヶ月やって成果が出なければ見直す」「この指標がこの閾値を下回ったら切り替える」。選ぶ前に、選び直す条件を決めておきます。
この3つは独立しているように見えて、相互に強化し合います。評価が宣言を支え、宣言が撤退判断の起点になり、撤退判断の経験が次の評価を鋭くします。前回の3層が「操作→分解→判断」という依存関係を持っていたように、「選ぶ」の3要素も評価→宣言→撤退という順序があります。評価せずに宣言すれば蛮勇ですし、宣言せずに撤退判断だけ持っていても意味がありません。
と書いて、立ち止まります。この3要素を整理できたのは、失敗した後でした。当時はこんな構造は見えていませんでした。評価だけして宣言しませんでした。宣言したのに撤退ラインを決めていませんでした。3つが揃ったのは、3つとも欠けた経験をした後でした。たぶん、構造は事後的にしか見えません。それでも書きます。事前に知っていれば、失敗の質が変わるかもしれないからです。
と書いて、気づきました。この3要素、評価・宣言・撤退を並べた瞬間、既視感があった。診断して、方針を立てて、一貫した行動をとる。これは戦略の構造そのものです。そして、私がやっていた(つもりの)技術選定が、戦略ですらなかったことに気づきました。「売上を2倍にする」は戦略ではありません。目標の列挙にすぎない。同様に、「もっと調べてから選ぶ」は選択ではなかった。私がやっていたのは目標の列挙、つまり比較表を精緻にすることであって、「何が本当の困りごとか」を直視する診断ではなかった。
この定義を前提に、それぞれの要素で何が起きるかを見ていきます。
知識が増えると、動けなくなる
方法を学びました。ハンマー、ドライバー、レンチ。全部知っています。全部使えます。スクラム、リーン、システム思考。どれも説明できます。
では、目の前の問題に、どれを使うか。
「全部知っている」ことと「適切に使える」ことは、まったく別の能力です。
選択肢が増えると、むしろ動けなくなることがあります。どれでも解けそうに見える。どれが最適かわからない。「もう少し考えてから」と言い訳する。「状況を見て判断しよう」と先延ばしする。結局、何も選ばないまま時間だけが過ぎます。学んだ意味がない。
選択肢が多すぎると、人は選べなくなる。6種類のジャムと24種類のジャムでは、6種類の方が売れるという話があります。24種類を前にすると、人は「もう少し比べてから」と棚の前で立ち尽くす。私の工具箱はジャム24種類の棚でした。
あるとき、自分の行動パターンに気づきました。人は2つのタイプに分かれます。あらゆる選択肢を検討し最善を求める人と、「十分に良い」選択肢が見つかった時点で決断する人。そして、直感に反する事実がある。最善を求める人の方が、選択の結果に満足していません。「もっと良い選択があったのでは」という後悔が消えない。「十分に良い」で決断する人の方が、選んだ後の満足度が高い。
私は完全に前者でした。データベースの選定です。MySQL、PostgreSQL、CockroachDB、TiDB、Vitess。ベンチマークを比較し、ブログ記事に目を通し、GitHub Issueまで追いました。2週間かけて比較表を作りました。完成度は高かった。しかし、2週間経っても選べませんでした。比較すればするほど、各選択肢の長所と短所が均衡していく。どれも「ある条件下では最善」であり、「別の条件下では最善ではない」。完璧な選択肢は存在しませんでした。当たり前です。存在するなら、他の選択肢は淘汰されています。
振り返って気づきます。比較表を作っている間、私は「選んでいる」つもりでした。実際には「選ばない理由を積み上げている」だけでした。Aの弱点を見つけてはBに目を移し、Bの弱点を見つけてはCに逃げる。情報収集は選択の準備ではなく、選択の回避でした。「もっと調べてから」は、いつの間にか「調べ続けることで選ばずに済ませる」にすり替わっていました。
「十分に良い」で決断することは妥協ではなく、構造的に合理的な戦略です。選択肢が一定数を超えると、追加の調査で得られる情報の質は逓減します。一方で、調査にかけた時間のコストは線形に増加します。どこかで交差する。その交差点を過ぎたら、「もう少し調べれば」は投資ではなく浪費です。
この経験から、私は技術選定のルールを1つ決めました。「3日で決める。3日で決まらなければ、その時点で最も情報が揃っている選択肢にする」。3日は恣意的な数字です。しかし、期限があるだけで、最善を求め続ける衝動が止まります。そして正直に書くと、3日で選んだ結果が、2週間かけて選んだ結果と比べて劣っていたことは、ほとんどありません。このルールを決めた翌週、新しいミドルウェアの選定に5日かけました。ルールを作った人間がルールを破る。よくある話です。ちなみに、5日かけた結果は、3日目の時点で候補に上がっていたものと同じでした。
知識が増えるほど、選択肢が増えます。選択肢が増えるほど、選べなくなる。皮肉な構造です。これは個人の性格の問題ではなく、選択肢の数が一定の閾値を超えた時点で構造的に発生します。つまり、学べば学ぶほどハマる罠です。前回「方法を学べ」と書きました。学んだ結果、ここに来る。知っていれば避けられる罠ではありません。知っているからこそハマる罠です。
私は何度もこれにハマりました。
選ぶとは、捨てることだ
選ぶとは、他を捨てることです。
Aを選ぶとは、BとCを選ばないことです。BとCで得られたかもしれない結果を、手放すことです。
これが怖い。
あるプロジェクトで、痛い目にあいました。大規模なリファクタリングを進めながら、同時に新機能もリリースしようとしました。リファクタリングのためにインターフェースを変更したら、新機能のコードと競合しました。新機能のためにAPIを追加したら、リファクタリングの方針と矛盾しました。両方やろうとした瞬間、どちらも中途半端になりました。結局、リリース日を2回延期しました。
プロジェクトの振り返りで、テックリードに言われました。「なぜ両方同時にいけると思った?」。返す言葉がありませんでした。「リファクタリングを先にやるなら、新機能は止めろ。新機能を優先するなら、リファクタリングは次のスプリントに回せ。両方欲しがるな」。
身をもって学んだ教訓です。選ばないことは、両方を失うことです。
もう1つ、技術選定で間違えた話を書きます。
あるプロジェクトで、データストアの選定を任されました。要件は明確でした。ユーザーのアクティビティログを保存し、リアルタイムで集計します。書き込みが多く、読み取りは集計クエリが中心です。私はRDBMSを選びました。PostgreSQLです。理由はありました。チームがPostgreSQLに慣れています。運用ノウハウがあります。JSONBカラムで柔軟なスキーマにも対応できます。分析しました。分析結果は正しかった。
しかし、選んだ後に前提が変わりました。
リリース3ヶ月後、ユーザー数が想定の8倍になりました。書き込みが秒間3,000件を超えました。PostgreSQLのWAL(書き込み先行ログ)がボトルネックになり、書き込みレイテンシが跳ね上がりました。集計クエリは30秒以上かかるようになりました。パーティショニングで凌ぎましたが、根本解決にはなりませんでした。
同僚が言いました。「ClickHouseなら、この規模でも問題なく捌けますよ」。調べました。その通りでした。ClickHouseは書き込みをバッチで処理し、列指向ストレージで集計クエリを桁違いに速く返します。最初からClickHouseを選んでいれば、この3ヶ月の苦労はありませんでした。
と書いて、立ち止まります。分析は正しかったのです。「チームがPostgreSQLに慣れている」「運用ノウハウがある」。これは選定時の重要な判断基準でした。問題は分析の正確さではなく、前提の変化です。ユーザー数が8倍になるとは、誰も予測していませんでした。予測できなかった以上、どれだけ正確な分析も、この変化には対応できません。分析が正しかったことと、選択が正しかったことは、別の話です。
分析は過去と現在のデータに基づきます。選択は未来に賭ける行為です。未来の前提が変われば、正しい分析に基づく選択が間違いになります。これが選択の本質的な難しさです。前回、方法の知識が課題認識を変えると書きました。しかし、いくら知識があっても、未来の前提変化は予測できません。だから、先に定義した「撤退判断」が要ります。あのとき私に足りなかったのは、「書き込みが秒間N件を超えたら、データストアを再選定する」という撤退ラインでした。
選べば他を失います。正しく分析しても前提が変われば裏目に出ます。
だから人は、選びません。「状況を見て判断する」と言います。「柔軟に対応する」と言います。「両方のいいとこ取りをする」と言います。
全部、選んでいません。
ここで反論が来ます。「90:10で配分すればいいじゃないか」と。Aに90%の時間を使い、Bにも10%残しておく。保険です。賢い選択に見えます。
しかし、90:10は機能しない、と断言する前に、留保が1つあります。
プロトタイプフェーズでは、80:20くらいのリソース配分で複数の選択肢を探索すべき場面もあります。選択肢を1つに絞る前に、最低限の検証をする期間は必要です。「100:0で選べ」が常に正しいわけではありません。選ぶ前の探索と、選んだ後の集中は、フェーズが違います。問題は、探索フェーズを永遠に続けることです。「まだ探索中です」と言い続けて、いつまでも選ばない。探索と先延ばしの区別がつかなくなります。
探索フェーズを過ぎた後で、90:10が機能しない理由はいくつかあります。
10%の保険があると、90%に全力が出ません。「うまくいかなければBがある」という逃げ道が、Aへの集中を妨げます。壁にぶつかったとき、「Bに切り替えるか」という判断が頭をよぎります。その判断にエネルギーを使います。本来Aに向けるべきエネルギーが漏れます。
10%では何も得られません。週に4時間だけ量子コンピューティングを学んでも、表面をなぞるだけで終わります。本当に使えるようになるには、没入が必要です。10%の没入は矛盾です。
そして、これが一番重要ですが、90:10は「いつ切り替えるか」の判断基準を生みません。
100:0で選んでいれば、「Aがダメだったらどうするか」を事前に考えます。撤退ラインを決めます。「3ヶ月やって成果が出なければ、Bに完全切り替え」と決められます。
しかし90:10だと、「Aがうまくいっていないな、でもまだBも並行しているし」と曖昧なまま続きます。Aを諦めるタイミングが定まりません。Bに本腰を入れるタイミングも定まりません。ずるずると両方を中途半端に続けて、どちらも成果が出ないまま半年が過ぎます。
私はこれを何度もやりました。「Rustも書くけどGoも捨てない」で1年を費やしたことがあります。結果、どちらも「まあ書ける」レベルで止まりました。「Rustを極める」と決めた後の半年で、1年分以上の成長がありました。最初からRustに100:0で振っていれば、1年早く今の状態になれました。
と、書きました。しかし、立ち止まります。
GoとRustを並行した1年は、本当に無駄だったのでしょうか。Goのsync.Mutexを毎日書いていたから、RustのArc<Mutex<T>>の意味が直感でわかった面はなかったか。Goの並行処理で実際にデータ競合を踏んだから、Rustの所有権が「なぜ必要か」を身体で理解できたのではないか。
答えはわかりません。「100:0が正しかった」と言い切れる根拠は、実は持っていません。ただ、選ばずに過ごした1年に後悔の色が濃いのは事実です。たぶん、100:0の方がよかった。たぶん。
100:0か0:100しかない、とは言いません。しかし、90:10は「両方選んでいる」のではなく「どちらも選んでいない」ことが多い。90:10の別名が「ハイブリッド」です。提案資料に「ハイブリッドアプローチ」と書くと、なぜか承認されやすい。AとBのいいとこ取り。両方の利点を享受できる。承認する側も「バランスの取れた判断だ」と言えます。全員が安心します。でも実際は、どちらの利点も中途半端にしか得られないことが多い。両方を選んだのではありません。どちらも選ばなかったのです。
この「どちらも選ばない」構造は、個人だけの話ではありません。組織ではさらに深刻です。個人が90:10でリソースを分散させるように、組織は会議体で議題を分散させます。月曜は事業の話をします。水曜は技術の話をします。金曜は組織の話をします。きれいに分けています。効率的に見えます。でも、境界で情報が消えます。「この技術的制約があるから、この事業戦略は実行不可能だ」という前提。「機能を絞れば3ヶ月で出せる」という代替案。これは、どの会議の議題にもなりません。分けた瞬間に、最も大事な情報が抜け落ちるのです。実際に経験しました。開発チーム全員が「この設計では半年後に破綻する」と知っていた情報が、事業側に届いたのは破綻した後でした。技術の会議で話し、事業の会議では話さなかった。それだけのことです。
私もこれを繰り返してきました。「AもBも大事だから、両方やる」と言い訳しました。結果、どちらも中途半端になりました。両方とも「やった」とは言えない状態で終わりました。
選ばないことで、責任を回避しています。「Aを選んだから失敗した」と言われたくない。だから選びません。結果、何も決まりません。何も進みません。
選択には根拠がいる
「なんとなくこれ」は選択ではありません。
選択には根拠がいります。「なぜAなのか」「なぜBではないのか」を言語化できなければ、選んだことになりません。
根拠を言語化するためには、各選択肢の特性を理解している必要があります。Aの強みと弱み、Bの強みと弱み、それぞれがどんな状況で効果を発揮するか。だから「方法を学べ」が先に来ます。学んでいなければ、根拠のある選択はできません。
しかし、学んだだけでは選べません。学ぶことと選ぶことの間には、別の壁があります。
その壁の正体に気づいたのは、自分のKubernetes導入を振り返ったときでした。冒頭の3要素に照らすと、私の「評価」は根本から間違っていました。第1回で書いた話です。Kubernetesを導入した。技術ブログも書いた。しかし、デプロイ頻度は週1回のまま変わらなかった。スケーリングが必要な負荷もなかった。
あのとき、私はKubernetesの「機能」を見ていました。コンテナオーケストレーション。オートスケーリング。自己修復。素晴らしい機能です。機能を評価し、機能に納得し、機能で選びました。しかし、導入後に何も変わりませんでした。機能は正しかった。選定プロセスに穴はなかった。では、何が間違っていたのか。
「何ができるか」で選んでいた。「何を解きたいか」で選んでいなかった。
技術選定で私たちが見ているのは、大抵「機能」です。この技術には何ができるか。どんな特徴があるか。ベンチマークでどれだけ速いか。比較表の列は機能で埋まります。しかし、機能は技術の側の話です。私たちの側の話、つまり目の前にどんな困りごとがあって、その困りごとを片付けるために何が必要かは、比較表のどこにもありません。
私がKubernetesを導入したとき、目の前に「コンテナオーケストレーションで解くべき困りごと」は、実はありませんでした。デプロイ頻度は週1回で事足りていた。スケーリングの必要もなかった。では、なぜ導入したのか。正直に振り返ると、困りごとは技術的なものではありませんでした。「Kubernetes導入」をやった人間として転職市場に出たかった。そう書くと卑小に聞こえます。聞こえますが、エンジニアの技術選定の何割かは、この卑小な動機で動いています。私だけではないはずです。
と書いて、立ち止まります。これを事後的に分析するのは簡単です。「あのときの私はキャリアの問題を技術選定にすり替えていた」と、今ならそう言えます。しかし、選定のその瞬間にそれが見えていたか。見えていませんでした。「技術的に必要だから導入する」と本気で信じていました。人は自分の動機を誤認します。特に、「すごい技術を使いたい」という欲求を、「この技術が課題を解決する」という合理性にすり替えます。当時の私に「それ、技術的に必要ないですよね」と指摘しても、否定したでしょう。機能の評価は正しかったのですから。
機能の評価が正しいことと、その機能が必要であることは、別の話です。
振り返って、構造が見えました。人はプロダクトを「買う」のではない。困りごとを片付けるために選ぶ。私はKubernetesを「買った」だけでした。困りごとが不在のまま、機能だけを見て導入した。だから何も変わらなかった。
この経験から、私は技術選定の問いを変えました。「この技術は何ができるか」ではなく、「我々は今、何に困っていて、それを片付けるために何が必要か」。問いを変えた瞬間、比較表の意味が変わりました。PostgreSQLとClickHouseの機能比較ではなく、「秒間3,000件の書き込みとリアルタイム集計という困りごとを、どちらが片付けられるか」という評価になります。機能の多さは関係ありません。目の前の困りごとを片付けられるかどうかだけが基準です。
しかし、先ほど書いた通り、困りごとの正体を見誤ります。「技術的に必要だ」と思い込んでいるとき、本当の困りごとは別の場所にあるかもしれません。だから、冒頭で書いた「宣言」が要ります。「私たちはこの困りごとを解くために、この技術を選ぶ」と書き出す。書き出すことで、「本当にそれが困りごとか?」と問い直す余地が生まれます。書かなければ、動機の誤認に気づかないまま走り続ける。たぶん。
もう1つ重要なのは、技術が「不要になる」瞬間の話です。技術が棚に戻されるのは、困りごとをより上手く片付ける代替が現れたとき、あるいは困りごとそのものが消えたときです。jQueryが使われなくなったのは、ブラウザ間の差異吸収という困りごとが、ブラウザの標準化によって消えたからです。jQueryの機能が劣化したのではありません。解くべき問題がなくなった。私たちが技術を「捨てる」とき(これは次回の話になりますが)、それは技術が悪くなったからではなく、困りごとが変わったからです。
選択の根拠は、覚悟だけでは足りません。「この技術で何を解くのか」が言語化できていなければ、覚悟は空回りします。覚悟の前に、困りごとの特定がいる。困りごとが明確なら、選択は半分終わっています。
困りごとが明確になり、覚悟もある。それでも、選ぶためにはもう1つ必要な力があります。選んだ根拠を、他者に伝える力です。
根拠を言語化する。選択を宣言する。これは「書く」能力を前提にしています。
根拠を書く、と簡単に言いました。しかし、書くフォーマットがないと、人は書きません。書こうと思っても、何をどの粒度で書けばいいかわからない。私がそうでした。
ADR(Architecture Decision Record、設計判断の記録)というフォーマットを知ったとき、「これだ」と思いました。設計判断こそがシステムの寿命を決めます。その判断を構造化して残す仕組みが、驚くほどシンプルだったのです。
コンテキスト(何が問題か)、決定(何を選んだか)、結果(何が起きるか)。この3つを短い文書で残します。テンプレートは以下の通りです。
# ADR-XXXX: [タイトル] ## ステータス 提案 / 承認 / 廃止 ## コンテキスト [何が問題か。どんな状況か。どんな制約があるか] ## 決定 [何を選んだか。なぜ選んだか] ## 結果 [この決定によって何が起きるか。良い影響と悪い影響]
たったこれだけです。しかし、この「これだけ」が、私の技術選定を根本から変えました。
ADRを導入する前、技術選定の根拠はさまざまな場所に散らばっていました。Slackの会話ログ。PRの説明文。コードのコメント。Design Doc。誰かの頭の中。どれも根拠を残しているつもりでした。しかし、どれも十分に機能していませんでした。
コードのコメントは、一見すると最も近い場所に根拠が残ります。// CockroachDBではなくPostgreSQLを採用。チームの習熟度を優先と書けます。しかし、リファクタリングでコードが消えれば、コメントも消えます。そもそも、コメントに書ける情報量では「なぜチームの習熟度を優先したのか」「他にどんな選択肢があったのか」「どんな条件が変わったら再検討すべきか」は伝わりません。
PRの説明文には、もう少し詳しく書けます。しかし、技術選定の判断は複数のPRにまたがります。「データストアをPostgreSQLに決めた」PRと「スキーマを設計した」PRと「マイグレーションを実装した」PR。どのPRに選定の根拠が書いてあるか、半年後に探せるでしょうか。PRは「何を変えたか」を記録するものであって、「なぜそう決めたか」を記録するものではありません。
Design Docは最も構造化された選択肢です。しかし、私の経験では、Design Docは「どう作るか」に重心が寄り、「なぜこの方法を選んだか」は1段落で済まされがちです。さらに、Design Docは設計が変わるたびに更新されます。更新されること自体は良いのですが、「当時の判断」が上書きされてしまう。ADRはappend-onlyです。過去の判断は変更せず、新しい判断を追記します。だから、「あのとき何を考えていたか」が残ります。
Slackの会話ログは最も生々しい議論が残ります。しかし、膨大すぎて検索できません。半年後に「なぜこの技術を選んだのか」と聞かれたとき、誰も答えられなかった。頭の中の記憶は、半年で変質します。「たしかPostgreSQLの方がパフォーマンスが良かったから」。本当にそうだったか? 当時のスレッドを掘り返すと、実際の理由は「チームにPostgreSQLの経験者が多かったから」でした。記憶は、事後的に合理化されます。
ADRを書くようになって変わったことが2つあります。1つは、選定時の思考が明確になったこと。書こうとすると、「なんとなく良さそう」が通用しません。コンテキストを書く段階で、「そもそも何の問題を解こうとしているのか」が曖昧だったことに気づきます。もう1つは、撤退判断が楽になったこと。冒頭で定義した3要素の「撤退判断」を思い出してください。ADRに「この条件が変わったら再検討する」と書いておけば、半年後に状況が変わったとき、「当時の前提はこうだった。今は違う。だから選び直す」と言えます。感情ではなく、記録に基づいて判断できます。
ただし、ADRにも限界はあります。書いた人間の解像度以上のことは書けません。データストアの選定でClickHouseの存在を知らなかった私が、いくら丁寧にADRを書いても、「ClickHouseという選択肢を検討しなかった」という事実は記録されません。知らないものは、検討できません。ADRは「選んだ理由」を構造化しますが、「選ばなかった理由」のうち「そもそも知らなかった」ものは記録から漏れます。これが前回書いた「方法の解像度が課題の解像度を決める」の、選択における現れです。
ここまでエンジニアの文脈で書いてきましたが、「意思決定の根拠を構造化して残す」ことの価値は、エンジニアリングに限りません。プロダクトマネージャーの機能優先度の判断。デザイナーのUI選定。マーケティングのチャネル選択。営業の価格戦略。どの領域でも、「なぜこの選択をしたか」は半年後に消えます。ADRのフォーマットをそのまま使う必要はありません。先ほどのテンプレートのコンテキスト・決定・結果の3項目を、チームのWikiやNotionに1ページ書くだけで十分です。
非エンジニアの方にも、意思決定の記録を書くことを勧めます。
ここまで、根拠を「書く」ことの重要性を述べてきました。ADRにしても宣言にしても、前提になっているのは「書ける」ことです。書く能力は自然には身につきません。これもまた、「学ぶべき方法」の1つです。
根拠を言語化できるようになりました。では、その根拠は何に基づくべきか。
選択の基準は「課題」に帰る
ここまで、「選ぶとは捨てること」「根拠を言語化すること」を書いてきました。では、言語化された根拠は何に基づくべきか。
課題です。
「この課題を解くために、この手段が最適だ」。これが選択の根拠になります。
ここで、話が一周します。
課題が明確でなければ、手段は選べません。手段を学び、その上で課題に立ち返る。課題が、選択の基準を与えます。
しかし、前回書いた通り、方法の解像度が課題の解像度を決めます。方法を知らなければ、課題を正しく認識できません。だから方法を学ぶ。
循環しています。
課題があるから方法を選ぶ。方法を知るから課題が見える。どちらが先でもありません。両方が必要です。鶏と卵のように見えますが、実際にはスパイラルです。課題を見て方法を学び、方法を学んで課題の解像度が上がり、解像度が上がった課題に対して方法を選ぶ。この繰り返しです。
「で、どこから始めるんですか」という問いが残ります。
厳密には始点がありません。でも、スパイラルに入る入口はあります。実際には人は何かから始めている。始めなければ動きません。
私の経験では、始点は「違和感」です。
何かがおかしい。何かがうまくいっていない。でも、何がおかしいかわからない。この漠然とした違和感が、スパイラルの入口になります。
違和感を感じたら、まず「似たような状況で使われている方法」を探します。うまくいっている人は何をやっているのか。うまくいっている組織は何を採用しているのか。そこに方法のヒントがあります。
方法を1つ学ぶ。すると、違和感が少しだけ言語化できます。「あ、これは〇〇の問題かもしれない」と言えるようになる。課題の解像度が上がります。
解像度が上がると、「この方法では足りない」か「この方法で解ける」かが見えます。足りなければ、別の方法を学ぶ。解けそうなら、その方法を選ぶ。
スパイラルの始点は、理論ではなく、違和感という身体感覚です。頭で考えて「どこから始めよう」と悩んでいても動けません。「なんかおかしい」という感覚に素直に従う方が、スパイラルは回り始めます。
このスパイラルを、私が経験した具体例で図示します。「選択」がスパイラルを回す、という話です。
認証基盤を設計したときのことです。最初の違和感は「ユーザー管理が散らばっている」でした。サービスごとに独自のログイン機構があります。パスワードポリシーもバラバラです。方法を探しました。OAuth2/OIDCを学びました。「認証を一箇所に集約すべきだ」という課題に変わりました。解像度が上がりました。
次に、「集約する」方法を選ぶ段階で止まりました。自前で実装するか、OSSの認証サーバーを使うか、SaaSに任せるか。3日間RFCを読んで、自前で作ることの非合理性を理解しました。作れます。作れますが、これをプロダクション品質で検証し続けるのは、私たちの仕事ではありません。OSSのOry Hydraを選びました。「認証を集約する」が「IdPの運用を最小コストで維持する」という課題に変わりました。さらに解像度が上がりました。
このスパイラルで重要だったのは、「選択によって課題が変わった」ことです。自前実装を選んでいたら、課題は「OAuthプロトコルの実装」になっていたでしょう。OSSを選んだことで、課題は「IdPの運用」に変わりました。選択が、次の課題を規定します。前回書いた「方法の解像度が課題の解像度を決める」の応用です。選択の解像度が、次の課題の解像度を決めます。
もう1つ、スパイラルの例を書きます。こちらは選択を間違えた話です。
最初の違和感は「アラートが多すぎる」でした。1日に200件以上のアラートが飛びます。ほとんどがノイズです。方法を探しました。アラートの閾値を調整しました。「閾値が不適切」が課題だと思いました。閾値を上げました。アラートは減りました。しかし、本当に対応すべきアラートも減りました。障害を見逃しました。
次の違和感。「閾値の調整だけでは限界がある」。SLO(サービスの品質目標)ベースの監視を学びました。課題が変わりました。「アラートの閾値をいくつにするか」から「ユーザーに影響があるかどうか」に。エラーバジェット(許容されるエラーの残量)が消費されたときだけアラートを出す設計に変えました。アラートは1日10件以下になりました。すべてがアクション可能でした。
ここでも選択がスパイラルを回しました。「閾値調整」を選び続けていたら、永遠に閾値をいじっていたでしょう。「SLOベース」を選んだことで、課題のレイヤーが変わりました。インフラの指標を見ていた目が、ユーザー体験を見る目に変わりました。前回書いた「課題がどのレイヤーにあるか見誤ると、いくら努力しても解決しない」。まさにあの構造です。閾値調整は「表示のレイヤー」で頑張っていたのと同じでした。SLOは「計測のレイヤー」を変える選択でした。
2つのスパイラルに共通しているのは、どの例でも「この方法を選ぶ」という明確な意思決定があったことです。Ory Hydraを選びました。SLOベースの監視を選びました。スパイラルは、選択によって回ります。では、選択を確定させるために何が必要でしょうか。
選んだら、宣言する
選んだら、宣言します。
「私はAを選ぶ。理由はこれだ」と、声に出します。文章に書きます。チームに共有します。
宣言することで、選択が確定します。後から「やっぱりBだった」と言い訳できなくなります。
これが怖い。だから人は宣言しません。「まだ検討中です」と言います。「もう少し情報を集めてから」と言います。「関係者と調整してから」と言います。
いつまでも検討中のまま、時間だけが過ぎます。
私にも覚えがあります。決められないまま、選択肢を並べて眺めていました。「どれがいいかな」と考え続けていました。Notionに選択肢を並べて、比較表を作って、色分けまでして、それを眺めていました。最終的に6列38行になりました。比較表の完成度だけが上がっていきました。あの時間、胃のあたりに鈍い重さがありました。選ぶ怖さが身体に溜まっていました。考えている間は、失敗しません。でも、成功もしません。前に進みません。
宣言しないことは、一種の保険です。「まだ決めていないから、失敗してもしょうがない」と言えます。でも、その保険のコストは高い。時間です。機会です。信頼です。
ただし、宣言の怖さは「しないこと」だけではありません。
あるとき、「この設計でいく」と宣言しました。根拠はありました。分析もしました。しかし、前提が間違っていました。チームは私の宣言に従って2週間動きました。途中で「これ、おかしいかもしれない」と気づきました。ですが、自分が宣言した手前、撤回しにくかった。「やっぱり違った」と言えば、2週間の作業が無駄になります。私の判断力が疑われます。結局、言い出すまでにさらに1週間かかりました。
宣言は確定力を持ちます。だからこそ、間違った宣言の破壊力も大きい。宣言しろ、と書きました。書きましたが、宣言した以上は、間違いに気づいたときに撤回する覚悟もセットで持つ必要があります。宣言の価値は「確定すること」にあります。しかし、「確定したから正しい」わけではありません。
選択は責任を生む
宣言すると、責任が発生します。
「私がAを選んだ」という事実が残ります。Aで失敗したら、私の責任です。「Bにしておけばよかった」と後悔するかもしれない。でも、選んだのは私です。
これを引き受ける覚悟がなければ、選択はできません。
覚悟とは、失敗を受け入れる準備です。「Aを選んで失敗するかもしれない。でも、Aを選ぶ」。この態度が、選択を選択たらしめます。
責任を取りたくないから選びません。選ばないから何も進みません。何も進まないから成果が出ません。成果が出ないことの責任は、誰も取りません。「みんなで決めたことだから」「状況が悪かったから」「情報が足りなかったから」。
この構造が、組織を腐らせます。そして、その腐敗の一部は私です。選ばなかった私が、この停滞を作っていました。
組織で選ぶことの難しさ
個人なら、自分で選んで自分で責任を取れます。シンプルです。
組織では、そうはいきません。
「みんなで決めましょう」と言います。会議を開きます。意見を出し合います。「Aがいい」「Bがいい」「Cも捨てがたい」。議論は盛り上がります。でも結論が出ません。「次回また議論しましょう」。
誰も選びません。誰も責任を取りません。
合議制の罠です。全員が賛成する選択肢は、大抵、誰も反対しないだけの無難な選択です。角が取れて、特徴がなくなって、「まあ、これなら文句は出ないだろう」という選択肢。本当に必要な選択は、誰かが反対します。「リスクが高い」「前例がない」「うちのやり方じゃない」。だから選ばれません。
無難な選択は、無難な結果しか生みません。飛躍しません。
組織で選ぶためには、誰かが「私が決める」と宣言する必要があります。その人が責任を取ります。反対意見があっても、決めます。「私が決めた。結果は私が引き受ける」。
これができるリーダーは少ないです。できるリーダーがいる組織は強いのです。
「そんなリーダーがいない組織では、どうすればいいのか」という問いが残ります。
答えは、自分がその役を引き受けることです。肩書きがなくても、「私が決めます」と言えます。言えば、責任が発生します。責任を引き受けることで、決定権が生まれます。権限が先ではありません。責任が先です。
私は過去に、これを小さなスコープで始めました。「このタスクの技術選定は、私に任せてください」と言いました。成功すれば信頼が積み上がります。失敗すれば、責任を取ります。どちらにしても、「誰も決めない」より前に進みます。
もう少し具体的なパターンを書いておきます。組織で「選ぶ」ために、私が使ってきた方法です。
期限を切る。「来週の月曜までに決めましょう。それまでに決まらなければ、私の判断でAにします」と宣言します。反対意見がある人は、期限までに代替案を出す必要があります。出なければ、Aで決まり。期限がないと議論は永遠に続きます。期限を切ることで、選択が強制されます。
実際にやったことがあります。「来週までに決まらなければ、Terraformにします」と宣言しました。期限が来ました。反対意見は出ませんでした。Terraformにしました。ただ、2ヶ月後、別のツールを推していたメンバーが静かにチームを離れました。反対意見が「出なかった」のではなく、「言えなかった」のだと後で知りました。そのメンバーの退職連絡を受けたとき、背中が冷たくなりました。私は「決断した」と思っていました。実際には、声の小さい人を踏みつけていただけでした。期限を切ることは、沈黙を合意と誤認するリスクがあります。
可逆性で説得する。「この選択は可逆的です。2週間試して、ダメならBに戻せます。だから今すぐAを試しましょう」と言います。不可逆な選択は慎重になります。可逆なら、試す障壁が下がります。そして、ほとんどの選択は、思っているより可逆的です。
もう1つ、使ってきた方法があります。小さく試して結果を見せる方法です。「全体に適用する前に、私のチームだけで試させてください」と言います。全体への影響を心配する人を説得できます。小さく試して結果を見せれば、「全体に広げていいか」の判断がしやすくなります。成功すれば横展開。失敗すれば、損害は最小限です。
これらの方法は、機能します。機能しますが、万能ではありません。期限が沈黙を生むこともあります。「可逆的」と言ったものが実は不可逆だったこともあります。方法を知っていることと、方法がうまくいくことは、違います。それでも、何も選ばないよりは、はるかにましです。
「選ばなかった」ことによる損失を、もう1つ書いておきます。
技術的負債の返済を、チームとして2年間先送りにしました。コードベースの中に、もう誰も理解していないモジュールがありました。テストもありません。ドキュメントもありません。しかし、本番で動いています。「触らなければ壊れない」。それが暗黙の合意でした。
返済するか、しないか。毎四半期の計画で議題に上がりました。毎回、「今期は新機能の優先度が高い」で先送りになりました。誰も「返済する」と宣言しませんでした。宣言すれば、新機能の遅延の責任を引き受けることになります。誰もその責任を取りたくありません。合理的な判断です。個人にとっては。
2年後、そのモジュールに起因する本番障害が起きました。深夜3時。PagerDutyの音で目が覚めました。画面を開く前に、原因がわかりました。あのモジュールだ。知っていました。全員が知っていました。知っていて、2年間選ばなかった。影響を受けたユーザーは12,000人。復旧に6時間かかりました。原因を調査するだけで3日。コードを理解している人間が、もう社内にいなかったからです。障害報告書を書きながら、「2年前に返済していれば」と全員が思いました。しかし、2年前の自分に言えるでしょうか。「今期の新機能を止めて、誰も理解していないコードの書き直しに3ヶ月使います」と。当時の情報では、先送りは合理的に見えました。
振り返って気づいたのは、私たちの思考のフレームが狭すぎたということです。「技術的負債を返済するか、新機能を作るか」という二択で考えていました。しかし、本当に二択だったのか。「新機能の一部を、負債の返済を兼ねた設計で作る」という選択肢がありました。「3人のうち1人を負債返済に専任させる」という選択肢もありました。二択に見えていたものは、フレームが狭かっただけです。
組織で選べないとき、選択肢が2つしか見えていないなら、3つ目がある。私はそう思っています。3つ目が見つかった時点で、議論の質が変わります。「AかBか」の対立が、「A、B、Cのどれが最も合理的か」という評価に変わります。これは冒頭の3要素の「評価」の質を上げる方法でもあります。
全体を変えることはできません。でも、自分の周囲半径3メートルは変えられます。そこから始めます。
正解を求めると、選べない
ここまで、「選ぶとは捨てること」「根拠を言語化すること」「組織で選ぶ難しさ」を書いてきました。しかし、選択を阻む最も根深い罠にまだ触れていません。正解を求めること。そして、これがこの記事で一番言いたいことかもしれません。
エンジニアは「正しさ」を職業的に追求する人種です。コードには正解があります。テストに正解があります。パフォーマンスに正解があります。計測すれば、どちらが速いかわかります。ベンチマークを取れば、どちらが優れているか数字で出ます。この「正しさを情報で特定できる」という成功体験が、選択の場面にも持ち込まれます。「もっと調べれば、正しい選択がわかるはず」。
しかし、コードの正しさと選択の正しさは、構造がまったく異なります。
コードの正しさは、実行すれば検証できます。テストが通るか通らないか。レスポンスタイムが要件を満たすか満たさないか。答えがある問題です。選択の正しさは、未来にしか検証できません。そして、選ばなかった選択肢の結果は永遠にわからない。Aを選んだとき、Bを選んでいたらどうなっていたかは、誰にも検証できません。反実仮想は実行できないテストです。
つまり、選択には正解がありません。正確に言えば、「事前に正解を特定する方法」がない。にもかかわらず、エンジニアは「もう少し調べれば正解がわかる」と信じています。技術的な問題解決で鍛えた「情報→正解」のパイプラインを、選択というまったく別の種類の問題に適用しています。これが、エンジニアが選択で最もハマる罠です。
「どれが正解か」と考え始めると、選べなくなります。正解は、事前にはわからない。やってみないとわかりません。未来は予測できません。選択の時点では、どれも「仮説」です。
正解を求めて情報を集め続けます。「もう少し調べれば、正解がわかるはず」。わかりません。いくら調べても、正解は見えません。見えないまま、時間だけが過ぎます。情報収集が目的化します。Slackで意見を聞き、ドキュメントを読み、専門家に相談し、それでも決められません。
私は先ほど、2週間かけてデータベースの比較表を作った話を書きました。あの2週間で私が得たものを正直に振り返ると、「どれも一長一短だ」という確信だけです。1日目の直感と14日目の結論は、ほとんど同じでした。13日分の情報収集が変えたのは、選択の質ではなく、私の不安の深さでした。最終日の夜のことを、今でも覚えています。14日目の夜、スプレッドシートを閉じようとして、手が止まりました。閉じたら、次は選ばなければなりません。知れば知るほど各選択肢の弱点が見えます。弱点が見えるほど、「この弱点が致命的だったらどうしよう」と怖くなります。情報は不安を解消するために集めたはずでした。しかし、情報が不安を増幅していました。
ある時期、この構造を外から眺められるようになりました。知性が高い人間ほど、結論を先に持ち、その結論を支持する証拠だけを精巧に集める。そういう罠に陥りやすい。私の場合、「選ばない」という結論が先にあり、その結論を正当化するために比較表を精緻にしていた。弱点が見つかるたびに「まだ選べない」が補強される。知性が、選択回避を完璧に合理化します。
もう1つ、身に覚えのある構造がありました。専門性を積んだ人間は、「自分は十分に調べたから、この判断の遅さは慎重さだ」と信じます。しかし、慎重さと回避は違います。私が2週間かけて作った比較表は、慎重さの産物ではなく、「自分は十分に調べた」という専門家の自信が生んだ精巧な言い訳でした。
ここに構造がある。知性そのものが諸刃の剣なのです。分析力が高いほど、バイアスを自分から隠す能力も高い。比較表を見せたとき、同僚は「すごい調査だ」と言いました。褒められました。褒められたことで、比較表が選択回避の道具であることにさらに気づきにくくなった。精度が高いほど、周囲が肯定する。肯定されるほど、止められない。
ここに「情報信仰」の構造があります。情報を集める→弱点が見える→不安が増す→さらに情報を集める→さらに弱点が見える。ループです。出口がない。このループに入った人間は、外から見ると「慎重に分析している」ように見えます。本人も「十分な調査をしている」と思っている。しかし実態は、情報収集を鎮痛剤として使っているだけです。痛みの原因、「選ぶことへの恐怖」には一切手を付けていません。
振り返ると、私の2週間は「悪い戦略」の典型でした。空疎な言葉で埋まった比較表。課題の回避。目標と戦略の混同。「最適なデータベースを選ぶ」は目標であって戦略ではない。戦略は「何が本当の困りごとか」を直視することから始まります。私は直視しなかった。データは精緻だが、診断が不在でした。と書いたが、誰も自分の戦略を「悪い戦略だ」とは思いません。思えるなら、最初からやらない。心理と構造が、ここで合流します。知性が回避を合理化し、合理化された回避が「戦略」の顔をして居座る。
ただし、十分な分析をせずに選ぶのは蛮勇です。どこまで分析して、どこから決断なのか。その境界は明確ではありません。
私の現時点での仮説はこうです。「新しい情報を1つ得ても、選択が変わらないと感じた時点」が境界です。最初の1日で得た情報は、選択を大きく左右します。3日目に得た情報は、選択を微調整する。5日目に得た情報は、もう選択に影響しません。影響しないのに情報を集め続けているなら、それは分析ではなく、決断の先延ばしです。
もう1つ基準があります。「情報を集めている自分」に安心感を覚え始めたら危険信号です。調査している間は選んでいない。選んでいない間は失敗しない。失敗しないことに安心している。「調べている」という行為が「選ばない」ことの免罪符になっています。忙しく調査しているから、サボっているようには見えません。自分にも周囲にも。しかし、選んでいないという事実は変わりません。
選択とは、不確実性の中で決断することです。 正解がわかってから決めるのは、選択ではありません。答え合わせです。
リスクを取らない選択は、選択ではありません。「どちらを選んでも同じ結果になる」なら、選ぶ必要はない。選択が意味を持つのは、結果が異なる可能性があるからです。つまり、選択には必ずリスクが伴います。
選んだ後にすること
選びました。宣言しました。責任を引き受けました。
その後、何をするか。
全力でやります。ただし、全力とは長時間働くことではありません。迷いを消すことです。選んだ後にやることは、大きく3つあります。また3つに分けている。もはや習性です。迷いを消して1つに集中すること、集中しながら自分を観ること、そして失敗から学ぶこと。どれも、選ばなかった時期には手に入らなかったものです。
迷いを消して1つに集中し続けると、何が起きるか。ある変化が訪れます。
無意識化です。
最初は意識的にやります。「Rustで書く」と決めて、1つ1つ考えながらやります。ぎこちない。遅い。コンパイラに怒られます。エラーメッセージを読みます。直します。別の場所で怒られます。
続けていると、考えなくなります。手が勝手に動きます。借用チェッカーをどう通すかが、判断ではなく反射になります。あの瞬間のことは覚えています。あるとき、所有権のエラーを見た瞬間に「ああ、ここはCloneじゃなくて参照を渡すべきだ」と手が動きました。考えていませんでした。指が先に答えを知っていました。ただし、その指が間違えることもあります。先日、無意識に.unwrap()を書いて、レビューで指摘されました。身体化された悪い癖も、無意識化されます。
そこまで行くと、その上に新しい層を積めます。言語の文法を考えなくていいから、アーキテクチャを考える余裕ができます。
選ばずに複数の言語を並行していると、この無意識化が起きません。どれも「意識的にやる」段階で止まります。どの言語でも、ドキュメントを見ながら書いています。
無意識化されなければ、その上に何も積めません。だから、選ぶことには意味があります。選ぶことで、初めて次の段階に進めます。
無意識化は、言語や技術に限った話ではありません。技術選定の判断そのものも、無意識化されます。
最初の頃、技術選定のたびに膨大な時間をかけていました。比較表を作り、ベンチマークを取り、チームで議論し、上長に説明する。1つの選定に2週間かかりました。
しかし、同じ種類の選定を10回もやると、判断のパターンが身につきます。「この規模なら、このデータストアで問題ない」「このチーム構成なら、この言語が適切だ」。考える前に方向性が見えます。2週間かかっていた選定が、2日で終わるようになります。判断が速いのではありません。迷わないから速いのです。ただし、パターンが身についた結果、パターンの外にある問題を見落としたこともあります。「この規模ならPostgreSQLで十分」と即断した案件で、実はデータの保持要件が特殊で、パターン通りでは対応できませんでした。判断が速いことと、判断が正しいことは、別の話です。
障害対応でも同じことが起きます。最初は、障害が起きるたびにパニックになりました。何を見ればいいかわかりません。手当たり次第にログを読みます。仮説を立てるどころではありません。しかし、50回も障害対応をすると、「まずエラーレートの変化点を見る。次にデプロイ履歴を確認する。直近のデプロイがなければ、外部依存を疑う」というフローが、考えなくても動きます。これが無意識化です。前回書いた「操作→分解→判断」の3層が、すべて身体化された状態です。
そして、この無意識化が「選ぶ」行為そのものに適用されたとき、選択の型が身につきます。「この状況では、まず可逆性を確認する」「この規模では、まず最小スコープで検証する」「この政治的状況では、まず期限を切る」。冒頭で定義した評価・宣言・撤退の3要素が、意識しなくても回るようになります。そこまでいけば、選択のコストは劇的に下がります。選択のコストが下がれば、選択を恐れなくなります。恐れなくなれば、動けます。
ただし、ここにも留保があります。パターンが適用できる範囲内では、選択のコストは低いままです。しかし、パターンの外に出たとき、たとえば初めて触る技術領域や経験のない規模の問題に直面したとき、選択のコストはまた上がります。新しい領域に踏み出すたびに、人は途上に戻ります。選び直して、また深めます。その繰り返しです。
組織でも同じことが起きます。チームが「この構成なら問題ない」というパターンを身につけた。そのパターンの外に出る判断を先延ばしにした結果、技術的負債が積み上がり、結局スピードも失うケースを何度も見てきました。パターンが通用しなくなった兆候を感じながら、「まだ大丈夫」と言い続ける。これも、選択の先延ばしです。
全力でやりながら、同時に自分を観る必要があります。
障害対応中、熟練のSREは「今、自分が何をしているか」を言語化できます。ログを追いながら、「この仮説は検証できた」「次はネットワーク層を見るべきだ」「今、自分は確証バイアスに引っ張られている」と把握しています。対応しながら、自分の思考プロセスを見ています。
最初は、目の前のエラーを追うだけで精一杯です。自分が何を調べているかなんて意識できません。がむしゃらにログを読んで、気づいたら3時間経っています。
しかし、ある程度の経験を積むと、対応しながら自分を観察できるようになります。「今、焦っている」「この仮説に固執しすぎている」「別のアプローチを試すべきだ」と気づけます。気づけるから、修正できます。
コードを書くときも同じです。書きながら、「今、何を考えているか」を意識します。「この設計判断は、何を根拠にしているか」「この実装は、どんなトレードオフを選んでいるか」。書きながら、自分の思考を観ます。
没入と観察は矛盾するように見えます。全力で没入しているのに、同時に冷静に観察します。しかし、この二重性が、選んだ後の成長を加速させます。
データベースのマイグレーションを始めた瞬間を思い出します。本番環境でスキーマ変更を流し始めました。その途中で「やっぱりNoSQLに移行した方がよかったかも」と迷ったらどうなるか。判断が鈍ります。中途半端なスキーマが残ります。マイグレーションを始めたら、最後までやり切ります。うまくいかなければ、ロールバックして学びます。途中で方針を変えるのが、一番まずいのです。
選んだ以上、その選択を正解にするために動きます。「Aを選んだけど、Bの方がよかったかも」と迷いながらやっても、成果は出ません。迷いがエネルギーを分散させます。
「でも、迷いは消えないじゃないか」という反論が来ます。その通りです。消えません。しかし、迷いに従う必要はありません。感情と行動は別です。迷いが湧いたとき、私は選んだ理由を読み返します。感情ではなく理由で判断する。ただ、もっと構造的な対処法があります。
もう1つ、迷いへの対処法があります。あるとき、同僚の技術選定の相談に乗りました。私と似た状況でした。2つの選択肢で迷っている。しかし、他人の問題として見た瞬間、答えは明確でした。「それ、Aでしょ。理由はこれとこれ」。5分で言い切りました。
帰り道に気づきました。私が自分の問題では2週間迷っていたのと、同じ構造の問題だ。他人の問題として見たら5分で答えが出た。人は他者の問題には冷静で的確な助言ができるのに、自分の問題になると判断を誤る。以来、私は選択後の迷いに応用しています。「もしチームメイトが同じ選択で迷っていたら、私は何と言うか」と問い直す。すると、感情的な迷いが消えて、評価の軸だけが残ります。自分の問題を他人の問題として眺めるだけで、判断の質が変わる。不思議ですが、再現性があります。これは生まれ持った知恵ではなく、訓練可能なスキルです。私は月に2回ほど、意識的にこの「他人の目」を使っています。
Aを選んだなら、Aに全力を注ぎます。Aの可能性を最大限に引き出します。Aでできる限りのことをやり切ります。それでも失敗したら、学びます。「Aではダメだった。この条件ではAは機能しない。次はBを試す」。
選択→実行→学習→選択。このサイクルを回します。
迷いながら中途半端にやるより、選んで全力でやって失敗する方が、学びは大きいです。失敗から学ぶためには、全力でやる必要があります。中途半端にやって失敗しても、「全力でやれば成功したかも」という言い訳が残ります。全力でやって失敗すれば、「この方法ではダメだ」という確実な学びが得られます。
「学びが大きい」とは、具体的にどういうことか。
全力で失敗したとき、得られるものがあります。
1つは、境界条件の特定です。「この方法は、この条件では機能しない」という知識。Rustで並行処理を書いて、所有権の壁にぶつかりました。「RefCellの乱用はデッドロックを招く」という境界を学びました。中途半端に書いていたら、「なんか動かない」で終わっていたでしょう。
もう1つは、失敗パターンの言語化です。次に同じ罠に落ちそうになったとき、事前に気づけます。「ああ、これは前にハマったパターンだ」と言えます。何度も同じ種類のデプロイ障害を起こしました。ようやく「この構成でブルーグリーンデプロイをやると、コネクションプールが必ず枯渇する」と学びました。中途半端に対症療法を繰り返していたら、いつまでも同じ障害に見舞われていたでしょう。
さらに、撤退判断の精度が上がります。次の選択で「どこまでやったら撤退すべきか」の判断が速くなります。全力でやって3ヶ月で限界が見えた経験があれば、次は1ヶ月で「あ、これは前と同じパターンだ」と気づけます。中途半端にだらだら続けた経験からは、この感覚が育ちません。
感情的な成長ではありません。認知的なツールの獲得です。
「失敗から学ぶ」という言葉は、慰めに聞こえることがあります。失敗したときに自分を納得させるための言い訳に聞こえます。
しかし、私がここで言いたいのは、もっと積極的なことです。
失敗は、投資です。 将来のリターンを得るために、今コストを払っています。と書いたが、これは失敗した人間が事後的に自分を慰める言説と、どこが違うのか。違いは1つだけあるはずです。慰めは過去を正当化して終わる。投資は次の行動を変える。変わったかどうかは、本人にしかわかりません。
新しい言語を学ぶとき、最初はバグだらけのコードを書きます。コンパイラに怒られます。実行時エラーが出ます。その1つ1つが、「この言語ではこれをやってはいけない」という知識になります。バグを出さなければ、その知識は得られません。
だから、学習段階では、意図的に失敗しにいく価値があります。「これ、たぶん動かないだろうな」と思いながら書いて、案の定動きません。そこで「なぜ動かないか」を調べます。その調査が、理解を深めます。
失敗を避けようとすると、学びが浅くなります。安全な範囲でしかコードを書きません。ドキュメントに書いてあることしかやりません。境界条件を踏みません。結果、「動くコード」は書けますが、「なぜ動くか」がわからないままになります。
ただし、ここに1つ注意があります。
「全力でやって失敗する」は、「再起不能になる」とは違います。全力と無謀は異なります。
選択にはリスクがあります。リスクを取ることが選択の本質だと書きました。しかし、取るべきリスクには上限があります。その上限は「失敗しても次の選択ができる」ことです。
会社を辞めて起業します。失敗しても、また就職すればいい。これは取れるリスクです。全財産を借金で溶かし、人間関係も破壊します。これは取ってはいけないリスクです。次の選択ができなくなります。
私はこれを「致命的でない失敗」と呼んでいます。選択→実行→学習→選択のサイクルを回すためには、サイクルが止まる失敗を避ける必要があります。全力を出しますが、致命傷は負いません。このバランスが難しい。私の場合、「致命的でない失敗」の閾値がやや高めに設定されている自覚はあります。深夜3時の障害対応を「いい経験だった」と言える程度には。ただし、これは「次がある」環境にいるから言えることです。スタートアップで資金が3ヶ月分しかないとき、同じ閾値は使えません。環境が閾値を決めます。
難しいですが、判断基準はあります。「この選択が失敗したら、次に何ができるか」を事前に考えておくことです。次の選択肢が思いつかないなら、それは無謀です。思いつくなら、リスクは取れます。
「選ぶ」とAI時代
ここまで書いてきた「選ぶ」の構造、つまり評価・宣言・撤退は、AI時代にどう変わるのか。前回、AI時代にも「方法を学ぶ意味がある」と書きました。AIは方法を知っていますが、違和感を持てません。では、「選ぶ」についてはどうでしょうか。
AIは選択肢を提示してくれます。「RustとGoのどちらが適切か」と聞けば、条件次第でどちらも推薦してくれます。比較表も作ってくれます。それぞれの長所と短所を、私が2週間かけて作った比較表より正確に、10秒で出力します。あの2週間を返してほしい、とは思いませんでした。思わなかったことに、少し驚きました。
実際にやりました。先月、あるマイクロサービスの言語選定でAIに相談しました。チームの構成、既存のコードベース、パフォーマンス要件、運用体制。条件を全部伝えました。返ってきた推奨は、私が2日かけて到達した結論とほぼ同じでした。
しかし、その推奨を見て「よし、これで決まりだ」とは思いませんでした。正しそうに見えました。正しそうに見えたのに、宣言する気にならなかった。口に出そうとして、喉の奥で言葉が止まりました。「AIがそう言ったから」では、チームの前で宣言できません。正確には、宣言はできます。ただ、「失敗したときに私が責任を取る」と言えません。推奨の根拠はAIのものであって、私のものではないからです。
結局、AIの推奨を参考にしつつ、自分で分析をやり直しました。結論は同じでした。それでも、「自分の分析に基づいて選んだ」と言えるようになりました。非効率です。非効率ですが、宣言と責任は、効率の外にあります。
ただ、AIには「選べません」。そしてここに、「情報があれば正しく選べる」という信仰への最終的な反証があります。AIは人間が2週間かけて集める情報を10秒で提供します。情報の非対称性は事実上消滅しました。それでも、人は選べない。ということは、選べなかった原因は最初から情報の不足ではなかったのです。情報は必要条件かもしれません。しかし十分条件ではない。あの2週間の比較表が、すでにそれを証明していました。情報の先にある「宣言」と「責任」と「撤退判断」。これは情報からは導出できません。
「この組織で、この時期に、このメンバーで、どちらを選ぶか」。これはAIには決められません。組織のメンバーがGoに慣れていること。来月リードエンジニアが退職すること。半年後にサービスの規模が10倍になる予定であること。社内政治的に、新しい技術を導入すると反発する人がいること。これらの文脈は、AIのプロンプトに全部書けるでしょうか。書けたとしても、それぞれの重みづけは誰がするのか。
選択のコンテキストは、その場にいる人間にしかありません。
しかし、「選択は人間にしかできない」と言い切るのも安易です。AIが文脈を理解する精度は急速に上がっています。5年後には、組織の状況をAIに伝えて、「どの技術を選ぶべきか」を聞けるようになるかもしれません。そのとき、「宣言は人間の仕事だ」と書いたこの記事は、古くなるかもしれません。
もっと足元を揺さぶる問題もあります。LLM時代の技術選定には、従来にはなかった問いが加わります。「次のモデルが出たら、この判断は無意味にならないか」。選定の前提そのものが、プロジェクトの途中で変わりえます。これは「情報信仰」とは別種の罠を生みます。「もう少し待てば、より良い選択肢が現れる」。待つことが合理的に見えます。しかし、「待つ」もまた、選ばないことの変種です。
私たちがたどり着いたルールはこうです。「現在のモデルの能力で判断する。ただし、撤退ラインに『次のモデルで再評価する』を含める」。今のモデルで目の前の困りごとを片付けられるかどうかで選びます。選んだ上で、次のモデルが出たときに「この困りごとは、まだ人間が解くべきか」を問い直す。選択を固定するのではなく、選択のサイクルを速く回します。
これは冒頭で定義した「撤退判断」の応用です。従来の撤退ラインは「この方法がうまくいかなかったら撤退する」でした。LLM時代の撤退ラインは「この方法が不要になったら撤退する」です。失敗ではなく、陳腐化です。前回書いた、VMの最適化に半年を費やした話と同じ構造がここにあります。あのときは半年で気づきました。LLMの進化速度では、3ヶ月で同じことが起きえます。方法が失敗するより、成功したまま無意味になる方が怖いのです。
しかし、仮にそうなっても、1つだけ残るものがあります。選択の責任を引き受けることです。AIが「Rustを推奨します」と言いました。採用しました。失敗しました。誰の責任でしょうか。AIの責任にはできません。AIは推奨しただけです。選んだのは人間です。
前回、「AIの出力の質は、使う人間の力量で天井が決まる」と書きました。今回の文脈で言い換えると、AIの推奨の価値は、選択の責任を引き受ける人間の覚悟で決まります。覚悟のない人間がAIの推奨を採用しても、失敗したときに「AIがそう言ったから」で終わります。学びがありません。覚悟のある人間は、AIの推奨を自分の判断として引き受けます。だから失敗しても、「なぜ失敗したか」を掘り下げます。撤退判断を行い、次の選択を磨きます。
AI時代の「選ぶ」は、評価のフェーズではAIの力を借り、宣言と撤退判断のフェーズでは人間が引き受けます。冒頭で定義した3要素の重心が、AIの登場によって「宣言」と「撤退判断」に移りました。評価はAIに任せられます。しかし、宣言と撤退は、依然として人間の仕事です。
方法を選ぶことが、Whyを確定させる
前回、「方法の探求は課題の発見につながっている」と書きました。課題とは、言い換えれば「Why、なぜこれを解くのか」です。方法を学ぶことで、新しい課題が見えてきます。今回は、その先にある「選ぶ」ことについて書きました。
学んだだけでは動けません。選ばなければ、何も始まらない。選ぶとは、他を捨てることです。宣言することです。責任を引き受けることです。そして、選ぶことで初めて、課題が確定します。
「この課題を、この方法で解く」。この宣言が、曖昧だった課題を具体化します。選択が、問いを鋭くする。「なんとなく困っている」が、「この問題を、この方法で解決する」に変わります。
方法を選ぶことが、Whyを確定させます。
「もっと調べれば選べる」は嘘です。正確に言えば、ある地点までは本当で、そこから先は嘘になる。その地点を過ぎたら、比較表を閉じてください。情報は十分にあります。足りないのは情報ではありません。覚悟です。
前回、「自分が『仕方ない』と思っているものを3つ書き出せ」と書きました。今回は、その先です。
正直に書くと、私にも先送りにしている選択がある。「もう少し情報が集まってから決める」と自分に言い聞かせて、3ヶ月以上動いていない判断がある。この記事を書きながら、気づいた。選べと書いている本人が、選んでいなかった。
書き出そうとした。3行で書けなかった。書けないことが答えだった。それでも書いた。3行になるまで削った。削る過程で気づいた。本当に怖いのは「選ぶこと」ではなく、「選んだ自分が間違っていたと知ること」だった。「なぜAを選ぶのか」「なぜBではないのか」「いつまでに判断するのか」。3行で書けるかどうかが、評価が足りているかどうかの判断基準になります。3行で書けないなら、まだ評価が足りないか、あるいは、書けないことを理由に先送りしているだけです。
と書いて、立ち止まります。冒頭で「選べ」と書きました。しかし、選ぶためには「選ばなかった選択肢を手放す余裕」が必要です。1つの言語に集中する時間がある。撤退ラインまで試す猶予がある。失敗しても次がある。それは環境の話でもあります。明日の締め切りに追われている人に「100:0で選べ」と言えるでしょうか。言えるとしたら、それは時間の余裕がある側の傲慢かもしれません。前回と同じ構造です。「課題から入れ」が呪いになるように、「方法を選べ」もまた、選ぶ余裕がない人への呪いになりえます。それでも書きます。選べる状況にあるのに選ばないのは、もったいないからです。
PRの変更差分は、まだ開いたままだった。レビューコメントを1つ書いた。書きながら、「この方法で指摘するのが正しいのか」と考えていた。たぶん、正しいかどうかは、選んでからでないとわからない。
おい、方法を選べ。