世界を動かす技術を、日本語で。

最もシンプルな方法を試してみよう

概要

  • ソフトウェア設計では「最もシンプルな方法」を常に選択する重要性
  • 理想的な設計よりも現状理解とシンプルな解決策の優先
  • シンプルな設計は一見地味だが、本質的な優秀さを持つ
  • シンプルさの定義とその実践上の課題
  • 将来のスケールより現状の要件重視の設計方針

ソフトウェア設計における「最もシンプルな方法」のすすめ

  • ソフトウェア設計で重視すべきは「 最もシンプルな方法」の選択
  • バグ修正、既存システムの保守、新規アーキテクチャ設計の全てに適用可能
  • 多くのエンジニアが「理想的なシステム」を目指しがちだが、現状の理解とシンプルな解決策が本質
  • システム設計には多様なツール(app server, proxy, database, cache, queue等)の知識が必要
  • ツールを多用したくなるが、 本当の熟練者 は「引き算の美学」を実践
    • 武道映画の「動き回る初心者」と「静かな達人」の対比
  • 優れた設計は一見地味で、問題が「意外と簡単だった」と気付かされる体験
  • 例:UnicornはUnixのプリミティブを活用し、Webサーバとして最重要な保証をシンプルに実現
  • Rails REST APIもCRUDアプリに必要な最低限を「退屈なほど普通」に提供
  • これらは「すごいソフトウェア」ではなく「すごい設計」の例

シンプルな設計の実践例

  • Golangアプリにレートリミット機能を追加する場合
    • Redis等の永続ストレージでユーザーごとにリクエスト数を管理する案
    • しかし、まずは インメモリ で管理できないか検討
    • アプリ再起動時にデータが消えるが、本当に問題か再確認
    • そもそもエッジプロキシがレートリミットをサポートしていないか調査
      • 設定ファイル数行で済むなら、それが最適
    • 必要ならRedis等の永続ストレージを追加
  • 最初は「最もシンプルな方法」で構築し、要件が増えたときだけ拡張
  • YAGNI(You Aren’t Gonna Need It)の徹底適用

シンプル設計の課題と誤解

  • 常に「最もシンプルな方法」を選ぶ際の3つの課題
    • 将来要件を見越さないことで柔軟性のないシステムやスパゲッティ化の懸念
    • 「シンプル」の定義が曖昧で、結局「良い設計をしろ」と同義になりがち
    • 「今だけ動く」システムでなく、スケール可能な設計が必要という反論

スパゲッティ化(Big Ball of Mud)への反論

  • 「シンプルな方法=小手先のハック」と誤解されやすい
  • ハックは 本質的に複雑 で、覚えておくべきことが増える
  • 適切な修正(proper fix)は、理解が必要だが結果的にシンプル
  • 「最もシンプルな方法」へ到達するには複数案の比較検討が必要で、 本当のエンジニアリング が求められる

シンプルさの定義

  • シンプルなシステムの特徴
    • 動く部品」が少なく、考慮すべき要素が少ない
    • コンポーネント間の結合が弱く、インターフェースが明確
    • 例:Unixプロセスはスレッドより結合が弱く、UnicornはPumaよりシンプル
  • ただし、全てのケースで「どちらがシンプルか」は判断が難しい
    • インメモリ vs Redisの例
      • インメモリは新規インフラ不要でシンプル
      • Redisはレートリミット保証が明確でシンプル
    • 判断基準:「 シンプルなシステムほど安定
      • 維持コストや運用負荷が少ない方がシンプル

スケーラビリティへのこだわりは不要

  • 「インメモリはスケールしない!」という反論に対して
  • 「最もシンプルな方法」は今のスケールに合わせて設計
  • 将来の大規模化を見越した過剰設計は多くの場合 無駄柔軟性の低下 を招く
    • 実際、どこがボトルネックになるかは運用しないと分からない
    • 2倍、5倍程度のスケールまで対応できれば十分
  • 過剰な独立性や分割は、逆に機能実装を難しくし、分散トランザクション等の難問を招く
  • ほとんどの場合、複雑な分散設計は不要

