コーディング ファスト&スロー: 開発者と自信過剰の心理

今日は、開発者が見積もりを作成している時に脳内でどんなことが起きているのか話してみたいと思います。なぜこんなにも見積もり作業が難しいのか、そして、私の見積もり精度は相変わらずひどいものですが、私がどうやって(非常に幸せな事業主の方々に向けて)ソフトウェアを書いて生計を立てる術を編み出してきたのかについてお話ししたいと思います。

まずは昔話をひとつ。

あれは<私がものすごく年寄りには見えない程度の年代をここに挿入>頃でした、私は年若き開発者でした1。大学のコーディング演習では優秀な成績を修め、若手開発者として誰がどんな問題を提示してきても解決し、想像を絶する速さでどしどしコードを量産していました。新しい言語は週末の間に習得し、書けるようになっていました(少なくともそう信じていました)。

それで自然な流れとして自分でプロジェクトを取り仕切ることになりました。アカウント・マネージャが大まかにクライアントの要望を説明してくれて、内容について話し合った後、「3週間くらいあればできる」と私は言い、彼は「いいでしょう」と言いました。それで私はコーディングに取り掛かったのです。

さて、結局どのくらい時間がかかったと思いますか? 4週間、それとも5週間でしょうか。
それが、実を言うと3カ月かかったんです。

あの頃のことははっきりと覚えています。「優れたプログラマ」としてのセルフイメージが出来上がっていたところに、恐ろしい失敗を犯した私は不眠になり、パニック発作を何度か起こしました。でもそれでも仕事は終わりません。私は胃に穴があきそうになりながら、見せられるものはまだないと、アカウント・マネージャに延々と説明し続けなければなかったのです。
その暗黒の時代に私は、こんな失敗は二度としないと心に固く誓いました。

しかし残念ながら、私のキャリアを振り返ってみて心底分かったことがあります。私の見積もりは常に見当はずれなのです。

それどころか、こんなことも分かりました。正しい見積もりができる人などいないということが。

最近、Daniel Kahnemanの『Thinking, Fast and Slow』(訳注:日本語版があります。『ファスト&スロー(上)あなたの意思はどのように決まるか?』)を読みました。心理学が解き明かしてきた、人間の認知力とその素晴らしい強み、そして(驚くほど予測可能な)弱みについての広範な概観について書かれています。

気に入ったのは「自信過剰」についての箇所です。そこには言うなれば、開発者が見積もりを作成する方法との関連性があったのです。

なぜあなたは見積もりが苦手なのか、パート1: ソフトウェア開発とは最初は分からないことを学んでいくこと

最初に言っておきますが、私たちの見積もりが全然当てにならないのには2つの理由があります。第一の理由は回避できない類のものです。ソフトウェア開発の本質は、コンピュータに指示を出すため、とてつもなく明確な詳細について把握する作業を伴うものです。ここで問題になるのは、着手する時には目に見えてない部分に問題が隠れており、それをあなたは完全に理解していないということです。こういう問題が後に噴出して、あなたを完全に打ちのめすのです。

この手の問題は本当に避けられません。もし“完全に理解している”なら、その処理をする既存のライブラリやソフトウェアの部品が存在するわけで、あなたは何も書かなくてよいということになります。そうでない限り、そこには不確実性があり、時に暴発するのです。こういった暴発の解決に、1日から1年、または宇宙滅亡の日を超えるまでかかるかは分かりません。

例えば、あるサードパーティのサービスへの接続の信頼性が低かったとしましょう。そうすると失敗時のリトライ処理のトラッキングレイヤを全て書かなくてはなりません。また、データベースがある特定の文字セットのエンコーディングを読み取れない場合は、最初からスキーマを再構築しなくてはなりません。古典的な問題としては、顧客に出来上がったものを見せたら、当初の要求とは少し違うものが欲しいと言い出すことです。ちょっとだけここを直してという要求が非常に大変な作業につながる、というようなことがあります。

