個人的な体験
書き直し。カッとなってバーンのやるのは悪手で、リファクタリングのように漸近的とは行かないまでも境界のはっきりした小さな部分問題を上手に切り出してシュッとやるのが良い。皆が書いたのを読んでそんなコンセンサスを確認できました。それができるコードベースならカッとならない気もするけれど。
そういえば個人的な話を書いていなかったとはまじさんに言われて気付いた。
自分は新卒入社した会社でカッとなって書き直しをした結果ひどいデスマをやらかした体験があり、そのトラウマからアンチ書き直し派になった。向井さんの体験と似ていなくもないけれど、自分でやらかしてしまった。ちなみに同じ会社ではより大規模な失敗書き直しが進行中だったし、その後転職した中小零細二社でもやはり書き直し失敗事例を目にした。書き直しの失敗は珍しくないし、そこからリファクタリングの価値を見出すのも自分たちの年代の同時代性かなと思う。書籍 “Refactoring” の初版は、自分が学生だった 1999 年に出ている。
一方、今まで一番熱心に仕事のコードを書いたのもその失敗書き直しだった。自分は当時ガラケー組み込み向けブラウザの SVG レンダラを開発していて、前任者から引き取ったコードがあんまりだったので書き直しを決めたのだった。(上司が阻止しなかったのは今思うと不思議。)オブジェクトモデルからラスタライザまで全部書き直し。朝から晩まで新しいデザインについて考えて、晩から朝までコードを書いていた。若かったのもあるし働きすぎて精神衛生を損ねたりもしたけれど、自分でぜんぶやる万能感は熱意に繋がっていたと思う。
今の会社でやっている仕事に、そういう熱意や責任感はない。真面目に働いてるけれど、他人のコードへの達観が根にある。例えば TL になって自分に責任が降ってきたらどうかというと・・・あんまり嬉しくないな。世の中の後任 TL はちゃんと責任とってて偉い。
板につく妥協
仕事への責任感とかは選択の問題でもあるので置いておくとしても、リファクタリングような連続的、漸近的なソフトウェア開発の様式をメンタルモデルのデフォルトとして受け入れることで失われるもあると思う。具体的にいうと、自分は理想のコードのデザインを考えなくなってしまった。
漸近的な改善は、デザインを現状との差分として考える。そうである必然性はないが、少なくとも圧力はある。あるべき理想を考え、その理想に至る長い差分の連鎖を探求するには実力が必要。実力がないとカッとなって書き直しというショートカットをするか、遠くの理想を諦め手近な改善で妥協する。後者は局所最適になってしまう。
漸近的な改善ばかりやっていると、アーキテクチャ全体への理解もさぼりがち。目につく範囲の不便を解決していくだけで仕事になるので、end-to-end のアーキテクチャをわざわざ学ばない。こうして理想への距離がまた一歩遠のく。
たとえば自分がある時期まで専門家みたいな顔をしていたウェブブラウザ、その全貌を理解していたかというと、してない。WebKit/Blink というレンダリングエンジンのレベルですら理解は曖昧だった。今のカメラアプリに至っては現像パイプラインのコードなんてほぼブラックボックスで、ぜんぜんわかってない。読んですらいない。(論文だけ読みました。) それでも仕事になる。むしろさっさと成果を出したいなら悠長に他人のコードとか読んでられない。
書き直しは逆だ。アーキテクチャの探求や E2E での理解を強制される。もちろんこちらにも限界があって、つまり俯瞰はできたが解像度が低いなんてことはよくある。書き直して無駄な複雑さをぶっとばそうとする素人書き直しは概ねこの低解像度に起因している。とはいえ漸近志向では目をそらしがちな視座を持てるのもまた事実だと思う。
理想的にはこんな風にできるとよい: 眼の前にある問題から数歩さがって全体を俯瞰し、ソフトウェアのあるべき姿についてよく考える。その理想に近づける現実的で漸近的な道筋を描いて仮説をたて、その仮説を検証するようにコードを一歩づつ書き換えていく。“Think big, act small” ってやつ。
これが難しいのは理想までの距離の長さだけでなく、その道程に山や谷があるからだと思う。理想に近づく過程ではしばしば局所最適から外れる必要がある。道から外れて暗闇を歩く苦しさや見通しの悪さに怖気づき、心やテストが挫ける。あるいは周囲を説得しきれない。
夢のある書き直し
自分の勤務先、前代の無茶振り社長がいなくなってから Moonshot という言葉をあまり使わなくなった気がする。代わりに最近、チームの PM が Roofshot というのを聞いた。月にいかなくてもいいから屋根には登ろう、みたいな。「書き直しではなく正しいエンジニアリングの力で漸近的変更を通じ谷と山を越えて行こう」という主張とも理解できる。でも谷には狼、山には熊がいるのを自分たちは知っている。何も考えず空に向かってポンコツロケットを飛ばしていたかつての無謀さが少し恋しい。
自分が仕事で手伝ってきた製品は今のところ消滅していないので、結果としてポンコツではなかったロケットたちだと言える。そして、よく考えてみるとこいつらはどれも書き直しである。Chrome というブラウザは転職してきた Firefox 関係者たちがはじめた書き直しだし、今やってる Pixel Camera はスタンフォードの教授が乗り込んできてはじめた書き直し。電子書籍リーダーは買収された電子書籍会社の面々による書き直しだった。
激しい生存者バイアスをスルーしつつこいつらがうまくいった理由を考えると、まず彼らは和良氏のいう俺 TUEEE 二周目勢だった。つまり一周目をきちんと走り、問題を理解していた。
そして、一周目で叶えられなかった大きい野望を持っていた。ブラウザではプロセス分離による高性能化、強力なセキュリティや切り離せるタブなど。カメラでは RAW にアクセスできる API の上に載せた compuational photography による超高画質の現像パイプライン。電子書籍はそういうテクニカルな超越は特にないと思うけど、それでも電話機に最適化した電子書籍アプリのビジネス的な需要はあっただろう。そういえばたびたび話に出てくる Rui-san のリンカも、単に書き直すだけでじゃなくて毎回バーンと速くなっている。
振り返ると今の自分は「一周目をちゃんとやる」を全然できていないし、昔の自分にしても大きな野望はなかった。自分にとっての書き直しは、「コードのデザインからゴミをなくしてメンタルモデルと表現を一致させること」に過ぎず、野望の礎ではなかった。コードの綺麗さは当時の自分にとってすごく重要なものだったので正当化していたが、説得力が足りない。コードのミタメばかりを気にして、そのコードで何を成し遂げるかを全然考えていなかった。それが自分の限界だったのだと思う。
こういうバーンとした書き直し、表面的には古典的 Second System Effect そのものにも思えるけれど、何か違いはあるのだろうか。Feature creep 的に機能を増やすのではなく根本的なアーキテクチャを刷新するところが違う・・・のかな?あるいは結局、単なる生存者バイアスなのかもしれない。自分はバーンとやった人たちが生き延びたあとからノコノコ参加しただけなので、本当のところはよくわからない。
漸近主義の壁
自分のバーンとやる力の無さ、漸近志向の限界は、五年くらい前から強く感じるようになった。
あるとき、自分は Mojo という Chrome IPC の置き換えを手伝っていた。 Mojo 自体は比較的よく理解された小さな部分問題の書き直し。置き換えはそこそこインクリメンタルで、データベースのマイグレーションみたいな雰囲気のプロジェクトだった。Mojo は今は完全に Chrome ツリーの一部だけれど当時はなぜか GitHub で開発しており、なぜか SDK まであった。そのくらい境界もはっきりしていた。
Mojo の手伝いが一段落した自分は、後に Flutter となる Sky という Blink フォークプロジェクトの手伝いをすることになっていた。けれど Sky は言語処理系を JS から Dart に入れ替えており、Dart 嫌いな自分はあーやだやだとグズグズしていた。
自分にとっての Mojo は、将来 Chrome OS と Android を統合するかもしれない Unified IPC Framework だった。自分にとっての Sky は HTML から不要な機能を取り除いて速いブラウザのサブセットをつくる HTML 版 ASM.JS みたいなプロジェクトだった。つまりどちらもドラスティックとはいえ漸近的なリアーキテクチャのプロジェクトだと思っていた。
Sky の言語が Dart になったとき、後者の期待は消え去った。自分はひどくがっかりしたし、同じくらいがっかりしてプロジェクトを去る人もいた。
さて、ある日上司がやってきて「あたらしいマネージャがくるからその下についてね、明日挨拶に来るからね」という。その新しいマネージャ、挨拶の席につくなり「よお、俺達 Mojo 使って新しい OS 作るから一緒にやろうな、とりあえずこれ最初のターゲットな」とそこらへんで売ってる AOSP 互換のスマホを手渡してきた。はあ?翌週、隣の机に新しいエンジニアがやってきた。「ブートローダー作りに来たっす。」
自分は Android と Chrome OS だけで十分にカオスだと思っていたから、そこに新しい OS を作るなんてあり得ない話だった。Sky が Dart になった上にこんな追い打ちを受けて嫌気が差し、社内求人を探してさっさと他のチームに逃げ出した。
この新しい OS はその後 Fuchsia という名前になり、Mojo はフォークされて FIDL になり、UI は Flutter で書かれていて、最近 初代 Nest Hub の OS を置き換えたらしい。
自分は未だにこの OS の必要性には説得されていないし逃げ出した判断に後悔はないけれど、こうした体験はリファクタリング信仰に影を落とした。結局、漸近的リアーキテクチャの大きな達成になると信じていた高速レンダラも統一 IPC フレームワークも消えてしまった・・・というか、そもそも存在すらしない自分の妄想に過ぎなかったわけだから。アタマが漸近志向に染まりすぎているんじゃないか。
それ以来、リファクタリングやクリーンアップは極力やらないよう意識している。まず目に見える結果を出せるコードを書く。まあ生理的な限界もあるのでぼちぼちリファクタリングしちゃうんだけど。
これは「一周目をちゃんとやる」小さな一歩のつもりだった。でも振り返ってみると、全然そうなってないね。漸近志向はコードのクリーンさのような内部品質だけでなく機能や性能といったソフトウェアの本質的な価値にも当てはまる概念なので、リファクタリングをやめればよいというものではなかった。
一周目をちゃんとやるには、新しいプロジェクトをはじめたり、せめて新しく始まったプロジェクトに参加する方が良いのだろう。でも自分は腰抜けすぎて、そんなリスキーな仕事はできない。それどころか腰抜け的な態度が体に染み渡っており、余暇ですら新しい野心的プロジェクトをやる気が起きない。アイデアも実力も足りてない。そもそも一周目をちゃんと走れるくらいなら、それで満足しそうなものじゃん。はまじさん の書き直しへの興味のなさはこれじゃないかな。
夢に加担する
イチから何か作る気力もないし気分転換にオープンソースごっこでもやろうかと、最近 DuckDB というプロジェクトにしょぼい PR を書いている。DuckDB は BigQuery, RedShit や Presto のような columnar storage の OLAP データベースを SQLite みたいなライブラリにしようという試みで、二年前くらいに開発が始まっている。SQL とか作るのに時間がかかるので、二歳はそこそこ若い部類。たとえば SQLite は 20 歳で MySQL や PostgreSQL は 25 歳くらい。もともとはデータベースをいじれたら面白いかもとはじめたパッチ修行、触ってみると実際コードベースの若さを感じる。
このプロジェクト、調べてみるとまあまあ野心的な書き直しだった。DuckDB の中の人たちは CWI というオランダの大学から spin-off したアカデミア。 CWI は MonetDB という最古の columnar storage の一つ (よく引用されている)を開発した由緒ある大学で、DuckDB の中の人たちも MonetDB を触っていたらしい。あるとき MonetDB をライブラリ化する MonetDB Lite というプロジェクトをはじめたもののサーバをライブラリにリファクタリングするのはさすがに厳しく、コードベースも古臭いしいっちょ新しく書くかと DuckDB は始まった(論文)。ちゃんと一周目をやっている。
二周目の野心は色々あるっぽいけれど、個人的には Python のデータ分析ライブラリ Pandas の DataFrame オブジェクトに直接 SQL を書ける機能が好き。Pandas 便利だけれど、時々 SQL でズバっと整形できた方がラクだなと思うでしょ。
とはいえ自分はデータベースの素人で、コアの難しいところには手が出せない。個人的には二周目、書き直しの要素はない。でもきちんと一周目をやった人たちが二周目を走る手助けができたら楽しいかなと思い、しょぼいバグとかを直している。
自分自身で一周目や二周目を走る日が当分来なそうなのは少し悲しいけれど、今は身の丈と受け入れている。