未来を形作るテクノロジーの深掘り記事。

良いソフトウェアに時間がかかる理由と急げない理由

最良のソフトウェアが数か月ではなく数年かかる理由。オープンソースからスタートアップまで、エンジニアリングにおける忍耐の価値を解説します。

木製のテーブルの上に置かれた開いたノートパソコンから育つ、丁寧に剪定された盆栽の木

Flaskが1.0に到達するまでに8年かかりました。SQLiteは2000年から活発に開発が続いていて、今でも意味のある改善が入っています。Linuxカーネルは30年以上の歴史がありますが、年を重ねてむしろ良くなっていると言ってもいいでしょう。一方で、VCの支援を受けたスタートアップに対する平均的な期待は、18か月以内に成果を見せること、できなければその理由を説明することです。

良いソフトウェアを作るのに実際どれだけ時間がかかるかと、私たちがどれくらいかかると期待するかの間には、年々広がるギャップがあります。素早くリリースすることへのプレッシャーそれ自体が間違っているわけではありません。しかしその結果、忍耐は野心の欠如と見なされ、長く生き残るプロジェクトは、地道に正しいことを積み重ねている数年間に「遅い」と片付けられてしまう文化が生まれています。

「一夜にして成功」の神話

ソフトウェアにおける「一夜にして成功」は、ほぼすべて長い前史を持っています。Reactは、オープンソース化される前にFacebookの社内で1年以上使われていました。Rustは1.0に到達するまでに7年間開発されました。PostgreSQLは1986年に研究プロジェクトとして始まり、2010年代に本番環境の定番データベースになるまで、実にほぼ30年にわたって静かに着実な改善を重ねてきました。

突然現れたように見えるものは、たいてい可視性の閾値を超えた改善の積み重ねの結果です。ソフトウェアは常に良くなり続けていました。人々が注目していなかっただけで、誰にも無視できないほど十分に良くなった時点で一気に知られるようになるのです。

Flaskの作者であるArmin Ronacherは、この点について直接書いています。Flaskは2010年のエイプリルフールの冗談として始まりました。それがほぼ偶然に本格的なプロジェクトになったのです。エッジケースの修正、ドキュメントの改善、APIの見直しといった地道な作業を何年も続けた結果、最も人気のあるPythonのWebフレームワークの一つになりました。どの年も無駄ではありませんでした。一年一年が基盤をより強固にしていったのです。

ソフトウェアには削りきれない時間の要素がある

人を増やしたり、もっと頑張ったりしても解決が早まらない問題があります。Fred Brooksは1975年のThe Mythical Man-Monthでこれを指摘しました。その核心的な洞察は今も変わっていません。ソフトウェア開発の特定の側面は、並列化できず逐次的に進めるしかないのです。

  • 問題領域の理解。しばらくその領域に身を置くまで、問題空間を完全に理解することはできません。どんなソフトウェアの最初のバージョンも、初期の前提が埋め込まれています。2番目のバージョンには、最初のバージョンから学んだことが反映されています。本当の理解には反復が必要で、反復には時間がかかります。
  • API設計と安定性。良いAPIは利用を通じて生まれます。真空の中で完璧なAPIを設計することはできません。実際のユーザーが実際のエッジケースにぶつかる必要があります。早々に1.0を出したライブラリは、初期の設計判断を何年も後悔することがよくあります。
  • エッジケースと堅牢化。機能の最初の80%は全体の時間の20%で完成します。残りのエッジケース、エラー処理、プラットフォーム固有の癖が、残りの80%の時間を占めます。この比率は怠慢ではなく、信頼できるソフトウェアを作ることの本質的な性質なのです。
  • コミュニティとエコシステム。ドキュメント、チュートリアル、プラグイン、質問に答えてくれるコミュニティが揃うまで、ツールは本当の意味で役立ちません。このエコシステムは人工的に作れるものではなく、時間をかけて自然に育つものです。

人工的な締め切りがもたらす害

「素早く動き、破壊せよ(Move fast and break things)」は、製品と市場の適合性を探していたソーシャルネットワークにとっては妥当な標語でした。しかしインフラ、開発者ツール、データベース、あるいは他人のシステムが依存するものには、最悪の哲学です。基盤となるソフトウェアを急いで作ると、壊れた影響は雪だるま式に膨らんでいきます。