最初にこういう問題に出くわすと、「仕様の段階でもっと慎重に定義しよう」と思います。でも、これが大きな間違いなのです。何故でしょう。その理由とはこうです。上述の例から分かるように、問題を事前に把握して詳細な仕様を書けるとしたら、コードが書けるからです。これはどうすることもできません(これを読んで異論がある人には何度も言いますが、本当に、本当に、本当に、この問題は回避しようがないのです。完全な仕様書はものすごく効率の悪いものです。もっと効率の良い方法についてこれから述べたいと思います)。

しかしここが面白いところです。実地で数カ月以上仕事をしたことがあるプログラマなら誰でも、私が上述したような問題に必ず突き当たるのです。

そして、それでもひどい見積もりを作り続けるのです。

さらに悪いことに、私たちは自分の見積もりに確信を持っています。私は未だに自分の見積もりに自信を持っているのです。それを作成した時点では。

ちょっと待ってください。私が言いたいのはつまり、全ての開発者が全く同じように、予測可能な思考のエラーに陥っているということでしょうか。

そうです。それがまさに私の言いたいことなのです。

なぜあなたは見積もりが苦手なのか、パート2: 自信過剰

Kahnemanは「エキスパート」が予測を行う際の問題について詳しく述べています。驚くほど様々な場面で、これらの予測というのは完全に無駄になります。非常に多くの場合に、特に次に述べる3つの事実が当てはまります。

  • 「エキスパート」の将来の出来事についての予測は、ほぼ無意味と言えるほど完全に当てにならない
  • そうであっても、「エキスパート」は彼らの予測に関して非常に自信を持っている
  • そして、何と言っても、彼らの自信を損なわせるものは何一つないようである

この最後の項目は本当に注目に値します。エキスパートたちがいかに、自らが過去に失敗したという証拠に正直に向き合おうとしても、また、人間の認識力の欠陥というものを深く理解していたとしても、自分たちの予測の正確性に関して心の奥底で感じている自信は揺らがないのです。

Kahnemanは、このことに関連する自分自身の失敗について驚くべき話を披露し、説明しています。
「これを読んで全ての言葉に心から納得したとしても、あなたが将来に判断を下す時の自信は揺らがないでしょう」

興味深いのは、エキスパートの予測がかなり当たるケースもあるということです。そのことについてこれから少し検証し、あなた自身の開発プロセスにどう応用できるのか、考えてみようと思います。でもその前に、間違った自信過剰がどのように作用するのか、その詳細について実際に検証してみたいと思います。あなた自身についても思い当たることがあるかもしれませんね。

間違うとはどういうことか:システム1とシステム2、そして3週間と3カ月の問題

『Thinking Fast and Slow』の中でKahnemanは、私たちの思考を司る2つの「システム」の相互作用の心理状態について、ページを割いて説明しています。システム1とシステム2です。かなり簡単に要約させてもらえれば、「システム2は注意深く、合理的で分析的な思考であり、システム1は素早く、推測に基づいた、パターンマッチング的な思考」です。

そして決定的なのは、進化というものが、まるでシステム2をできるだけ介在させないことを目標としているかのように思えることです。進化という観点から言えば納得できます。システム2はとても時間がかかり、かなり費用もかさむので、非常に限られた状況においてのみ運用されるべきです。しかしここには多分問題があります。思考することなしに、あなたの頭はどうやってシステム2を発動するべき時を知るのでしょうか。この観点から、心理学の多様な「認知バイアス」の多くは、洗練された工学的手法として理にかなっており、どうやって即時に注意を割り当てるのかと言う、厳しい現実世界の問題に対処できるのです。

システム1と2の相互作用が本当にひどい結果を導くのを見てもまだ、見積もりを信じるのをやめないことについて、私の友人であり(Hut 8 Labs の共謀者でもある)Edmund Jorgensenに話を聞いてみようと思います。彼はメールで次のように説明してくれました。