良い設計のための心構え

  • システムの現状把握自体が難しく、 正確な全体像 を掴むのが設計上の最大の課題
  • 多くの設計はこの理解不足のまま進み、結果的に良い設計にならない
  • ソフトウェア開発には2つの方法論
    • 将来要件を予測し、最適なシステムを設計
    • 現状要件に最適なシステムを設計=「最もシンプルな方法」
  • 複雑な機能の相互作用が増えるほど、 シンプルなアーキテクチャの重要性 が増す

謝辞・参考

  • 「最もシンプルな方法でやる」という表現はWard CunninghamとKent Beckによるもの
  • Rich Hickeyの講演「Simple Made Easy」も参考
  • Unicorn, Puma, Redis, Golang, Rails REST API等の具体例
  • 複雑さの管理には「シンプルさ」が最優先設計原則

Hackerたちの意見

「すべてはできるだけシンプルにすべきだが、シンプルすぎてはいけない。」これを早くから目指してきた私にとって、この記事が見落としている問題は、みんなが話しているさまざまな技術を知らないことだと思う。必要だと感じたことがなかったから。何か必要なものを見逃しているのか、それとも多くの人が騙されるような不必要な複雑さなのか?実際のプロジェクトでこれらを試して学ぶのは避けたい。自分の学びのためにシステムに不必要な複雑さを加えたくないから。以前、そういうことをする人と一緒に働いたことがあって、ほんとに悪夢だった。でも、実際のプロジェクトがないと、何かをしっかり学ぶのは難しいし、鋭い部分を見つけるのも大変だ。

そうなんだよね、私は(ほぼ)この悪夢を生きてる。上司が新しいソフトウェアにすごく興味を持っていて、役に立つかもしれないから、よく「ちょっと見て、役に立つかどうか確認して」って言われる。ああ、先週の釣りの予定も入れつつ、請求番号なしでこの釣りの予定も入れさせるのか…

確かに、これは厄介な問題だよね。私もよく感じる。これが履歴書主導の開発につながるんだ。私はそれを避けるために本当に頑張ってる。

すごく共感できる気持ちだな。こういう記事はすごく納得できるし、シンプルさを大切にして早まった最適化を避けようとしてるけど、実際にはそれが称賛されるシンプルさなのか、ただの経験不足やスキル不足なのか全然分からないことが多い。

最初は手作業ででも、動く最もシンプルなものを実装するべきだよ。「全体」をやるツールを追加する必要がないときにね。最終的には、予想していなかったニーズからもっと多くのものを追加することになるかもしれないけど、それでもいい。もし「全体」をやるツールを作っているけど、逆に悪化しているなら、実際に「全体」をやるツールを使うべきだってことがわかるよ。最初からそのツールを使わなかったことで時間を無駄にしたのかな?これはほぼ哲学的な質問だね。今、何が必要かがわかっているし、もし必要なかった場合に避けるチャンスがあった。おそらく10回中9回は正しい判断ができるだろうね。

キャリアの中で一番議論になったのは「動く」という定義についてだ。「動くからといって壊れていないわけではない」という言葉は、物理的な世界でも器用な人には響くけど、多くのソフトウェア開発者にはピンと来ないみたい。どんな職人も、壊れた道具を使って修理することがある。新しいのを買うべきだと分かっていて、次の機会に言い訳をして買う人も多い(ハードウェアストアに行くとか、セールの時に)。たぶん、10人中8人くらい。ソフトウェアの場合は、同じ努力をするのは1人くらいだと思う。

そういう会話は仕事の重要な部分だよ。例えば、何かが「動く」と同意できることもある。今のところ望む結果を得るために使えるけど、いろんな面でうまく機能していないこともある。信頼性がないか、すごくコストがかかるかもしれない。

ネットのどこかで見つけたこの言葉: > 「プログラムが動くのは十分ではない。それは正しい理由で動かなければならない。」 これって、違う角度から見た同じことだと思う。

「動く」という定義は、雇い主がそのリソース(私が働いている時間)を修正に使いたいかどうかに依存するんだ。もし彼らがそのリソースを使って品質を優先したいなら、私も品質を優先するよ。逆に、ただメトリクスを達成してチェックボックスを埋めたいだけなら、それでも全然構わない。測定したものが得られるからね。何を測るべきかについて意見を言うのは構わないけど、その決定を下すのは私じゃないんだ。

