TOP

このエントリーをはてなブックマークに追加

Parallel Inheritance Hierarchies


Parallel Inheritance Hierarchies

Parallel Inheritance Hierarchies(並行継承階層)

兆候と症状
クラスのサブクラスを作成するたびに、別のクラスのサブクラスを作成する必要がある場合。

※正直この説明だけだとどういう状況なのかがよくわからなかった。
このサイトの方がわかりやすかったのでこちらをベースに訳してみました。

image.png

このサイトより抜粋

どうやら似たような継承関係を持つクラスが複数あるような状況で、新たなクラスを追加するともう一方の方にもクラスを追加する必要があるような状況らしい。

上の図で言うと、VehicleクラスがOperatorクラスを保有している(フィールドがある)ような状況で、Vehicleのサブクラスに新しいクラスを追加したいような場合にOperatorも追加しないといけないような状況のことを言っているらしい。

対処法も違うやり方が掲載されているのでご紹介


Defer identification of state variables pattern

Defer identification of state variables pattern(状態変数の識別延期パターン)

状態変数(図1でいうPoint)をサブクラスに識別させるパターン。 (サブクラスでの定義をDefer identification:遅延識別と言っている) スーパークラスでアクセッサをabstractで定義しておいて、サブクラスでOverrideすることで、柔軟な設計ができるようになる。

【図1】
image.png
このサイトより抜粋


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


Intelligent children pattern

Intelligent children pattern

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

image.png
このサイトより抜粋

スーパークラスにOperatorを返すアクセッサをAbstractで定義しておいて、サブクラスでOperatorのサブクラスを返すようにOverrideすることで実現する。

image.png このサイトより抜粋

問題の理由
階層が小さければ問題は発生しにくいですが、新しいクラスが追加されると、変更を加えることがだんだん難しくなります。

対処
※対処は元のサイト(sourcemaking)を訳しています。 上で紹介した「Intelligent children pattern」とは別の対処方法の話です。

2つの手順でParallel Inheritance Hierarchiesを排除できます。まず、ある階層のインスタンスが別の階層のインスタンスを参照するようにします。次に、「Move Method」と「Move Field」を使用して、参照先クラスの階層を削除します。


【リファクタリング前】
image.png
このサイトより抜粋

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

効果

  • 重複コードの排除
  • コード構成の改善

When to Ignore Parallel Inheritance Hierarchiesは、プログラムアーキテクチャでさらに大きな混乱を避けるための方法の一つです。階層の重複を排除しようとしても醜いコードが生成される場合は、すべての変更を元に戻し、そのコードに慣れてください。



書籍としてはこの辺りが参考になると思います。

リファクタリング第2版
refactoring
レガシーコード改善ガイド
legacy_code