最近考え事が増えたので久々につれづれと書いてみようと思う。
今日は、「間違った問題を解くことは、エンジニアにとって最も怖いことだ」という話をした。
---
4月になり、新しいメンバーも増え、チームとしてもまた新たに活気づく時期になった。うちだと4月は査定の結果が共有される時期ということもあり、半年ごとの振り返りとともに、また新たに次の半年に向けて歩みを変え始める時期でもある。こと給与に関して言えば上がったり下がったりするわけども、振り返りをして、じゃあそれを受けて自分自身が次の半年でまた何をするかというのは自分自身の問題である。
最初に仕事につくときは、さあ果たしてこのチームで自分は何をしたらいいのだろうと考えるだろう。私が新しいチームに入るときはいつもそうして始める。それぞれが得意そうな分野をコミットログやらチケットから想像し、設計を決めるためのドキュメントから議論の様子をみつつ、過去の資料を洗いざらいに読み込み、このチームのなかで一体何に着手するのが良いだろうかというのを決めるのになかなか時間がかかる。自分がプレーヤーの場合にはこれが顕著だ。自分のスキルとプロダクトの現状を照らし合わせて、最も磁力が強くはたらくところを探しに行く。それが見つかれば、いよいよ詳細に見始める。
何かをしはじめるときには虫の目と鳥の目を使う。虫の目はごく繊細な様子を読み取る。そのプロダクトのコードのほころびから、過去になぜこういう設計になってしまったのかを想像していく。現状のつくりがやろうとしていることを深くまで読み解く。もしボトルネックがあるのなら、本当の原因を深掘っていく。細かい振る舞いを把握していく。これが虫の目だ。
鳥の目は鳥瞰の目のそれである。全体像を把握する。プロダクトがなぜこのような狙いに基づいて作られているのか。そもそもこの設計にした理由はなんだったのか。過去の資料をみつつ、想像を膨らませていく。ここで作ろうとした競合優位性はなんだったのか。あるいは、志半ばで途絶えている状態なのか。複数のコンポーネントが同じようにしているようにみえるが、どういう狙いがあるのか。抽象をたどって、理由を繋いでいく。街の作りを上からみるように、どうしてこの道はこの方向に引かれているのだろうというのを想像していく。こうして2つの目で紐解くということをする。
どんなプロダクトでもこのやり方がうまくいくかどうかはわからないが、今のところ関わったものはこういうやりかたでやっている。大抵の場合プロジェクトに入るときというのは、もとにあるプロダクトとうまく付き合わなければならない。何をするかを決めるためには、頭にいろんなものごとを詰め込んだほうが、後々効率が良い。
---
間違った問題を解くのはなぜよくないか。どんな問題でも、問題を解くのは時間がかかる。そしてエンジニアは問題に取り掛かるとそれを楽しみ、自分の知る最良の手段でそれを解く。問題を解く楽しみこそこの職業の醍醐味とも言える。問題を解くために、実現力を私たちは日々高めていて、なるべく問題を解けるように打ち込む。同じ問題でも人によって解き方が違う。その違いを私たちは楽しむ。
間違った問題でも解いているときは夢中になるし、それを責めることはとても難しい。でも、間違った問題を解いているときは、本当に解かなければならない問題に使える時間を失ってしまっている。同じ時間をつかって、同じような大変さで問題を解いていても、成果が変わってしまう。成果の大きさは問題の解き方より、どんな問題を解いたかのほうが支配的なことが多いのである。
じゃあ問題を設定するのは誰か。これはきっと環境によるだろう。全部自分でビジネスを含めて設定しているなら自分で自由に問題を設定できる。もしそうじゃないなら、問題設定は他の誰かがやるか、あるいは自分でやればいい。もし自分で問題を設定できるならすべて自分の頭で考えればいい。でも、もし自分が問題を設定できなくて、そしてそれが間違った問題だとしたらどうしたらいいだろう?問題を解き始める前に、この問題を解くべきではないとわかるだろうか?あるいは、盲目的に着手するしかないのだろうか。もし解くべきでないとあなたが思っているなら、果たしてどのようにその意志決定を変えることができるだろうか。
問題の設定が大事だとわかっていても、案外その問題設定を変えることが難しいこともあるだろう。組織によって意思決定の仕方は様々だ。明確なプロセスを経て決めるところもあるだろうし、あるいは井戸端会議的に勢いで決めることもあるだろう。意思決定の最終責任者を置いて、決めることもよくあることだ。じゃあ果たしてその問題を解くと決めたことにある背景はなんだろう。なぜその問題を解くと決めたのだろう?意思決定の背景を知ることは、問題の良い解き方に近づくための良い方法である。
もしその問題設定が間違っていることにあなたが気がついたらどうするべきか。あなたがなぜその問題を解くべきではなく、他の問題を解くべきだと考えているのかを、意思決定の主体である人たちにわかりやすく、論理的に伝える必要がある。何をすべきかを考えるのは9割は情報で、1割はセンスなのかもしれない。けれど、なぜをそれをすべきかに答えるためにはロジックが必要である。であるなら、なぜそれをしないべきかに答えるにもやはり論理が必要だ。一度決めたことを変更するには、最初の決断から時間が経つほど慣性がかかっていて、より強固なロジックが必要になることが多い。間違った問題を解いていると自覚しても、もしそれを覆すほどのロジックがなければ、そのまま進んでしまうこともあるだろう。覆すときには、決定した時点よりもより確固たる地盤に基づいた説明が必要になるのである。
---
こうして間違った問題に時間に取り組み事になってしまうことの代償は大きくなっていく。なので私たちは最初の意思決定を慎重かつ大胆にしなければならない。情報のない意思決定は間違いに向かう。本当にその場で正しい情報が整い、議論しているメンバーが複数の面から議論できているかどうかを互いに観察しなければならない。問題そのものの関連する範囲が広ければ広いほど意思決定は困難になる。情報を待っていては問題をそのものを解くことができなくなってしまうこともあるだろう。あとから見て、そのタイミングであれを決断できたのは運が良かったものだと思うこともあるかもしれない。それはその時点で集めうる情報を集めて、最後にはそのメンバーの趣向で決めるしかない。決断をするときというのは、無駄に生じうるリスクの大きさを抑えつつ、最終的にはリスクを選択して取りに行くプロセスだ。最後の選択には趣向があっていいし、おそらくあるべきなのだと思う。
物事を決めることが難しいとわかっているからこそ、決定をするタイミング以外の時間でより良い決定をするための情報を集め、考えをまとめ、考えられるメンバーを増やし、良い決定をできる環境を整えるべきだ。複数人で物事を決めるのであれば、そのメンバーの中で自分がやるとより鮮明になる情報あるいは領域を深掘りし、次の決定に活かせるようにするとよい。結果的に、それが将来の時間の使い方をよりよくする。
---
プログラムを書くことは、意思決定である。結局のところ私達プログラマは日々判断をして、コードを書いている。何をするかを把握し、なぜするかを整理し、何をしなくてよいかを判断し、どうやっても同じスピードで流れる時間を使って、コードを粛々と書く。時には実現するために大量のコードを書いては消す。荒く書き、イメージを具体的に落とし込み更に想像力をかきたて、あるべき形に落とし込んでいく。その過程も問題を設定する段階で既に織り込まれていて、私たちは試行錯誤のなかで問題を解くことを許容される。私たちはそうして、いま自分にできる最高のやり方で問題を解く。
コードを書く前に、良いプロダクトになるかどうかはほとんど決まっているのだ。