「リファクタリング:Rubyエディション」めも

リファクタリング:Rubyエディション

リファクタリング:Rubyエディション

だらだらとスパゲティなコードを書いてしまう私には非常にありがたい本。
「いつメソッドにまとめるか」「メソッドの名付けをどうするか*1
などコードを書くときに悩む事柄の解法が書いてある。
なお、
たのしい開発 スタートアップRuby

たのしい開発 スタートアップRuby

では、入門書の次に読むべき本としてこの本と
メタプログラミングRuby

メタプログラミングRuby

とが挙げられていましたが、この2冊でも「リファクタリング:Rubyエディション」を先に読んだ方が良いのではないかと思います。この本はRubyの教科書の延長上にありますが、「メタプログラミングRuby」は本当に魔術書なので。

目次

ひとまず実際のリファクタリング項目名が列挙されている目次を載せておきます。いずれこの目次にまとめを追記していきたいと考えています。

第6章 メソッドの構成方法
6.1 メソッドの抽出(Extract Method)
6.2 メソッドのインライン化(Inline Method)
6.3 一時変数のインライン化(Inline Temp)
6.4 一時変数から問い合わせメソッドへ(Replace Temp with Query)
6.5 一時変数からチェインへ(Replace Temp with Chain)
6.6 説明用変数の導入(Introduce Explaining Variable)
6.7 一時変数の分割(Split Temporary Variable)
6.8 引数への代入の除去(Remove Assignments to Parameters)
6.9 メソッドからメソッドオブジェクトへ(Replace Method with Method Object)
6.10 アルゴリズム変更(Substitute Algorithm)
6.11 ループからコレクションクロージャメソッドへ(Replace Loop with Collection Closure Method)
6.12 サンドイッチメソッドの抽出(Extract Surrounding Method)
6.13 クラスアノテーションの導入(Introduce Class Annotation)
6.14 名前付き引数の導入(Introduce Named Parameter)
6.15 名前付き引数の除去(Remove Named Parameter)
6.16 使われていないデフォルト引数の除去(Remove Unused Default Parameter)
6.17 動的メソッド定義(Dynamic Method Definition)
6.18 動的レセプタから動的メソッド定義へ(Replace Dynamic Receptor with Dynamic Method Definition)
6.19 動的レセプタの分離(Isolate Dynamic Receptor)
6.20 evalを実行時からパース時へ(Move Eval from Runtime to Parse Time)

