ソフトウェア開発メモ

日々のソフトウェア設計、実装で考えている、気づいた事を書いています。それが真実か否かは保証しません。悪しからず。

継承乱用の戒め

始めに

 仕事で書いたコードを見直すと余計な所まで継承を使っている。ちゃんと設計を勉強して、有名なEffective Javaの「継承よりコンポジションを使え」の章を何度も何度も読みかえしたのに。自戒の念を込めておさらい。

歴史

という事で継承とコンポジションのおさらい。

私は80年代の事は知らないけど、いろいろ文献を見る限り、コンポジションは比較的後、1990年前後に出て来た概念だと思う。

2つの流れが有って、継承なしにカスタマイズするやり方として、まずSmalltalkのPluggable MVCという手法がでてきた。アダプター系のクラスにオブジェクト+ゲッター/セッターのメソッドシグネチャやブロッククロシジャー(Objective-CのBlocksと同じ)を設定して、カスタマイズするクラス(大抵はView)に接続する方法。

 次に、NeXTSTEPフレームワークメソッドシグネチャーだけを定義したプロトコル(Javaでいうインターフェス)を継承、実装して、カスタマイズするクラスに接続する方法。ちなみに元々プロトコルは分散通信の負荷を下げるために導入された(だから、プロトコルというかどうかは知らない)。ちなみに、iOSフレームワークのクラス階層は、デレゲートをうまく使っているせいか浅いのが多いです。

 その後、これらの設計ノウハウを体系的にまとめあげた有名な本(デザインパターンが出て来た)は出版された。そこには太字でこう記載されてある。「継承よりコンポジションを使え」。あと続いて「設計者は再利用技術として継承を使い過ぎ」と書いてある。

次に、「継承よりコンポジションを選ぶ」という格言で有名なEffective Javaも出版された。

 2000年以降は継承は最後の手段というか、本当に型として扱いたい場合だけやる物だという意識が(偉い人の間では)ようやく一般化してくる。

実際は

殆どの人はコンポジションをうまく使いこなせず、(特に実装の方が色々楽なため)安易に継承の方を使ってしまう。自分でフレームワークの用な物?を作る場合は顕著。

結果とし謎な深い階層構造ができる。

改善案
  • 本当に継承が必要か真剣に検討する。
  • どうしても必要な場合、サブクラスとの密結合を避けるため継承のためのフック(テンプレート)メソッドしか提供しない方向で設計する。ようはプロトコルメソッドと同じですな。

まあ、派生クラスに対してどれだけオープンにするか?ということですな。

追記 2014/10/4:テンプレートメソッドを提供する場合でも、スーパークラスメソッドを呼ばなければ行けないものはやはり危険。