キャリアの中で最悪な時期の一つは、プロトタイプを作るのが好きなチームがいる会社でのことだった。彼らは急いで概念実証を作って、上司がそれを役員の前で披露するんだ。どこかに展開されて、小さなデータベースに接続されるから、実際に試してみると「動いてる」ってことになる。役員たちは、こんなに早くできたことに驚くんだよね。プロトタイプチームはそれを別のチームに引き渡して、次のプロトタイプに移る。引き継いだチームはプロジェクトを開いてみると、実際には動作するサイトじゃなくて概念実証だったってことに気づく。セキュリティやバリデーション、エラーメッセージなど、オンラインにする前に必要な基本的なことが全然含まれてないんだ。だから、今それを持っているチームはしばしば完全にやり直さなきゃいけなくて、他の製品で使われている構造の中で作り直すことになる。役員たちは、自分の目で「動いてる」のを見たから、展開チームがただ面倒にしてると思って怒るんだよね。

こういうアドバイスの皮肉なところは、すでにたくさんの経験を持っていて、それを適用する判断力がある人にとっては最適だってこと。例えば、「最もシンプルなこと」をどうやって知るの?それが「うまくいく可能性がある」とどうやって確信できるの?昨日、私が自分で書いたXLSXインポーターに問題があった(理由は聞かないで)。XML名前空間を正しく扱うのを忘れていて、Excelは常にデフォルトの名前空間でファイルをエクスポートするから。そしたら、すべての要素に名前空間を追加したファイルが来て、インポーターがすぐに壊れた。例えば、Excelは常に出力するけど、このファイルは。 「うまくいく可能性がある最もシンプルなこと」は、名前空間のプレフィックスを削除して、衝突する名前がないと仮定することだった。でも、それをするのは気が引けた。たぶんうまくいっただろうけど、将来の自分に地雷を残すのが心配だった。だから、4時間かけてすべてのパースコードを書き直して、名前空間を正しく扱うようにした。私の選択に賛成かどうかは別として、「うまくいく可能性がある最もシンプルなこと」をするのはそんなに簡単じゃない。でも、経験が増えれば増えるほど簡単になる。もちろん、その頃にはこのアドバイスは必要ないかもしれないけど。

仕事では、「間違った方向に」コードを追加しないという追加の注意を持ってこの問題に取り組んでいる。だから、部分的な実装を持つのは全然問題ないし、むしろ望ましいこともある。より完全な実装が向かう方向に進んでいる限りね。基本的には「KISSだけど、ハックはなし」って感じだね。

AIのバイブコーディングでも同じことが言えるよ。経験が多いほど、エージェントを正しい道に導くのが簡単になる。どのタスクにエージェントを使うべきか、自分でやるべきかを見極めるのも同じことだね。

この種のアドバイスの皮肉なところは、すでに多くの経験を持っていて、それを適用する判断力を持っている人にとって最適だということだよね。たとえば、「最もシンプルなもの」が何かをどうやって知るの?著者もこれに触れてると思うけど、「最もシンプルな解決策を見つけるには、いろんなアプローチを考慮する必要がある。言い換えれば、エンジニアリングをする必要がある。」

ここでコメントしてるほとんどの人が、「最もシンプルなこと」をするってのは、ハッキリ言って雑で早いことをするって意味じゃないってことを見落としてると思う。シンプルなことは、実はすごく難しいこともある。考えたり、システムを理解する必要があるんだよね。彼が最初に言ってることでもあるけど。でも、ほとんどの人は見出しを読んで、個人的な不満をぶちまけ始めてる気がする。

