コードの汚さと経営合理性についてのひろゆき氏の問いにどう答えるのが正解か?

2024/09/19に公開

先日2ちゃんねるやニコニコ動画の創業メンバーとして有名なひろゆき氏が以下のようなツイートをしてエンジニア界隈で話題になりました。

https://x.com/hirox246/status/1836333134519885898

このツイートに対しては大量の引用リプライがついていてスパゲッティコードで同僚や後続が多大な迷惑を被るという批判的な意見もあればエンジニアも経営者目線やアントレプレナーシップを持つべきだという肯定的な意見もありかなりの盛り上がりを見せていました。

一方、私はこのツイートを見たとき、その内容自体はシンプルで、賛成・反対のどちらの意見もすぐに思いつきました。しかし、いざ言及しようとすると、このツイートに対して「自分にとって」どう答えるのが正解なのかを判断するのがかなり難しいと感じました。

ひろゆき氏の問いに答えるのはなぜ難しいか?:経営サイド vs 開発者コミュニティ

この問題に言及するのが難しいのは、労使問題のように、エンジニアリング組織内での自分の立場と切り離せないポジショントークの問題が絡むからです。

まず経営の観点からいうと、Facebookの「完璧を目指すよりまず終わらせろ」の格言にもある通り、サービスがまだ成功を収めていない段階ではこうすれば良いという正解の具体的なイメージを持ったエンジニアがとにかく手早く新バージョンやプロトタイプをリリースし成功に辿り着くことはとても重要です。また、「文句」をブツクサ言いながら働くことはみっともない ことであり、ビジネスよりもエンジニアコミュニティでのウケを優先した技術的選択やリファクタリングに半年時間をよこせというようなエンジニアのエゴイスティックな要求を拒絶する必要が経営サイドにはあります。

しかし開発者側の視点をみてみると、一般的に多くのエンジニアは製品が出来上がったあとに開発組織に参加しますので、既存の顧客に影響を与えずに先人が作ったダメなコードの直しやその上に新規の機能追加をさせられるというリスクのわりには報われない仕事からそのキャリアをスタートすることが多いです。ですので、ひろゆき氏的な意見にはそういった創業メンバーの尻拭いをさせられがちなエンジニアコミュニティの中ではヘイトを買いやすく、また、開発組織のトップにいる人間もそれを意識して(=仮に多少コードなんて汚くていいというような本音を持っていたとしても)それを言い出しづらいという構造があります。

ですので、この問題に対して有益な議論をするためには、経営サイドと開発サイドのそれぞれの観点から「ここだけは正しい」と言えるような事実を積み重ねていって妥協点を探る必要があります。

経営サイド側に立った意見:技術的負債を一切発生させずに成功した企業は存在しない

世界の主要なスタートアップ企業をみた場合、以下のように、起業の初期の段階では創業者が自分の頭の中にある製品イメージをとにかくはやく市場に出して検証するためにモノリシックで混沌としたコードが出されることが多いです。創業当初のコードやアーキテクチャのままスケーラビリティを獲得しそのまま成長している企業はほぼありません。

まず市場が求める正解みつけてから投資を募り、ビジネスを走らせながら徐々にシステムを改良していく、という順番は覆しようがないと言えるでしょう。

企業名 初期の実装 現在の実装
X(旧Twitter) Ruby on Railsのモノリシック構造:スタート時は迅速な開発のためRailsを使用し、短期間で機能追加が可能だったが、スケーラビリティに問題が発生。 Java/Scala ベースの分散型システム:現在は、Apache Kafka、Finagle(Scala)、Manhattan(内部開発の分散データストア)を用いてリアルタイムのデータ処理を行う大規模なマイクロサービスアーキテクチャへ移行。
Facebook PHP:初期は簡易なPHPスクリプトで構築。スパゲッティコードでスケーラビリティに難があった。 Hack (HipHop for PHP)、React、HHVM:PHPを高速化するためのHipHop(HPHPc)を経て、PHPの代替としてHackを導入し、HHVM(HipHop Virtual Machine)でパフォーマンスを向上。フロントエンドはReactに移行。
Shopify Ruby on Railsのモノリシック構造:開発初期からRailsを採用し、迅速なプロトタイピングと展開が可能だった。 Rails、Go、Kubernetes:現在もRailsが基盤だが、パフォーマンス向上のためGoを利用したサービスや、Kubernetesでのコンテナ管理を採用し、拡張性を強化。
Wix PHP、Flash:初期にはPHPとFlashを使用してシンプルなウェブビルダーとしてスタート。 React、Node.js:フロントエンドにReact、バックエンドはNode.jsを使用
Netflix Java、MySQLのモノリシック構造:初期にはJavaで構築され、MySQLをデータベースとして利用。 Java、Node.js、Python、Microservices、AWS:現在は、マイクロサービスアーキテクチャで分散型システムに移行。クラウドプラットフォームはAWSを利用し、ビデオストリーミングはメディア専用のマイクロサービスにより実現。

開発サイドに立った意見:「きれいなコード」のための思い切った技術投資が莫大な利益を生むことがある

スタートアップは初期の段階で誤った技術選択をすることがありますが、その修正に時間を費やした結果、後に大成功するケースもあります。

たとえば、Notionは初期にフロントエンドの構築にGoogleのWeb Componentsを採用しましたが、技術的な限界に直面し、全員を解雇してReactを再選択するために会社をリセットしました。

