30章 デザインパターン
「デザインパターンを“思い出すため”の道具ではなく、“自然に生み出す”ためのプロセス
デザインパターンは設計図として使うものではなく、TDDを真面目にやると結果として現れる設計の形
TDDとしては、小さいテストを書く通るだけの実装重複が増えたら抽象化
代表的なデザインパターン
Factory
オブジェクト生成の責務を隠蔽
User::factory()->create();
TDDとして
- new の重複が出始める
- テストの準備が煩雑
↓
Factory抽出
Strategy
条件分岐をオブジェクトに昇格
NG
if($type === 'a') { ... }
elseif($type === 'b') { ... }
OK
$resolver->resolve($type)->calculate();
TDDでの生まれ方
- テストが「条件ごと」に増える
- ifが膨張
↓
クラス分割
Command
処理単位の明確化
CreateOrder::execute()
Composite
再起的な構成を表現
$total = $cart->sum();
Cart → Item → Option
各要素が sum() を持つ
Template Method
枠組みを固定し、差分をサブクラスへ
abstract class Calculator {
final public function run() {
$this->pre();
$this->calc();
$this->post();
}
}
Null Object
nullチェック排除
$user->profile()->display();
パターンは目的ではない。
- 問題解決の結果
- 名前をつけて保管しただけ
TDDが生む設計進化
Step1
if ($type === 'A') return 100;
Step2
match($type) {
'A' => 100,
'B' => 200
};
Step3
interface FeeRule { public function calc(); }
class TypeAFee implements FeeRule {}
class TypeBFee implements FeeRule {}
→ Strategy パターン自然発生