いい加減さとシンプルさを混同しないで。XMLをregexで解析すること(または非名前空間準拠のXMLパーサーを使うこと)はシンプルじゃない。ごちゃごちゃしてて、冗長で、エラーが起きやすくて、全くイディオマティックでもシンプルでもない。もし、意図通りに準拠したXMLパーサーを使っていれば、ファイル内で異なる名前空間のエンコーディングが発生していることに気づかなかったかもしれない!パーサーにこれを任せると、HTML(またはXML)を正しく解析すれば、&などに気づかないのと同じように、全く「気にならない」んだ。小さなファイルでテストするから最悪の方法になるけど、XLSX処理のカスタムコードは大きなファイルを一括インポートするために使われることが多く、時々この分割を使うことがある。生産環境では大きなデータブロックを静かに失うことになる!それはトラブルシューティングするのが楽しくない(またはシンプルじゃない)。速くて楽な道は、System.IO.Packagingみたいなものから始めることだよ。これはOpen Packaging Conventions (OPC) コンテナフォーマットのための.NETの組み込みライブラリで、すべてのOffice Open XML (OOXML)フォーマットの基盤となるコンテナフォーマットなんだ。組み込みのXMLパーサーを使えば、名前空間をうまく扱える。唯一の面倒な点は、OOXMLフォーマットが使える名前空間のグループが2つあること、Microsoftのものとオープンな「標準化された」ものがあることだね。

この表現の起源についてプログラミングの文脈で触れていないのは残念だね。これはウォード・カニンガム(ウィキの発明者)が、ケント・ベックとの仕事の中で生まれたものなんだ。数年前のDr. Dobb'sのインタビューで、彼らが80年代後半に一緒にコーディングしていたとき、互いにその原則を思い出させ合っていたって言ってた。最終的には、彼らのトークや著作の定番になったんだよ。この記事で触れられている制約についても彼らは認識していた。彼らが挙げた例は、閉まったドアに直面することだった。最も簡単なことはハンドルを回すことかもしれない。でも、ドアがロックされていたら、最も簡単なことは鍵を探すことになる。もし鍵が失くなっていると知っていたら、最も簡単なことはドアを壊すことかもしれない。記事が言うように、最も簡単なことを見つけるのは必ずしも簡単ではないんだ。彼らはこのアプローチが技術的負債(カニンガムが作った用語)を生むことを理解していたけど、短期的にはコードを動かすことがその懸念を上回っていたんだと思う。この技術的負債の側面には触れておくべきだったと思うよ。

これが一番上のコメントになるべきだね。

ケント・ベックはエクストリームプログラミングを正式にまとめたんだ。これは、要求が変わる中でシンプルなシステムが進化するための実践の集まりだよ。

ウィキの発明者 その例を挙げてくれて面白いね。初めてウィキを使う前は、Lotus Notesを使ってチームフォルダーでプロジェクトを整理してた。Notesが最後に読んだ時から更新されたドキュメントをハイライトしてくれるのが好きだったんだ。次のプロジェクトでは、そのチームがウィキを使ったんだけど、シンプルすぎて、どのドキュメントが更新されたのかがわからなかったから、結局役に立たなかった。人々は新しいプロジェクトデザインをウィキに入力したけど、更新されたページがどれか一目でわからないから、誰も見なかった。シンプルすぎたんだよね。

一般的に言って、こういうことを言う人を聞くと、すごく警戒するね。実際、ソフトウェア開発について広範な主張をする人がいると、すぐに疑いの目を向けちゃう。彼らは何も分かってないか、嘘をついてるか、その両方だと思う。ソフトウェア開発の経験が豊富になればなるほど、結局のところそれは難しくて、注意と熟慮が必要だってことが分かる。万人に合うアドバイスなんてないよ。私が見たいのは、オープンマインドで考え深い人たちなんだ。

うん、こういう気持ちには大体同意するかな。こういう一般的な意見って、あんまりニュアンスがなくて、文脈を考慮してないことが多いよね。でも、聞いてる人も考えないとね。J2EEを使いたいと思う人たちって、当時のイベントソーシングやセマンティックウェブとかに興味がある人たちだから。これはその逆を言ってるんだよね:デフォルトで複雑さを増やさないようにしようって。シンプルな解決策に偏った方が、複雑すぎるものよりもずっといいと思う。ダン・マッキンリーが言ってた「退屈な技術を選べ」っていうのもそうだし。もちろん、基本的にはそれが正しいけど、業界の多くの人は逆のことをやってるみたいで、新しいものを作ることで評価されると思ってる。俺もキャリアの中で、過剰に賢い開発者の悪いアイデアを解消するのに多くの時間を費やしてきたよ。時にはその賢い開発者が自分だったりもするしね!だから、確かにこれは一般的すぎる意見で言う必要はないんだけど、シンプルなアプローチで済むところを過剰に設計しちゃう人が多いから、やっぱり役に立つんだよね。