「このプロジェクトにどのくらいの期間かかるか自問する時、システム1では全く分からなくても、何かしらの答えを見つけようとして、質問を置き換えるんだ。何に置き換えるかって?『これをやるとしたら自分はどのくらい自信を持ってやれるか』というような質問を、時間の見積もりに換算する。個人によってその乗数は大分違う(例えばBobがXレベルの自信がある時、3週間と言い、SuzyがXレベルの自信がある時、いつも5週間、と言うように)」。

自分が2つの“大まかな”時間の見積もり感覚を持っていると自覚している人は挙手してください。例えば、私の場合は「3週間」と「3カ月」です。前者の意味は「ややこしそうだが基本的にはやり方は分かる」で、後者の意味は「わあ、これは大変そうだ、何をすればいいのか分からないが、まあ多分理解できるだろう」ということになります。

つまり、Edmundは完全に正しいのです。
(家で同調してくだっている方へ。私の“3週間”プロジェクトは5~15週間かかり、私の“3カ月”プロジェクトは概ね1~3年かかります。そんなに長い間、誰かが私に賃金を払い続けてくれるケースは非常に珍しいですが…)。

いいだろう、もう自信過剰はやめよう!

ここまで読んであなたは、「Danの言いたいことは分かった。このような見積もりの難しさを考慮して、システム1ではなくシステム2を働かせるやり方で臨めばいい。そうすれば、注意深く分析的な思考によって、もっと的を射た見積もりを作成することができる」と。

おめでとうございます。ウォーターフォールモデルを発明しましたね。

このモデルは基本的に「コーディングを開始する前に完全な仕様書を」というお約束のことです。直感的に見積もるのではなく、各々が分析的な思考で詳細な仕様を作成し、細かい要素に分けて見積もるのです。

でも、これでも、例のごとく失敗します。

ここで本当にやっかいなのは、見積もりの誤りの元となる2つの原因の相互作用です。人間の自信過剰への偏向、それと、実地のどのようなソフトウェア開発プロジェクトにもつきまとう、生来の不確実性です。この不確実性がひどいせいで、どんなに注意深く合理的なシステム2も、正確な予測をすることが難しくなるのです。

幸いなことに、あなた自身の認知力の長所を働かせつつ、実地の仕事における激しい変化をうまく処理する方法があります。

まず、あなたの思考の長所を働かせる方法です。

エキスパートが見積もりを誤らない状況と、その活用法

Kahnemanと他の研究者は、エキスパートの判断がそれなりに信頼できる状況を明らかにしました。彼はこのように言っています。

「ある直感的な判断が信頼できるかどうかを知るためには、2つの問いを立てるとよいでしょう。1つは、「判断がなされた環境は、手もとの証拠から予測ができるような規則的なものか?」という問いです。この答えは、診断医に対してはイエス、証券コンサルタントに対してはノーとなります。そして2つ目は、「そのエキスパートは判断に必要な手がかりや規則性を覚えるための十分な機会を与えられているか?」という問いです」

「十分な機会」とは、何度も予測を立てる経験を積むことができ、頻繁なフィードバックの繰り返しによって予測の精度を把握することができるような機会のことです。
6~18カ月のソフトウェア開発プロジェクトというのは、悲惨なほどこれらの条件を満たしません。これまで述べてきたように、環境がまるで“規則正しくない”からです。加えてエキスパートは多くの予測を立てることも、即座にフィードバックを得ることもできません。1年以上かかるような仕事ではフィードバックの間隔が長過ぎて、直感を鍛えることができないのです(そして多くの回数の予測を行うこともできません)。

しかしながらソフトウェア開発において、上の条件をぴったり満たす見積もりのやり方があるのです。0~12時間の、ただちに実行されるタスクについて見積る方法です。これぐらいの規模だと、様子がガラっと変わってきます。

  • 依然として変動性はありますが(詳しくは後述します)、“環境の規則性”をある程度信頼することができます。4時間のタスク2つは、6カ月のプロジェクト2つよりもずっと多くの共通点を持つ傾向にあります。

  • このような見積もりは数年のうちに何百回も行うことができます。

  • 見積もり精度についてのフィードバックを非常にすみやかに得ることができます。

