/note/tech

The Wrong Abstraction

要約:

■ 1. 主張の概要

  • 「複製(duplication)は誤った抽象化よりはるかに安い」という命題を提唱
  • 「誤った抽象化よりも複製を選ぶべき」という指針を示す
  • この主張はRailsConf 2014での講演「all the little things」で取り上げ、大きな反響を呼んだ

■ 2. 誤った抽象化が生まれるパターン

  • プログラマAが重複コードを発見し、抽象化(メソッドまたはクラス)として切り出す
  • しばらく時間が経ち、新しい要件が追加される
  • プログラマBが既存の抽象化を保持しようとし、パラメータと条件分岐(conditional)を追加して対応する
  • さらに新しい要件が来るたびに、別のプログラマが同様の変更を繰り返す
  • 結果としてコードは条件分岐だらけの難解な手続きとなり、理解も修正も困難になる

■ 3. 既存コードが及ぼす心理的圧力

  • 既存のコードは「正しく、必要なものだ」という強い影響力を持つ
  • コードは過去の努力の産物であるため、その価値を保持しようとする動機が生まれる
  • コードが複雑であればあるほど「多大な労力をかけたはずだ、無駄にしてはならない」という感覚が強まる
  • これは「サンクコストの誤謬(sunk cost fallacy)」に相当し、判断を歪める要因となる

■ 4. 解決策:「前進するための最短路は後退すること」

  • 誤った抽象化に直面した場合、サンクコストに引きずられず、後退(巻き戻し)を選ぶべき
  • 具体的な手順:
    • 抽象化されたコードを、呼び出し元すべてにインライン展開して複製を再導入する
    • 各呼び出し元において、渡されているパラメータを基に実際に必要なコードの範囲を特定する
    • 各呼び出し元で不要なコードを削除する
  • この作業により抽象化と条件分岐の両方が除去され、各呼び出し元は必要なコードだけを保持する
  • 旧抽象化を完全に取り除いた後、現行要件に即した形で改めて重複を分離し、新たな抽象化を導出できる

■ 5. 実践的な教訓

  • 「この投資を守らなければならない」から「このコードから学べることはすでに学んだ」へ視点を切り替えることで、作業が容易になる
  • インライン展開後に前進の道筋が明確になり、新機能の追加が速く容易になる
  • パラメータを渡したり、共有コードに条件分岐を追加しているなら、それは抽象化が誤っているサイン
  • 誤った抽象化を早期に廃棄するほど、損失は少なくなる
  • 後退は撤退ではなく、より良い方向への前進である

■ 6. 付記: 99 Bottles of OOP 第2版リリース

  • 99 Bottles of OOP の第2版が新たにリリースされた
  • 第2版の変更点:
    • 3章追加され、全体量は第1版比で約50%増量
    • Ruby、JavaScript、PHP の3言語で個別書籍として提供(内容は同一)
    • 「ビール」と「牛乳飲料」の2バリエーションが存在
    • epub、kepub、mobi、pdf の4フォーマットで配信
    • 合計6種類の書籍、24通りのダウンロード組み合わせ
  • 1回の購入でいずれのバージョン・フォーマットもダウンロード可能