https://blog.allstarsaas.com/posts/notion-interview-20201111

もしNotionの経営陣がReactに移行するリスクをとらず「読めないと文句を言う奴はいらない」といって後ほどフレームワークとしては敗北する運命にあるWeb Componentsでの開発に固執していた場合、Notionが現在のようなWeb画面での万能性や複数人がいじっても矛盾が発生しない一貫性を手に入れることは不可能であり、当然製品としても成功していなかったでしょう。

開発サイドに立った意見:テストと型安全は経済的利益を生む

ソフトウェアの仕様をコードに起こし改修を行っても既存の仕様との矛盾をきたしていないことを保証するテストコードへの投資は、システムの移植性と改良スピードを高め長期的に経済利益を生み出します。

たとえば、私がてがけているMAMORIOではRailsのテストカバレッジを80%以上に保つルールを設定していたおかげで昨年インフラをherokuからawsにまるごと移行する作業をわずか3ヶ月で行うことができ、それによってインフラコストが40%低下させることができました。

https://zenn.dev/iototaku/articles/7beb58415b042b

もしもシステムのテストコードを積み重ねておらず、ワンクリックでシステムのほとんどのアクセスとコードを検証できる体制が整っていなければ手動で全件テイストをおこなわなければいけないので移行にはより時間がかかっていたでしょう。

さらに、MAMORIO-Bizというサイトのフロントエンドのjavascriptのコードをtypescriptに置き換えさせる技術投資も非常にうまくいきました。MAMORIO-Bizは当初jsのReactJSとReduxの組み合わせでリリースされたのですが、変数の型が存在しないためそれによるバグが頻発していました。

しかし型によって関数からどのような種類の値が返ってくるかを保証してくれるTypescriptを導入するための期間を5ヶ月ほど設けた結果、バグに対象するためのデプロイの頻度は明らかに減り、また売上も増えました。

開発サイドに立った意見:初期の開発コストを短縮するために雑な選択をした結果即死することがある

COVID-19が蔓延していた2020年に日本の厚生労働省とデジタル庁がリリースしたCOCOAアプリはxamalinというiOSアプリとAndroidアプリを一挙に作ることができるクロスプラットフォームの開発フレームワークで作られていましたが、位置情報やBluetoothの仕様に大きな違いがあるをそれぞれの環境になれたベンダーに依頼せずに作ったことが当初から大きな疑問が持たれていました。
そして、2022年に、ほとんどAndroidの実機でのテストで実験が行われていないこととOSの仕様への無理解から4ヶ月も機能していない時期があったことがあきらかになるスキャンダルを発生させてしまいました。

https://www.nhk.or.jp/politics/articles/feature/53380.html

クロスプラットフォームはモバイルアプリの開発でイニシャルの開発コストを短縮するためによく経営再度から提案される選択肢ですが、iOSとAndroidは異なる設計思想に基づいており、スピードを意識して少人数で行うために両者の違いを隠蔽するクロスプラットフォームを採用した結果思わぬ事故を起こすことがあります。

開発サイドに立った意見:初期の雑なセキュリティ設定を放置してると即死することがある

また、セキュリティに関連するコードを雑にあつかうことも大きなリスクがあります。
2023年に発生した位置情報アプリNauNauのケースでは、naunauはzenlyが終了したあとにそのかわりとして登場し成功した位置情報SNSでしたが、firebaseの権限まわりを雑に扱った結果200万人以上の位置情報が他人に見えてしまうセキュリティ事故を起こし、そのままサービス終了となってしまいました。

https://www3.nhk.or.jp/news/html/20231021/k10014232891000.html

DBやAPIのアクセス権限の制御は非常に面倒ですが、Webサービスはリリースした瞬間に全世界に公開されますので、セキュリティーファーストのアプローチをとらないと破滅的事故を起こす危険性があります。

まとめ:即死系の地雷を避けつつのびのびとコードを書こう

たとえばひろゆき氏が汚いコードの例として挙げたあるforループの中で作られたインスタント変数をグローバル変数に格上げしてしまうような問題は現代の開発環境では多くの場合対処可能です。
リンターや型や開発フレームワークが無秩序なコードを抑制し、また高度なエディタやAIツールがコードを読み解くのをかなりの程度助けてくれます。
また、スタートアップの初期段階では、製品のビジョンを持つ創業メンバーが作る初期コードと、市場フィットを達成した後に必要となる最適化されたコードとの間に差異が生じるのは避けられない現実です。この構造的な問題は今後も続くでしょう。

しかし一方で、ソフトウェア開発の世界には長年の経験と知識の蓄積があり、それらを用いないで見えている地雷を回避しないのは非合理です。
特に、私個人の印象では

アプリ >> フロントエンド >>> DB >>>バックエンド

という順番で取り返しのつかない技術的負債を生み出す罠が多いように思います。

ですので、開発の初期段階では開発者コミュニティのあいだで薄ぼんやりと共有されているような共通見解を参考にして適切なフレームワークやツールを選択しつつ、まずは市場で結果を出せるプロダクトをいち早くリリースすることに全力をかけ、ある程度成功を収めることができてからは積立投資のようにテストカバレッジをあげていき、プロダクトの成熟期に移植性の向上やリリース速度の速さといった果実を得るという風にすればいいのではないかなと思います。

Discussion