有望なオープンソースプロジェクトが、基盤が支えられる以上の速さで成長しようとして崩壊するのを、私は何度も見てきました。そのパターンは予測可能です。プロジェクトが人気になり、メンテナは機能を素早く出すよう圧力を感じ、品質が落ち、コントリビューターは燃え尽き、ユーザーはより安定したものへ移っていきます。皮肉なことに、減速していれば、もっと遠くまで行けていたはずなのです。

長く生き残るプロジェクトは、最も速くリリースしたものではありません。早い段階で良い判断をしたため、後で全部書き直す必要がなかったプロジェクトです。

技術的負債は、ただ汚いコードの問題ではありません。時間の圧力の下で行われ、将来の可能性を制約する判断のことです。素早く出荷するためのあらゆる近道は、今後のすべての変更に課される税金のようなものです。近道の中には取る価値のあるものもありますが、それは意図的に選ぶべきであって、誰かが次の火曜日を締め切りだと勝手に決めたからではありません。

実践における忍耐とは

ソフトウェア開発における忍耐とは、意味もなくゆっくり進むことではありません。何を作るかについて慎重であり、物事にどれだけ時間がかかるかについて正直であることです。うまくいったパターンをいくつか挙げます。

  • 早くリリースし、コミットはゆっくり。フィードバックを得るために、ソフトウェアはすぐユーザーに届けましょう。ただし、安定版APIとして約束する内容は非常に慎重に選んでください。0.xのバージョニングを惜しみなく使い、変更があり得ることを明確にしておきましょう。
  • 機能追加にはノーと言う。追加するすべての機能は、永久に保守し続けることになる機能です。最良のプロジェクトは、スコープについて明確な意見を持っています。SQLiteは、決してやらないことを明示的に挙げています。その規律こそが、世界で最も広くデプロイされているデータベースである理由なのです。
  • 基礎に投資する。ドキュメント、テスト、エラーメッセージ、パフォーマンスは派手ではありませんが、積み重なっていきます。ドキュメントが充実し、堅実なテストスイートを持つプロジェクトは、1年目にドキュメントが不十分なプロジェクトが進められる以上の速さで、3年目に前進できるのです。
  • メンテナのエネルギーを守る。燃え尽きはオープンソースプロジェクトを殺す最大の要因です。持続可能なペースは、スプリントの速度よりも大切です。週に20時間の集中した作業を5年間続けるメンテナは、週80時間を半年間働いて姿を消すメンテナより、多くのものを出荷します。

スタートアップのスピードの罠

スタートアップには正当なジレンマがあります。生き残るためには素早く動く必要がある一方で、動きすぎると、規模が大きくなるにつれて負債となる脆いシステムを生んでしまいます。これをうまく乗り切る企業は、2種類のスピードを区別する傾向があります。

反復のスピード。アイデアをどれだけ速く検証し、ユーザーからフィードバックを得て、方向転換できるか。これは最大化すべきものです。短いサイクル、素早いプロトタイピング、そして何かを捨てることを厭わない姿勢。

コミットメントのスピード。アーキテクチャの判断、公開API、データモデルをどれだけ速く固定するか。これは最小化すべきものです。可能な限り可逆性を保ちましょう。取り返しのつかない判断を先延ばしできるほど、最終的に決めるときにより多くの情報が手元にあります。

多くのスタートアップの過ちは、この2つを混同することです。機能の反復と同じ速さでアーキテクチャにコミットしてしまい、その後の2年間は時期尚早な判断の代償を払い続けることになるのです。

生き残ったプロジェクトから学ぶ

私たちが最も頼りにしているソフトウェアプロジェクトには、共通の特徴があります。それは、どれも一度は「遅い」と見なされていたことです。MySQLが手っ取り早く動く選択肢だった一方で、PostgreSQLは地味な選択肢でした。Pythonは「遅すぎる」と言われ、Perlが実用的な選択でした。Gitは普通の人間が使えるようになるまで何年もかかりました。

これらのプロジェクトが持っていたもの、それは時間でした。間違いを犯し、そこから学び、堅実なものを築く時間です。1年目から誰にでも何でも応えようとはしませんでした。中核となる目的で卓越することを目指し、その卓越さに必要なだけの時間をかけることを厭わなかったのです。

次に「プロジェクトに時間がかかりすぎている」とイライラしたときには、あなたが最も頼りにしているもの、たとえばOS、データベース、言語ランタイム、バージョン管理は、どれも誰の予想よりも長くかかったことを思い出してください。だからこそ、それらは機能しているのです。

ものには、ただ時間が必要なのです。最善の対応は、その現実と戦うことではなく、それを前提にしたシステム、チーム、期待値を築くことです。