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

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

2025年8月30日原文(seangoedecke.com)

概要

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

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

  • ソフトウェア設計で重視すべきは「 最もシンプルな方法」の選択
  • バグ修正、既存システムの保守、新規アーキテクチャ設計の全てに適用可能
  • 多くのエンジニアが「理想的なシステム」を目指しがちだが、現状の理解とシンプルな解決策が本質
  • システム設計には多様なツール(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だけど、ハックはなし」って感じだね。

Hacker Newsで議論の続きを見る