第7章 オブジェクト間でのメンバの移動
7.1 メソッドの移動(Move Method)
7.2 フィールドの移動(Move Field)
7.3 クラスの抽出(Extract Class)
7.4 クラスのインライン化(Inline Class)
7.5 委譲の隠蔽(Hide Delegate
7.6 横流しブローカーの除去(Remove Middle Man)

第8章 データの構成
8.1 自己カプセル化フィールド(Self Encapsulate Field)
8.2 データ値からオブジェクトへ(Replace Data Value with Object)
8.3 値から参照へ(Change Value to Reference)
8.4 参照から値へ(Change Reference to Value
8.5 配列からオブジェクトへ(Replace Array with Object)
8.6 ハッシュからオブジェクトへ(Replace Hash with Object)
8.7 片方向リンクから双方向リンクへ(Change Unidirectional Association to Bidirectional)
8.8 双方向リンクから片方向リンクへ(Change Bidirectional Association to Unidirectional)
8.9 マジックナンバーからシンボル定数へ(Replace Magic Number with Symbolic Constant)
8.10 コレクションのカプセル化(Encapsulate Collection)
8.11 レコードからデータクラスへ(Replace Record with Data Class)
8.12 タイプコードからポリモーフィズムへ(Replace Type Code with Polymorphism)
8.13 タイプコードからモジュールのextendへ(Replace Type Code with Module Extension)
8.14 タイプコードからState/Strategyへ(Replace Type Code with State/Strategy)
8.15 サブクラスからフィールドへ(Replace Subclass with Fields)
8.16 属性初期化の遅延実行(Lazily Initialized Attribute)
8.17 属性初期化の先行実行(Eagerly Initialized Attribute)

第9章 条件式の単純化
9.1 条件文の分解(Decompose Conditional)
9.2 条件分岐の組み替え(Recompose Conditional)
9.3 条件式の統合(Consolidate Conditional Expression)
9.4 重複する条件分岐の断片の統合(Consolidate Duplicate Conditional Fragments)
9.5 制御フラグの除去(Remove Control Flag)
9.6 条件分岐のネストからガード節へ(Replace Nested Conditional with Guard Clauses)
9.7 条件分岐からポリモーフィズムへ(Replace Conditional with Polymorphism)
9.8 nullオブジェクトの導入(Introduce Null Object)
9.9 アサーションの導入(Introduce Assertion)

第10章 メソッド呼び出しの単純化
10.1 メソッド名の変更(Rename Method)
10.2 引数の追加(Add Parameter)
10.3 引数の削除(Remove Parameter)
10.4 問い合わせと更新の分離(Separate Query from Modifier)
10.5 メソッドのパラメータ化(Parameterize Method)
10.6 引数から別々のメソッドへ(Replace Parameter with Explicit Methods)
10.7 オブジェクト自体の受け渡し(Preserve Whole Object)
10.8 引数からメソッドへ(Replace Parameter with Method)
10.9 引数オブジェクトの導入(Introduce Parameter Object)
10.10 設定メソッドの削除(Remove Setting Method)
10.11 メソッドの隠蔽(Hide Method)
10.12 コンストラクタからファクトリメソッドへ(Replace Constructor with Factory Method)
10.13 エラーコードから例外へ(Replace Error Code with Exception)
10.14 例外からテストへ(Replace Exception with Test)
10.15 ゲートウェイの導入(Introduce Gateway
10.16 式ビルダーの導入(Introduce Expression Builder)

第11章 一般化の処理
11.1 メソッドの上位階層への移動(Pull Up Method)
11.2 メソッドの下位階層への移動(Push Down Method)
11.3 モジュールの抽出(Extract Module)
11.4 モジュールのインライン化(Inline Module)
11.5 サブクラスの抽出(Extract Subclass)
11.6 継承の導入(Introduce Inheritance)
11.7 階層構造の統合(Collapse Hierarchy)
11.8 テンプレートメソッドの作成(Form Template Method)
11.9 継承から委譲へ(Replace Inheritance with Delegation)
11.10 委譲から継承へ(Replace Delegation with Hierarchy)
11.11 抽象スーパークラスからモジュールへ(Replace Abstract Superclass with Module)

第12章 大規模なリファクタリング
12.1 リファクタリングという試合の性質
12.2 大規模なリファクタリングが重要な理由
12.3 4つの大規模なリファクタリング
12.4 複合的な継承階層の分割(Tease Apart Inheritance)
12.5 手続き型設計からオブジェクト指向設計へ(Convert Procedural Design to Objects)
12.6 ドメインのプレゼンテーションからの分離(Separate Domain from Presentation)
12.7 継承階層の抽出(Extract Hierarchy)
サイト閉鎖のお知らせ | ASCII Books


臭うコード


「臭うコード」つまりリファクタリングしなきゃいけないコードの「臭い」と対処法(リファクタリング)とをリストしておきます(本書pp.441-442)。

第3章 コードの臭い

  1. コードの重複
    • 6.1 メソッドの抽出(Extract Method)
    • 11.1 メソッドの上位階層への移動(Pull Up Method)
    • 11.8 テンプレートメソッドの作成(Form Template Method)
    • 6.10 アルゴリズム変更(Substitute Algorithm)
    • 6.12 サンドイッチメソッドの抽出(Extract Surrounding Method)
    • 7.3 クラスの抽出(Extract Class)
    • 11.3 モジュールの抽出(Extract Module)
  2. 長いメソッド
    • 6.1 メソッドの抽出(Extract Method)
    • 6.4 一時変数から問い合わせメソッドへ(Replace Temp with Query)
    • 6.5 一時変数からチェインへ(Replace Temp with Chain)
    • 10.9 引数オブジェクトの導入(Introduce Parameter Object)
    • 10.7 オブジェクト自体の受け渡し(Preserve Whole Object)
    • 6.9 メソッドからメソッドオブジェクトへ(Replace Method with Method Object)
    • 9.1 条件文の分解(Decompose Conditional)
    • 6.11 ループからコレクションクロージャメソッドへ(Replace Loop with Collection Closure Method)
  3. 大きなクラス
    • 7.3 クラスの抽出(Extract Class)
    • 11.5 サブクラスの抽出(Extract Subclass)
    • 11.3 モジュールの抽出(Extract Module)
  4. 長い引数リスト
    • 10.8 引数からメソッドへ(Replace Parameter with Method)
    • 10.7 オブジェクト自体の受け渡し(Preserve Whole Object)
    • 10.9 引数オブジェクトの導入(Introduce Parameter Object)
    • 6.14 名前付き引数の導入(Introduce Named Parameter)
  5. 変更系統の分岐
    • 7.3 クラスの抽出(Extract Class)
  6. ショットガン創の手術
    • 7.1 メソッドの移動(Move Method)
    • 7.2 フィールドの移動(Move Field)
    • 7.4 クラスのインライン化(Inline Class)
  7. メソッドの浮気
    • 7.1 メソッドの移動(Move Method)
    • 6.1 メソッドの抽出(Extract Method)
  8. 群れたがるデータ
    • 7.3 クラスの抽出(Extract Class)
    • 10.9 引数オブジェクトの導入(Introduce Parameter Object)
    • 10.7 オブジェクト自体の受け渡し(Preserve Whole Object)
  9. プリミティブ強迫症
    • 8.2 データ値からオブジェクトへ(Replace Data Value with Object)
    • 8.12 タイプコードからポリモーフィズムへ(Replace Type Code with Polymorphism)
    • 8.13 タイプコードからモジュールのextendへ(Replace Type Code with Module Extension)
    • 8.14 タイプコードからState/Strategyへ(Replace Type Code with State/Strategy)
    • 7.3 クラスの抽出(Extract Class)
    • 10.9 引数オブジェクトの導入(Introduce Parameter Object)
    • 10.7 オブジェクト自体の受け渡し(Preserve Whole Object)
  10. case文
    • 6.1 メソッドの抽出(Extract Method)
    • 7.1 メソッドの移動(Move Method)
    • 8.12 タイプコードからポリモーフィズムへ(Replace Type Code with Polymorphism)
    • 8.13 タイプコードからモジュールのextendへ(Replace Type Code with Module Extension)
    • 8.14 タイプコードからState/Strategyへ(Replace Type Code with State/Strategy)
    • 10.6 引数から別々のメソッドへ(Replace Parameter with Explicit Methods)
    • 9.8 nullオブジェクトの導入(Introduce Null Object)
  11. パラレルな継承階層
    • 7.1 メソッドの移動(Move Method)
    • 7.2 フィールドの移動(Move Field)
  12. 仕事をしないクラス
    • 11.7 階層構造の統合(Collapse Hierarchy)
    • 7.4 クラスのインライン化(Inline Class)
    • 11.4 モジュールのインライン化(Inline Module)
  13. 空論的一般化
    • 11.7 階層構造の統合(Collapse Hierarchy)
    • 7.4 クラスのインライン化(Inline Class)
    • 10.3 引数の削除(Remove Parameter)
    • 10.1 メソッド名の変更(Rename Method)
  14. 一時フィールド
    • 7.3 クラスの抽出(Extract Class)
    • 9.8 nullオブジェクトの導入(Introduce Null Object)
  15. メッセージの連鎖
    • 7.5 委譲の隠蔽(Hide Delegate
    • 6.1 メソッドの抽出(Extract Method)
    • 7.1 メソッドの移動(Move Method)
  16. 横流しブローカー
    • 7.6 横流しブローカーの除去(Remove Middle Man)
    • 6.2 メソッドのインライン化(Inline Method)
    • 11.10 委譲から継承へ(Replace Delegation with Hierarchy)
  17. 親密すぎるクラス
    • 7.1 メソッドの移動(Move Method)
    • 7.2 フィールドの移動(Move Field)
    • 8.8 双方向リンクから片方向リンクへ(Change Bidirectional Association to Unidirectional)
    • 7.3 クラスの抽出(Extract Class)
    • 7.5 委譲の隠蔽(Hide Delegate
    • 11.9 継承から委譲へ(Replace Inheritance with Delegation)
  18. インターフェイスの異なるクラス群
    • 10.1 メソッド名の変更(Rename Method)
    • 7.1 メソッドの移動(Move Method)
    • 11.3 モジュールの抽出(Extract Module)
    • 11.6 継承の導入(Introduce Inheritance)
  19. 不完全なライブラリクラス
    • 7.1 メソッドの移動(Move Method)
  20. データクラス
    • 10.10 設定メソッドの削除(Remove Setting Method)
    • 8.10 コレクションのカプセル化(Encapsulate Collection)
    • 7.1 メソッドの移動(Move Method)
    • 6.1 メソッドの抽出(Extract Method)
    • 10.11 メソッドの隠蔽(Hide Method)
  21. 継承した遺産の拒絶
    • 11.2 メソッドの下位階層への移動(Push Down Method)
    • 11.9 継承から委譲へ(Replace Inheritance with Delegation)
  22. コメント
    • 6.1 メソッドの抽出(Extract Method)
    • 10.1 メソッド名の変更(Rename Method)
    • 9.9 アサーションの導入(Introduce Assertion)
  23. メタプログラミング
    • 6.18 動的レセプタから動的メソッド定義へ(Replace Dynamic Receptor with Dynamic Method Definition)
    • 6.1 メソッドの抽出(Extract Method)
    • 6.19 動的レセプタの分離(Isolate Dynamic Receptor)
  24. 柔軟過ぎるAPI
  25. 紋切り型コードの繰り返し
    • 6.1 メソッドの抽出(Extract Method)
    • 6.13 クラスアノテーションの導入(Introduce Class Annotation)




なお6〜12章のリファクタリング項目で上記「臭うコード」に挙がっていないのは以下の項目です。

第6章 メソッドの構成方法

6.3 一時変数のインライン化(Inline Temp)
6.6 説明用変数の導入(Introduce Explaining Variable)
6.7 一時変数の分割(Split Temporary Variable)
6.8 引数への代入の除去(Remove Assignments to Parameters)
6.11 ループからコレクションクロージャメソッドへ(Replace Loop with Collection Closure Method)
6.15 名前付き引数の除去(Remove Named Parameter)
6.16 使われていないデフォルト引数の除去(Remove Unused Default Parameter)
6.17 動的メソッド定義(Dynamic Method Definition)
6.20 evalを実行時からパース時へ(Move Eval from Runtime to Parse Time)

第7章 オブジェクト間でのメンバの移動

第8章 データの構成
8.1 自己カプセル化フィールド(Self Encapsulate Field)
8.3 値から参照へ(Change Value to Reference)
8.4 参照から値へ(Change Reference to Value
8.5 配列からオブジェクトへ(Replace Array with Object)
8.6 ハッシュからオブジェクトへ(Replace Hash with Object)
8.7 片方向リンクから双方向リンクへ(Change Unidirectional Association to Bidirectional)
8.9 マジックナンバーからシンボル定数へ(Replace Magic Number with Symbolic Constant)
8.11 レコードからデータクラスへ(Replace Record with Data Class)
8.15 サブクラスからフィールドへ(Replace Subclass with Fields)
8.16 属性初期化の遅延実行(Lazily Initialized Attribute)
8.17 属性初期化の先行実行(Eagerly Initialized Attribute)

第9章 条件式の単純化
9.2 条件分岐の組み替え(Recompose Conditional)
9.3 条件式の統合(Consolidate Conditional Expression)
9.4 重複する条件分岐の断片の統合(Consolidate Duplicate Conditional Fragments)
9.5 制御フラグの除去(Remove Control Flag)
9.6 条件分岐のネストからガード節へ(Replace Nested Conditional with Guard Clauses)
9.7 条件分岐からポリモーフィズムへ(Replace Conditional with Polymorphism)

第10章 メソッド呼び出しの単純化
10.2 引数の追加(Add Parameter)
10.4 問い合わせと更新の分離(Separate Query from Modifier)
10.5 メソッドのパラメータ化(Parameterize Method)
10.12 コンストラクタからファクトリメソッドへ(Replace Constructor with Factory Method)
10.13 エラーコードから例外へ(Replace Error Code with Exception)
10.14 例外からテストへ(Replace Exception with Test)

第11章 一般化の処理
11.11 抽象スーパークラスからモジュールへ(Replace Abstract Superclass with Module)

第12章 大規模なリファクタリング
12.1 リファクタリングという試合の性質
12.2 大規模なリファクタリングが重要な理由
12.3 4つの大規模なリファクタリング
12.4 複合的な継承階層の分割(Tease Apart Inheritance)
12.5 手続き型設計からオブジェクト指向設計へ(Convert Procedural Design to Objects)
12.6 ドメインのプレゼンテーションからの分離(Separate Domain from Presentation)
12.7 継承階層の抽出(Extract Hierarchy)

*1:camelCaseかsnake_caseか、と言う意味ではなく