Parallel Inheritance Hierarchies
Parallel Inheritance Hierarchies(並行継承階層)
兆候と症状
クラスのサブクラスを作成するたびに、別のクラスのサブクラスを作成する必要がある場合。
※正直この説明だけだとどういう状況なのかがよくわからなかった。
このサイトの方がわかりやすかったのでこちらをベースに訳してみました。
このサイトより抜粋
どうやら似たような継承関係を持つクラスが複数あるような状況で、新たなクラスを追加するともう一方の方にもクラスを追加する必要があるような状況らしい。
上の図で言うと、VehicleクラスがOperatorクラスを保有している(フィールドがある)ような状況で、Vehicleのサブクラスに新しいクラスを追加したいような場合にOperatorも追加しないといけないような状況のことを言っているらしい。
対処法も違うやり方が掲載されているのでご紹介
Defer identification of state variables pattern
Defer identification of state variables pattern(状態変数の識別延期パターン)
状態変数(図1でいうPoint)をサブクラスに識別させるパターン。 (サブクラスでの定義をDefer identification:遅延識別と言っている) スーパークラスでアクセッサをabstractで定義しておいて、サブクラスでOverrideすることで、柔軟な設計ができるようになる。
【図1】

このサイトより抜粋
【図2】

このサイトより抜粋
Intelligent children pattern
Defer identification of state variables のより具体的な話。
スーパークラス同士をコンポジットさせるのではなく、サブクラス同士をコンポジットさせるパターン。

このサイトより抜粋
スーパークラスにOperatorを返すアクセッサをAbstractで定義しておいて、サブクラスでOperatorのサブクラスを返すようにOverrideすることで実現する。
このサイトより抜粋
問題の理由
階層が小さければ問題は発生しにくいですが、新しいクラスが追加されると、変更を加えることがだんだん難しくなります。
対処
※対処は元のサイト(sourcemaking)を訳しています。
上で紹介した「Intelligent children pattern」とは別の対処方法の話です。
2つの手順でParallel Inheritance Hierarchiesを排除できます。まず、ある階層のインスタンスが別の階層のインスタンスを参照するようにします。次に、「Move Method」と「Move Field」を使用して、参照先クラスの階層を削除します。
【リファクタリング前】

このサイトより抜粋
【リファクタリング後】

このサイトより抜粋
効果
- 重複コードの排除
- コード構成の改善
When to Ignore Parallel Inheritance Hierarchiesは、プログラムアーキテクチャでさらに大きな混乱を避けるための方法の一つです。階層の重複を排除しようとしても醜いコードが生成される場合は、すべての変更を元に戻し、そのコードに慣れてください。
書籍としてはこの辺りが参考になると思います。
リファクタリング第2版
レガシーコード改善ガイド