記事の一部には最初はイライラしたけど、「ハック」はしばしば隠れた複雑さを追加するって指摘してるから、トレードオフについての明確さはあるよね。問題は、見出しを繰り返すことなんだけど、「シンプルなことをやるだけでいい」っていうのが経営陣から強制されると(技術的かどうかに関わらず)、シンプルさを保つことにストレスがかかるんだ。複雑な問題に対してそれを実行しようとすると、簡単にハックに頼ることになって、それが移転しにくい知識になっちゃう。良いデザイン(最初は複雑に見えたもの)ではなくてね。逆に、「不必要な複雑さ」は、計画が悪いプロジェクトから来ることが多いと思う。人々は、野生の要求に対処するためにハックを追加し続けることに苦しむうちに、結局オーバーデザインになってしまう。そうして、そのエリアでは複雑さが解消されず、次のエリアでまた厄介なハックが必要になって、安定したエリアを設計しようとするとそのサイクルが繰り返される。だから、開発者としては、どんなに退屈でも、私たちのデスクに降りかかることが決まる会議に参加する必要があるんだ。

君の言いたいことはわかるけど、極端に言えば、結局「すべてはトレードオフ」か「タダ飯はない」ってことになっちゃうよね。業界で蓄積した経験を形式化して、新人に教えるためには、ある程度の一般化は必要なんだ。明らかな問題は、なぜか慎重に適用すれば役立つ概念やパターンがカルト化すること(クリーンアーキテクチャやクリーンコードを考えてみて)。これが最終的には業界を悪化させるんだ。たとえば、クリーンアーキテクチャやポートとアダプター、ヘキサゴナルなどは、一般的には非常に理にかなった実用的なアイデアだと思う。でも、なぜかすべての戦いはフォルダの名前をどうするかに集中してる。

これが赤信号だとは全く思わない。むしろ、私にとっては大きなグリーンフラッグだよ。最も簡単なことは複雑なシステムを作ることだから、シンプルなものを作るのは難しいんだ。

シンプルさ(複雑さの逆)は、ソフトウェアで何かをする二つの方法を考えるときに、通常は最も重要な要素だよ。なぜなら、それは人間が考え、提案し、合意し、作り、維持しなきゃいけないから。残念ながら、シンプルさは複雑なんだ。業界の平均的なエンジニアは、二つのデザインのどちらがよりシンプルかを判断するのが信頼できない。さらに、「シンプルさ」という主張は、みんなが口にするようになってしまった。だから、同僚が自分のアプローチに疑問を持つと、すぐに「これがシンプルだ」と返すようになってしまう。もっと長くて、誠実で、正しい議論に対してね。理想的にはチームリーダーが状況を見極める手助けをするべきだけど、最近はチームリーダーがあまり有能じゃないことが多くて、シンプルさは彼らにとって信頼できるサインを出すには複雑すぎるテーマなんだ。彼らは波風を立てたくないから、作業をしている人に判断を任せることが多い。チームがその複雑さを背負うことになるんだ。

記事から……「真の習熟は、より多くをするのではなく、少なくするタイミングを学ぶことを含むことが多い。野心的な初心者と古い達人との戦いは、武道映画の中でよくあるクリシェだ。初心者は動きが速く、ひねりや回転を繰り返す。一方、達人はほとんど静止している。しかし、なぜか初心者の攻撃は決してうまく当たらず、達人の最終的な攻撃は決定的なものになる。」

一般的に赤信号だとは言えないけど… いつも余計な複雑さを加える人を見かけるし、日常的にシンプルに保つことを勧めてるかな。そうしないと、デザイナーやプロダクトマネージャー、顧客、建築家が自然に解決策に余計な複雑さを加えちゃうから、必要ないんだよね。

