
2026/06/22 1:08
誤った抽象化より重複を(2016)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
開発者にとって最も重要な点は、コードを複製することが誤った抽象化を作成することよりも遥かに安く、安全であるということです。共有されたロジックが保守しづらくなったら、最適な解決策は通常、人工的な組織化を強制するのではなく、その具体的な呼び出し元にコードをインラインに書き戻すことです。このアプローチは、複雑さが増しても頑固に陳腐化した構造を維持しようとするプログラマーが見せる「沈没コストの罠」という現象に逆らいます。条件付け過多の冗長な手続き——不要な引数や if 文で混雑した肥大化関数——を取り除くことで、開発者はよりシンプルで回復力の高いソフトウェアを作り出します。もしコードが要件を満たすために引数を追加したり、条件分岐を追加したりする必要があれば、その抽象化は正しくありません。最も速い進め方は通常、「後退」ではなく「後方へ戻ること」です。この哲学を裏付けるかのように、著者は RailsConf 2014 で人気となった講演を拡張リソースとともに再公開し、書籍シリーズ「99 Bottles of OOP」の第 2 版をリリースしました。新刊は約 50% 長く、3 つの新たな章と、Ruby、JavaScript、PHP のそれぞれの独立した本が含まれています。これらは、様々な飲み物テーマにちなんで命名された各エディションで、ePub、PDF および他の形式で利用可能であり、これら資源により、悪質な抽象化よりも複製を優先するという重要なレッスンをより幅広い聴衆がアクセスできるようになりました。
本文
「誤った抽象化」への抵抗と進歩:沈没コストの罠から抜け出す方法
RailsConf 2014 の講演「すべて的小事なこと」で提唱した**「重複することは、誤った抽象化を作るよりもはるかに安くつく」**という考え方を再考します。 このアイデアに対し、多くの人々から「これこそ一万回も!」といった強力な共感と支持が集まりました。
1. 「誤った抽象化」が招く悪循環
一度作られた抽象化は、その存在自体に「正しい」という権威を持っています。しかし、要件が変わるにつれて以下のパターンが発生します:
- 重複の発見: プログラマー A がコード内の重複を見つけます。
- 新抽象化の作成: 重複に対処するために新しいメソッドやクラスを作成します(「コードは完璧だ」と思い込んじゃう)。
- 時間の経過と新要件: 新しい要件が現れます。元の抽象化では対応できず、「ほぼ完璧」な状態だったものが通用しなくなります。
- バリエーションの増加: プログラマー B が実装を担当し、すべてのケースに対応するために引数を追加したり、条件分岐を追加したりします。
- 複雑化への陥落: さらに新しい要件(プログラマー X など)が現れれば、さらに引数や条件分岐が増え、「while 繰り返す」ようにコードは理解不能になります。
なぜ変更したくないのか:沈没コストの罠
既存のコードには強力な影響力があります:
- 努力の保全: コードを作成するための労力や投資(インベストメント)を守るという動機が強力です。
- 無意識の囁き: 「これほど混乱しているのを正すのは時間がかかろう」「膨大な努力を無駄にするのは罪だ」という心理が働きます。
この結果、第 8 ステップのあなたが直面するのは、「既存のコードを変更して新要件を実装せよ」という圧力です。しかし、その試みは苛烈なものになります:
- コードは単一の抽象化ではなく、複数の漠然としたアイデアを埋め込んだ条件付き手続きになっている。
- 理解が難しく、壊れやすくなる。
2. 最速の前進は「後退」することです
このような状況(誤った抽象化)に直面した際、沈没コストの罠に引きずられそうになったら抵抗してください。 進むためには、実際には後退する必要があります。
具体的なアクションプラン
以下の手順でコードを整理し直します:
- インライン化: 抽象化されたコードをすべての呼び出し先へ埋め込み(インライン展開)、再び重複を導入する。
- 特定化: 各呼び出し先内部で、渡された引数に基づき、そのケースに必要な分のみを選択する。
- 削除: その呼び出し先に不要な部分は大胆に削除する。
これにより:
- 抽象化と条件分岐の両方を取り除く。
- 各呼び出し元は、実行されるべきコードだけに還元される。
この「巻き戻し」を行うと、表面的には共有された抽象化を呼んでいたにもかかわらず、実際に実行されていたのは意外にもユニークなコードだったことに気づきます。古い抽象化を完全に削除した後、再び出発点とし、重複を取り出して新しい正しい抽象化を作成し直すことができます。
失敗しないためのマインドセット
過去に、誤った抽象化のまま無理に進み続けようと努力しましたが、ほとんど成功しなかったケースがありました:
- 困難の蓄積: 新機能追加は極めて難しく、コードが複雑になり、次の追加をさらに困難にする悪循環に陥る。
- 視座の変化:
- 「このコードへの投資を守らねばならない」ではなく、
- **「このコードは一時期意味がありましたが、恐らくそこから学ぶべきことはすべて学んだでしょう」**と捉え直す。
現在の要件に基づいて抽象化を見直し許容した瞬間から、全てが簡単になります。インライン化した後、進む道は明確になり、新機能の追加も急速かつ容易になります。
3. 教訓
コードをシンプルに保つための心構え
- 沈没コストの罠に陥らないこと。
- 引数を渡したり、共有コードを通じて条件分岐を増やすことは、抽象化が誤っているサインです。当初は正しいとしても、その時はいくかもしれません。
- 誤った抽象化と認識した瞬間、最適な戦略は再び重複を導入し、正解を見極めるまで待つことです。
いくつかの条件分岐を蓄積して状況を洞察することはありますが、誤った抽象化を早めに放棄するほど痛みは減らせます。
結論
「抽象化が間違っている場合、最速で前に進む道は後退すること」です。 これは撤退ではありません。より良い方向への前進です。やってみてください。あなたの人生だけでなく、その後に続くすべての開発者の生活も改善されるでしょう。
ニュース:『99 Bottles of OOP』第 2 版リリース!
オブジェクト指向設計の教科書とも言える『99 Bottles of OOP』第 2 版がリリースされました!
今回の主な変更点
- 新章追加: 第 1 版に比べ、約 50% も長大な内容です。3 つの新章を収録。
- 言語不依存: テクニカルな内容は共通ですが、サンプルコードとして Ruby, JavaScript, PHP の 3 言語を使用しています。
- 多様なフォーマット:
- 言語バリエーション: Ruby 版 / JavaScript 版 / PHP 版(3 バリエーション)
- トーンバリエーション: ビール味 / ミルク味(2 バリエーション)
- 配布形式: epub / kepub / mobi / pdf(4 フォーマット)
合計 $3 \times 2 \times 4 = 24$ 種類の書籍が存在しますが、内容は全て同一です。購入者はこれらのオプションから自由に選択・ダウンロード可能です。