「ソフトウェア書き直し」の是非はなぜか目の離せない話題(1, 2, 3)で、その手の話があるとつい読んでしまう。自分は仕事では別に書き直しを決断できる立場ではないし、余暇でも特に書き直すソフトウェアがない。他人事。なのに目が離せない。オブセッションと言っていい。なので数年に一度は心の中のリライト話を吐き出して精神の平安を取り戻したい。今日はそんな日です。
Things You Should Never Do
インターネットのプログラミング・サブカルチャーに「書き直し・ダメ・絶対」というミームを持ち込んだのは、今からおよそ 20 年前の 2000 年に Joel Spolsky が書いた Things You Should Never Do, Part I – Joel on Software だと思う。(日本語訳は本になっている。昔はインターネットでも読めた気がするんだけど。) これは Netscape という会社が書き直した主要製品 Netscape Navigator に関する話である。同社はブラウザをフルスクラッチで書き直し、でもその出荷が遅れに遅れ、競合の Internet Explorer に市場を明け渡すことになった。結果として Netscape という会社は傾いて、数年後には買収され、なくなってしまった。残念でしたね。やっぱり書き直し良くないですよね。やめといた方がいいですよ、書き直さなくてもアーキテクチャとか直せますから・・・とまあそんな話だ。
当時の人々はこれを読んでわりと説得され、書き直し良くないな・・・とか思ったりしていた。時代の流れもあった。書き直しの主要な代替であるリファクタリングを世に広めた Martin Fowler の書籍 Refactoring の出版が 1999 年。ちょうと世の中のプログラマが「クソコードを書き直さなくても心を病まずに済む方法があるかもしれない・・・」と気づきはじめた頃だった。
逆に言うと「リファクタリング」という行為は今ほど当たり前ではなかった。だから Joel の主張にも新鮮味があった。
先の要約は実はちょっとウソがあった: “Things You Should Never Do” は Netscape が Netscape Navigator のベータ版配布をはじめた時に書かれている。つまり Netscape が潰れる前に書かれ、期待の新バージョンにめっちゃ水を差している。世の中(サンプル数 1, つまりわたくし) はこの新バージョン Netscape Navigator をすごく楽しみにしていた。なんか UI もかっこよくなったりして、こいつはすごいことが起こりそうだぞ今のところバグだけでクソ遅いけど・・・みたいな気分だった。そこに Joel は「クソ遅くてバグだらけなのは書き直しだからだよ」と数年後の崩壊を予言したわけで、先見の明ある慧眼記事として人々はそのあとしばらく読み継いだわけ。
けれど 20 年後の我々はもっと色々なことを知っている。Netscape の中の人はその後に買収元の AOL を説得し、Netscape Navigator 5 をオープンソース化した。これは史上初といってよいガチな企業発 OSS だった。コードをオープンソースしたのみならず、中の人は Mozilla という新会社/非営利団体をスピンアウトして開発を続け、Netscape Navigator も Firefox という超人気ブラウザとして蘇り、Web 2.0 とかを後押しして Microsoft の脅威となった。つまり書き直しは Netscape (会社) を潰したけれど Firefox (製品) を生み出した。これじゃダメなの?
Go, from C to Go
一方のリファクタリングも 20 年の間にずいぶん進化した。IDE のリファクタリングサポートやプログラミング言語の AST アクセス容易化のような技術革新もあったし、Microservices のような大規模インターネットソフトウェアのリファクタリング・パターンも広く知られるようになった。バーンと書き直さなくても、書き直したいところをリファクタリングで切り出して、そこだけ書き直せばいいじゃん。そんな考えが普通になった。
自分はある時期までリファクタリング原理主義者だったので、イチからソフトウェアを書き直すのはプログラマがザコだから・・・というのは煽りすぎだけど、眼の前の問題に対して実力が足りないからだと思っていた。この主張を裏付ける世の中のハイテクリファクタリングも、オープンソースやエンジニアリング・ブログの隆盛に伴い色々と目にした。たとえば従来難しいとされていたデータベースのオンラインスキーマ変更や移行も、人々は普通にやってのけるようになった。“database migration dual write <新し目のデータベース>” とか検索すると簡単に事例が見つかる。
ハイテク・リファクタリングの金字塔の一つは Golang コンパイラの C から Go への書き換え だと思う。従来はイチからの書き直しの口実になりがちなプログラミング言語の乗り換えを、コード翻訳ツール を併用することで安全に乗り切っている。ほらね、眼の前の問題に対して十分な実力があれば書き直しとか必要ないでしょ?
この例のいいところは「そんな実力あるわけねーだろ!」心置きなくつっこめるところ。Russ Cox より実力なくてもまったく困らない。いや困るかもしれないけど、それは人類プログラマ数名を除きだいたいみんな困ってる。
こうして、リファクタリング・・・より一般化していうと安全で漸近的なレガシー殺しは、かっこいいものになった。少なくとも森田の中では。
Showstopper!
書き直しの方はというと、まあ色々あると思うけど自分の印象にのこっているものをちょこっと紹介する。
「リファクタリング」が常識になる前の 20 世紀、書き直しは自殺行為ではなく、時にかっこいい英雄的行為だった。その象徴が Windows NT という Windows 10 の祖先の開発を描いた書籍 “闘うプログラマー” だと思う。原初 Showstopper! の出版は 1993 年。Windows NT では、何年も書けて Windows という OS をまあまあイチから書き直している。このやばいデスマぶりを描いたのが「闘うプログラマ」。とはいえ商業的にみると(そしてたぶんテクニカルにも)Windows NT は大成功した。デスマに巻き込まれた当時の Microsoft 社員も家の一つくらいは建ったことだろう。デスマにしても、自分はこのプロジェクトでは絶対に働きたくないけれど友人の中には「俺もカトラーの下で一つ偉業を成し遂げたいもんだわ」という猛者もいて、そこにある種の魅力はあった。つまり Joel Spolsky がかつて働いていた Netscape 殺しの Microsoft も、なんだかんだで書き直しをしていた。
時の流れを比べるため、最近読んだリライト・デスマ・ストーリーを一つ紹介したい: “Uber’s Crazy YOLO App Rewrite, From the Front Seat” は 2016 年に行われた Uber のスマホアプリ書き直しの様子を当事者が伝えている。イベント登壇中の社長の発言によって決まる根拠レスな締切。ダークローンチ無し、段階的ロールアウト無しの博打リリース。ホテルに缶詰のオールナイター。燃え尽きていく人々。モバイル固有の厳しさを差し引いても四半世紀の技術的進展を感じさせない荒々しさがすごい。これがユニコーンってやつか・・・。
当時の Uber を包んでいた時代の風によってこのリライトは奇跡の成功を収める。しかし Windows NT と違って時代の風は長く続かず、翌年 2017 年の内部告発 (スマホデスマとは無関係) によって件の社長は職を追われたのであった。株価を見る限り今も業績はぱっとしなげ。
そういえば Showstopper! の Microsoft でも, Windows の書き直し的プロジェクトだった Longhorn (2006) は失敗とみなされているな。いわゆる書き直しとはちょっと違う気もするけど。
Servo
まあデスマの話は置いておこう。自分にとってここ 10 年くらいで一番印象的だった書き直しは、なんといっても Servo だな。
Servo は Mozilla によるウェブブラウザの書き直しである。プログラミング言語 (Rust) から作っているので、正真正銘のイチからの書き直しと言える。JavaScript の処理系は再利用しているけどそれはまあ、いいじゃん。プロジェクトの開始は 2012 年らしい。Netscape Navigator 5 以来 10 年ぶりのリライトと見ることもできる。NN は C から C++ に移行したけれど、今度は C++ から特製言語の Rust. そして Firefox の次バージョンではなく research という位置づけを選んだ。つまり Firefox は並列に開発を続けている。
その後 Servo の CSS パーサ Stylo や GPU ベースのレンダラ WebRender など、いくつかの成果は Quantum というプロジェクトとして Firefox に持ち込まれ、一定の成果を挙げた。けれど Servo は成功した…と素直に言うのはちょっと難しい。なにしろ去年のレイオフで Mozilla は Servo や Rust の開発者をばっさり解雇してしまった。Servo はオープンソースなので開発は一応続いているが、減速は著しい。NN のときとちがって Servo の開発の遅れがレイオフの主因ではないとおもうけど、(たぶん Firefox OS のようがよっぽど人と金をつっこまれていたと思うし。) それでも開発者がクビになってしまったプロジェクトを成功と呼ぶのは憚られる。
やはり Servo は書き直しの失敗で、Joel Spolsky は正しかったのだろうか。
Flutter
リライトでもリファクタリングでもないソフトウェアの大改造手法にフォーク、あるいは「魔改造」がある。元のコードを、互換性を気にせずバンバン書き換えていく。互換性を意図的に捨てる点で、魔改造はリファクタリングと対照的である。一方でコードの連続性はリファクタリングに通じる部分がある。この連続性はリライトと似ても似つかない一方、リファクタリングでは辿り着けないゴールを目指すショートカットとしてリライトと魔改造には似通ったところがある。リファクタリングとリライトを混ぜ合わせてひっくり返すと魔改造になる。
興味深い魔改造の事例として、Dart という言語向けの クロス OS モバイル SDK Flutter を挙げたい。
Flutter はもともと Chrome (Blink) の魔改造プロジェクトとして始まった。2014 年に push された最初のコミットをみるとまだ Blink の姿を見ることができる。当時は Sky と呼ばれていたこのプロジェクト、なにがしたいのかは多分誰にもわかっていなかった。README にも “We’re experimenting with different ideas and exploring various approaches, many of which won’t work and will need to be discarded, but, if we’re lucky, some of which might turn out to be useful.” と書いてある。その後プロジェクトからは HTML とかが取り去られ、JS は Dart に差し替えられ、やがてスマホのクロス OS な UI フレームワークとして収束していく。今日のコードにその出自を伝える要素は無い。
魔改造をリライトやリファクタリングと同列に語るのにはやや無理がある。でも自分はどうしても Servo との対照を考えてしまう。Flutter はもともと、当時の Chrome (Blink) をどうにかして劇的に速くしたいという動機で始まった。たぶん Servo も Firefox に対して同じような思いがあって始まったと思う。だからスタート地点は、少なくともハイレベルには似ている。Flutter は Web 標準 … つまり仕様が複雑すぎるとみなし、それを捨ててみることにした。Servo は Gecko … つまり実装が複雑すぎるとみなし、それを捨ててみることにした。そんな双対がある。
個人的に Dart はまったく好きでないし Android アプリ開発者としてクロス OS のフレームワークにも興味がないけれど、傍目から見たプロジェクトとしての Flutter はまあまあ成功したと言えるんじゃないだろうか。同じ用途だとたぶん React Native の方が人気とはいえ、二番手くらいにはつけている。インターネットのレビューとかを読む限りでは採用した開発者は概ね満足しているようだし。なにより Flutter の開発チームはクビになっていない(と思う。Google でプロジェクト失敗に伴うクビがあるのかよくわからないが)。
リライトの引力
とはいえこう比べてみると Servo を失敗と呼ぶことへの抵抗も強くなる。Servo は Rust を生み出した。ソフトウェア産業への Rust のインパクトは Flutter よりずっと大きい。Rust に問題があるとすれば当初のスポンサーである Mozilla の助けにならなかったことだが … まあそういうこともあるじゃん。そういえば Netscape Navigator の書き直しも似たようなもので、会社 (Netscape) は潰れたけどその遺産 (Firefox) は人類に貢献した。もっというと Mozilla をクビになった Rust / Servo の開発者達は、プロジェクトに参加した自分の判断を後悔しているだろうか? 当時の Netscape 社員たちは? とてもそうは思えない。巨大ソフトウェアのリライトという野心的なプロジェクトは失敗の可能性も織り込んでいたはず。だから大局的には、星が揃わず博打が外れた、ただそれだけの話じゃないんだろうか。「ただそれだけ」で失業はちょっとイヤだけど。
こうして古き良きリライトのかっこよさが自分の中のリファクタリングの正しさに影を落としている今日この頃ですが、皆様いかがお過ごしでしょうか。