私が経験した中で最もスピーディだったチームは、毎週スプリントを行っていました。そして全てのタスクを原則0、2、4、8時間の単位に分解していました(さらに8時間のタスクについては常に精度を疑い、より小さな単位に分解しようと努めていました)。私たちはこれらのタスクの見積もりをとても素早く、いくぶんラフに行っていました。プランニングポーカーのような形式さえ使いませんでした。

こういう場合にシステム1の強みを活かすことができるのです。訓練を積む機会があり、たくさんの事例を見ることができ、有意義なパターンを収集することができるからです。そして短いスプリント期間のおかげで、非常に素早く見積もりの質についてフィードバックを得ることができるからです。

待って待って待って、じゃあ4時間の見積もりを1000回立てよう!

このような小規模な見積もりは立てられるのに、どういうわけかこれらを6~18カ月の見積もりにまとめ上げることができないということを、どのように説明すればよいのでしょう。誤差は平均化されないのでしょうか?

私は小規模な見積もりは大体正しいと思っています。しかしその見積もりが間違っていた場合、実はその誤差には限度がないのです。数学っぽく言えば、私は現実の時間は「べき分布」すると考えています。べき分布は安定した平均値を持たず、分散が無限大になることで知られています。率直に言えば、巨大なウォーターフォール型プロジェクトは、私にとってべき分布のように感じられるのです。
あなたはきっと「4時間と見積もったタスクに1カ月や2カ月を要するなんてことがあるのか?」と考えているでしょう。

そんなことはいつも起きています。何かをいよいよやり遂げようというところで、スコープをまるっきり変えてしまうような忌まわしい障害を発見した時などです。例えば最近関わったスタートアップで、システムから単一障害点を取り除くために、自分たちでコーディングしたIMAPサーバのフロントに、ロードバランサを配置することになりました。1台のサーバがダウンしても、ロードバランサがすみやかにもう1台のサーバへとフェイルオーバを行い、顧客に影響を与えないようにするためです。

これは4時間で済む類のタスクに思われました。

しかし実際に取り掛かろうとした時、私たちはIMAPサーバというのは慣れ親しんだHTTPサーバとは違って、接続状態を維持するということに気付いた(思い出した)のです。そのためもう1台のサーバへ透過的にフェイルオーバを行おうとすると、何とかして両方のIMAPサーバと接続状態を維持しておくか、IMAPサーバとの接続状態を認識し、維持するようなプロキシ機能を持ったフロントのロードバランサをコーディングしなければならなくなりました。

これは私たちにとって、3カ月程度はかかるプロジェクトに思われました。2

短い間隔のスプリントが重要な理由は他にもあります。ひどい見積もりによって生じるコストを最小限に抑えこむことができるのです。

我々は皆、見誤るだけなのか?

それでは一体どうすればよいのでしょう? 私たちのプロジェクトは失敗する運命にあるのだと受け入れるしかないのでしょうか? 私たちはいつも約束を反故にするから、関係者との仲を悪くしていくのだと認めるしかないのでしょうか?

重要なのはまず、長期的見積もりを正確に立てることは根本的に不可能なのだと受け入れることです。それを認めることができたら、非常に難題ではありますが、次の問題に取り組むことができます。つまり、有意義な長期的見積もりは立てられないとして、その上で開発チームはどうすれば大きな価値を生み出せるのか? という問題です。

私たちは、様々なアジャイルのアプローチが世界を席巻している理由についての、第一義的な説明に辿り着きました。次の投稿で、さらに詳細について書きます(“納期なし! 見積もりも仕様もその他諸々の嘘もないソフトウェア開発”)。

Hacker NewsSlashdotでの会話にぜひ参加してください)

――――――――――――――――――――


  1. (ラジオでは<その時代の楽曲をここに挿入> がかかり、みんなが<当時のTV番組>について話していました) 

  2. もしあなたが「待て、3カ月ということは、つまり君の過去の“3カ月見積もり”と同じなんじゃないか?」と思っているなら、何のことだかよく分かりませんね。