第6章 テスト不足に気づいたら
この章でやったこと
2 つのクラスで重複していたメソッドを、新しく定義した親クラスのメソッドに引き上げた
Before
code:mermaid
classDiagram
class Dollar {
+equals(other) bool
}
class Franc {
+equals(other) bool
}
After
code:mermaid
classDiagram
class Money {
+equals(other) bool
}
class Dollar {
}
class Franc {
}
Money <|-- Dollar
Money <|-- Franc
テスト不足に気がついた場合
サンプルコードでは Franc クラスの equals メソッドが不足していた
テストが無ければリファクタリングは不可能
結果として次第に設計が腐っていく
今回のケースでも一見すると継承でも良さそう
親クラスの実装変更がサブクラス全体に影響する問題 も現時点では起こり得ない
しかし、継承はやっぱりデメリットが多すぎ
is-a の関係ということは、高結合 で変更にも弱い ということ サブクラスは、親クラスの protected や private フィールドにアクセスできる(言語による)
これ避けるの無理ゲー
結果として利用者が想定していない挙動によるバグが発生する可能性
∵ 呼び出し元でクラス判定が必要になるため
対称性: x.equals(y) が true ならば y.equals(x) も true
推移性: x.equals(y) かつ y.equals(z) が true ならば x.equals(z) も true
∵ 等価性という概念は 二項関係 であり、両方の オペランド のうち「どちらの型を基準とするか」を一意に決められないため 親クラス視点では、サブクラス特有のフィールドは無視すべき余分な情報
サブクラス視点では、上記のフィールドは等価性の本質的な一部
上記の 2 つを同時に満たそうとすると、矛盾が生じる
まぁ、あくまで設計の過程でしょ
最終的に値の合成(has-a, Record<int amount, int currency>)に置き換わった気がする(忘れた)