継承の爆発
継承に関するトラブルで一番多いのは「継承の爆発」、つまり継承関係がやた ら多くなってしまってわけがわからなくなることです。プログラミング言語か ら入った人はこうなりがちです。なぜならプログラミング言語では継承は従来 のC言語なんかとは一味違う「かっこいい事」であり、これを使いこなす事で 友達に差をつけることができるからです。
「継承は素晴らしい」「継承が使いこなせるとかっこいい」「継承こそオブジェ クト指向だ」という間違ったメッセージを鵜飲みにして開発を始めると、次の ような事態に陥ります。
クラス爆発
前に継承の例で「犬」のサブクラスとして「秋田犬」があるというお話をしま した。「これはなんか変じゃない?」と思った方は見る目があります。そうで す。よく考えるとなんか変です。
「秋田犬」というのがあるならもちろん「柴犬」だって「土佐犬」だってある でしょう。「チワワ」だって「ブルドッグ」だって「セントバーナード」だっ て……そろそろ気がつきましたか?こうやって挙げるとキリがないのです。 こんな状況を避け、正しく分析するにはどうしたらいいのでしょう?「秋田犬」 というのは犬の「品種名」ですから、「犬」オブジェクトの「品種名」とい う属性に"秋田犬"と書いておけばいいだけなのではないでしょうか?
確かにそれも一理あります。しかしもう少し事情は複雑なのです。実は「犬」 というのだって同じなのです。「犬」があれば「猫」だって「熊」だって「狐」 だって「狸」だって「馬」だって「牛」だって……これもやっぱりキリがない のです。結局のところ「犬」というオブジェクトも何か変な定義なのでしょう か?
定義に完璧性を求めるとこうなります。この解決法は「いるものは定義する。 いらないものは考えない」というごく当たり前のものです。「何か変だ」と感 じたら「本当にサブクラスにする必要があるのか?」と考えましょう。いくら サブクラスやスーパークラスを見つけ出せたとしても、それが必要ないものだっ たら定義する必要はありません。
細分化
オブジェクトの継承関係はいくらでも細分化することができます。これが問題 を引き起こすことがあります。
例えば、「犬」というオブジェクトを分析してみましょう。犬は肉を食べます。 だから「肉を食べるもの」のサブクラスです。また、四つ足ですから「四足動 物」のサブクラスです。尻尾があります。だから「尻尾があるもの」のサブク ラスであるとも言えるでしょう。「ペット」のサブクラスでもあります。 と、こうやって挙げていけばキリがないのです。これが外延や機能の細分化に よって継承が爆発的に増えてしまう例です。
「そんなバカな。いくら何でも『尻尾があるもの』なんて意味のなさそうな細 分化はしない」とお思いの方もいらっしゃるでしょう。しかし実際にはこれは よく起きます。これは「再利用を考えた、後々まで使える完璧なライブラリを 作ろう」とするとしばしば起きることです。
「再利用」の話でも述べましたが、「再利用しよう」というスローガンを掲げ て分析を始める場合のほとんどは、どこに再利用するかという目的がありませ ん。だから、「尻尾があるもの」というクラス分けに意味があるかないかがわ からないのです。そして、「どうせだから付けておこう。ないよりある方がい いだろう」という理由で、意義について深く考えもせずに残されてしまいます。 結果として、どこに使うかもわからない謎のクラスがたくさんできてしまうの です。
継承の爆発にならないために
これらの問題を引き起こす理由は単純です。「継承関係をたくさんつけた方が 偉い」という価値観です。そして「何のために継承関係をつけるのか」という 目的を見失ってしまっているからです。まずこの価値観を見直しましょう。
モデルはシンプルイズベスト。簡潔でわかりやすい方が偉いのです。継承関係 をつけるのは、その方がモデルがシンプルになる場合に限ります。いたずらに 複雑になるような継承関係なら無い方がマシです。これは継承に限らずモデリ ング全般に言えます。
それから、「何のためにモデル化しているのか」を常に考えましょう。つまり はドメインです。どういった観点で、どういった場所に使うためのモデルを作っ ているのかを常に明確にし、それに必要なものだけを残して不要なものは全部 捨ててしまいましょう。