これはシンプルな領域ではうまくいくと思う。大手テックで働いていると、求められる複雑さに驚かされることが多い。最もシンプルなビジネスの問題でも、解決するのに1年かかることがあるし、驚くほど多くのエッジケースやスケールのせいで常に壊れてしまう。シンプルさを主張する人は、スケールで働いたことがないんだろうね。10年前のコードベースを参考にしたリライトでさえ、考慮すべきことが多すぎて失敗することが多い。クラシックな例として、チェスタートンのフェンスがある。「そのような場合には、ある制度や法律が存在する。簡単に言えば、道路に立てられたフェンスやゲートだ。より現代的な改革者は、陽気に近づいてこう言う。「これの用途がわからないから、取り除こう。」それに対して、より賢い改革者はこう答えるべきだ。「もしあなたがその用途がわからないなら、私は絶対にあなたに取り除かせない。離れて考えてきなさい。そして、あなたがその用途がわかると言えるようになったとき、私はあなたにそれを壊すことを許可するかもしれない。」」

著者はGitHubのスタッフエンジニアなんだ。彼らがスケールで働いたことがないとは思えないね。

半分以上の時間、複雑さはシステム自体から来ていて、組織構造やインフラの反響であって、要求や問題領域からではない。だから、このアドバイスは大体の場合有効だと思うよ。

君の言うことは間違ってないけど、問題の根源はドメインではなくて、悪いソフトウェアデザインかもしれないね。ソフトウェアのベースがトラップや意図しない副作用でいっぱいなら、問題の根源は関心の不明瞭な分離と密結合にあるんだ。もちろん、ある時点でリファクタリングはほぼ克服不可能なタスクになって、会社の文化が変わらなければ、君のリファクタリングが一つも実を結ぶ前に、さらにゴミが追加されることになる。信じてほしいけど、関心のクリーンな分離とシンプルなコンポーネントの組み合わせで複雑な問題を解決することは可能なんだ。ただ、うまくやるのは非常に難しいから、多くのプログラマーは試みもしない。だから、シニアの厳格なオーナーシップが必要なんだ(彼らもこの視点を支持しなければならない)。

俺は今、そんな企業の複雑さに深く関わってるけど、もっとシンプルで堅牢な方法でできたアイテムが山ほどあるのを常に目にしてる。シンプルなものは長期的な利点やメリットがたくさんあって、新しい人を育てるのも簡単だし、過剰に抽象化されたハイパー複雑なシステムよりもずっといい。リード開発者が自分のCVのために新しいものを試したいとか、退屈だからって理由でね。デバッグや移行、進化、一般的なメンテナンスが簡単で、純粋な開発者はあまり気にしないことが多いけど、シニアになると気にするようになるんだ。複雑な最適化は、極端なパフォーマンスや大規模な公共ウェブには確かに必要だけど、それが世界中のITの仕事の大半ではないんだよね。

前の仕事では、システムのリファクタリングや改善を試みた結果、失敗したり放棄されたりしたことが大きな複雑さを生んでいたんだ。もしそういうことが禁止されていたら、受け継いだシステムはもっとシンプルだったんじゃないかなってよく考えてた。もちろん、リファクタリングや改善を試みることは悪くないけど、自分の使い方に100%合うか、始めたことを予算内で終わらせられるか、そして各ステップの結果が前のものより良くなるように、段階的に進められるかを確認してほしい。

これの問題は、「スケールで」という言葉の意味について誰も合意できないことだよね。確かに、インターネット全体をインデックス化して、毎秒何万件も検索するなら、特有の課題があって、かなりの複雑さが必要だ。でも、もし毎秒10件のトランザクションしかないシステムなら…多分、そんなに複雑にする必要はない。シンプルな方法で十分うまくいくはずだし、ほとんどのシステムはそんなに忙しくなることはない。今のコンピュータは速いから!強力なサーバー1台(念のためもう1台)でかなりのことができるよ。

僕のエンジニアの上司はこれをマントラみたいに使ってた(彼は今、SpotifyのエンジニアリングSVPで、Comcastで一緒に働いてた)。ここで言いたいのは「まずは…」ってことだと思う。すべてのことをやらなきゃならないわけじゃなくて、必要ないことをやる時間を無駄にしないために、少しずつ始めようってこと。シンプルなことを全部集めると、最終的には複雑な巨大物になるかもしれないけど、そこに至るまでに無駄な時間をかけなかったことを願うよ。

