継承は悪なのか
はじめに
業務で Rails アプリを開発する中で「継承が辛いなあ。継承って実は使わないほうがよいのでは?」という気持ちが膨らんできた。
軽くググってみると、何年も前から継承の問題点が指摘されているようだ。
世の中的には議論が尽くされている状態っぽし、今更継承に対して問題意識を持った自分が情けないが、自分のモヤモヤを解消するために「継承は悪なのか」を整理する。
継承とは
継承は「差分プログラミングを実現するための手段(機能)」というのが僕の理解である。
そして、差分プログラミングの目的は下記の認識である。
- 手軽にソフトウェアを拡張できるようにすることで、生産性を向上させる。
- 共通部分をまとめることによって再利用性を高め、生産性を向上させる。
差分プログラミングのデメリットを整理することで、継承の問題点を明らかにできそう。
差分プログラミングのデメリット
下記の2点がデメリットだと考えた。
- スーパークラスとサブクラスの間、サブクラス同士の間に依存関係が生まれる(共通化されたデータやメソッド)。不適切な依存関係が生まれると修正が困難になる。
- 階層化されたクラスでは状態(データ/メンバ変数)と振る舞い(メソッド)が把握しづらくなり修正が困難になる。
従って、継承には下記のリスクがあるといえる。
- 継承を使うべきではないときに使うと、「差分プログラミング」のデメリットだけ発生してしまう。
- 継承を使うべきときでも、適切な依存関係と階層レベルを設計しないと、ソフトウェアを修正困難なものにしてしまう。
継承の問題点
まとめると、適切に継承を使うこと(使うべきかどうか判断すること・適切な依存関係と階層レベルで設計すること)が難しく、メリットよりも「差分プログラミングのデメリット」の方が大きくなりがち というのが継承の問題点だろう。
初めはちゃんと設計されていたとしても、適切な依存関係と階層レベルを保つのが難しく、「差分プログラミングのデメリット」の方がどんどん大きくなってしまった結果、出来上がったのが「神クラス」と呼ばれるものなんだと思う。
継承を正しく使う
継承を使うときの自分ルールを設定した。
- リスコフの置換原則を満たす(他のオブジェクトへの副作用や例外処理などを含めた置換可能性に従う)場合のみ、継承を使って良い。
- 階層を深くしない(多段継承を避ける)。
おわりに
継承は悪ではなかった。
しかし、正しく使うのが難しく、継承に対する理解(適切に使うための知識)が足りてないと「利用する側が修正困難なソフトウェアという悪を生み出してしまう(= 継承は悪を生み出しやすい)」という問題を抱えていることが分かった。