要は、過剰設計しないことだね。これはスケールを無視したり、エッジケースを考慮しないことではない。必要かどうかわからないスケールのためにコードを複雑にするのはやめよう。現在の要件を満たす最もシンプルな方法を取るけど、依存関係を壊さずに新しい機能やスケールを追加できるようにコードを書くことが大事だよ。詳しくはGoogleのエンジニアリングプラクティスを見てみてね。

シンプルさを主張する人は、スケールで働いたことがない。ほとんどのプロジェクトはスケールで動いてないし。「スケールで」という前に、シンプルで書き換え可能なコードは常に進化する。なぜなら、それは密度が低く、広がりが少ないから。確かに、最もシンプルなコードと、コードを維持するために必要な段階的な抽象化の間にはバランスがある。スタートアップや中小企業、大手アメリカの航空会社とも働いたけど、エンジニアリングの複雑さは必要ないところで高すぎる。僕が見てきたプロジェクトではそうだった。もし君がメガコープのエンジニアなら、状況は全然違うかもしれないけど、そこは1%の話だよね。もっと少ないかもしれない。

これはソフトウェアエンジニア同士のコミュニケーションの誤解の典型だね。ここでのタイトルを見てもわかるけど、「可能な限りシンプルなことをやれ」って言ってる。問題が複雑な時に複雑さから逃れることはできない。もちろん、必要以上に複雑にすることはできるけどね。この文章のどこにも、複雑さを完全に避けられるとは書いてないけど、多くの人が理由もなく問題を過剰に複雑にしがちだってことは言ってる。

いくつかのスタートアップで0から1のシステムを作ってきた者として、最も大事な原則は「シンプルは堅牢」ってことかな。最初にシステムを過剰に設計するのは簡単だし、そのシステムの改善を過剰に設計するのも簡単だよね。顧客の要求は常に進化してるし、未来の要求がどうなるかなんて予測できない(できる気がしてもね)。この原則を分解すると、シンプルなシステムはエラーが少ないだけじゃなくて、シンプルなアーキテクチャは将来的に変更しやすいってことも同じくらい重要なんだ。X、Y、Zを計画するべき?もちろん、でも逆説的に言うと、将来のために扉を開けておいて、「可能な限りシンプルなもの」を作ることが大事なんだ。複雑さは制約を生むし、これらの制限は時間が経つにつれてスタックを脆くするから、どんなに良い意図で計画してもね。

これは良いアドバイスだけど、シンプルさが何を意味するのかを定義するのは難しいこともある。私が理解できた唯一の技術的な方法は、コードのエントロピーとスコープを減らすことを目指すことだった(言語モデルがソロモンオフ/コルモゴロフのエントロピーを最小化しようとするのに触発されて)。 https://benoitessiambre.com/entropy.html https://benoitessiambre.com/integration.html

「働く」って何かを知ってるなら、これは鋭い哲学だね。でも、特に人と接するシステムなら、たぶん分かってないよね。「うまくいく」って何を意味するかを理解するのは、最初から物を作るのと同じくらい難しい。二回作る覚悟を決めてもいいかもね。[0] [0] https://ratfactor.com/cards/build-it-twice

現在の要件に基づいて、最適なシステムを設計することが重要な実践的アドバイスだよ。仮定のユースケースのために設計を始めると、無限のデザインの複雑さを開いてしまうからね。実際に必要なことのために厳密な仕様を設定して、それを作ることで、少なくともデザインプロセスがシンプルになる。そういうマインドセットから始めれば、実装にもその考えが引き継がれることを期待できるよ。シンプルなものが常に勝つんだ。シンプルは繰り返し可能だからね。すべてのシンプルなものが勝つわけじゃないけど(使えないものや欠陥があるものも多い)、勝者はいつもシンプルなんだ。

現在の要件に基づいて、最適なシステムを設計することが重要だよ。でも、マネージャーに将来のシナリオA、B、Cに備えたいかどうか聞くのを忘れないでね。そして、後で参照できるようにその答えを書き留めておいて。