LoginSignup
20
16

More than 5 years have passed since last update.

オブジェクト指向に限らず守りたい最重要原則 ”open/closed principle - OCP - 開放/閉鎖原則”(SOLID原則より)

Last updated at Posted at 2018-10-11

GoFのデザインパターンやGRASPと呼ばれるパターンがあります。

オブジェクト指向プログラミングにはPublicPrivate等のスコープがあります。

それが何のためにあるかと言えば、このopen/closed principle - OCP - 開放/閉鎖原則を守るためと言っても言い過ぎじゃないです。

もう少し補足すると、PublicPrivateデザインパターンを使うことによってこのopen/closed principle - OCP - 開放/閉鎖原則を守った設計が自然と出来るということです。

ちなみに、この OCP というのは オブジェクト指向の基本原則(基本5原則)と呼ばれるものの1つにあげられます。他の4つもとても重要なものではあるのですが OCP の重要さには負けます。

ちなみに今はこれを SOLID原則 と言う方が一般的らしいです。。

サマリー

OCPを簡単に表現すると、

拡張に対して開いて (open) いなければならず、
修正に対して閉じて (closed) いなければならない

という設計上の原則のことです、

もう少し平易な日本語で説明すると、

何か機能追加があった場合には、既存のコードには手を入れず、オブジェクトの追加によって対応可能であるべきであり、
何かバグなどの修正が入った場合には、バグが入ったオブジェクトだけを修正することで対応可能であるべきである。

ということを言ってます。

これはソフトウェア設計に限定された話ではなく様々な構造物において大事な原則です。

何か家電であったり自動車であったりも部品が壊れたらその壊れた部品の交換だけで済むべきです。何か機能の追加がしたければその機能をプラグイン的に差し込むだけで拡張できるべきです。

そういうことを言っています。

主な実現方法とメリット

オブジェクト指向においてどうやってこれを実現するか?という実装例です。

拡張 - Open について

実現方法の前にこれが実現できていなかったケースは以下になります。
機能追加があったときに、そのクラス自体を修正しています(functionA'とそれを使う feature Bを追加してます)。このクラス自体に変更が入っているために今まで class_A を使っていた feature A でも再テストが必要になります。

image.png

OCPの原則を守るためにこの問題を「継承」を使って解決します。
※ 解決のために継承を使う場合とインタフェースを使う場合がありますが本質的には同じことを指すためここでは「継承」を扱ってます。

次にこれを「継承」を使って実現した場合には以下のようになります。

image.png

継承を使い既存のオブジェクトには一切手を加わえることなく class_A' を作ることで機能の追加を行っています。 class_A を使っていた feature A には影響なく、feature B のための機能拡張ができています。

これが、拡張に対して開いている、という状態です。

修正 - Closed について

こちらは比較的簡単で、修正があった場合にはなるべく影響範囲を少なくしようという話です。

ある機能がバラバラに複数のクラスにまたがるのではなく、1つのクラスに封じ込めることで、ある機能に不具合があっても、その機能を表現している1クラスの修正で済ませるべきという考え方です。

ここに関しては他の基本原則である SRP が関わってくるので、いつかそちらでも説明します。

ここでもSRPの原則がなぜ必要かというと、OCPが守れるからと言ってしまってよいと思います。

メリット

機能追加(拡張)に対して、既存クラスに手を加えていないことが保証されているため、少ないリスクで作業が可能です。
先述の図で言うと、feature Aへの影響がない状態で機能の拡張feature Bの追加ができるということです。

小さな規模での少人数での開発では、このメリットがピンとこないこともあるかと思います。
ある程度規模が大きくなっていくと、1つのクラスに本当に多くの機能が依存しているため、そのクラスの修正による影響範囲の分析も難しく、そのための再テストの工数も膨大になってきます。

そのような問題を回避できるのが open/closed principle - OCP - 開放/閉鎖原則 です。

まとめ

最初にも言いましたが、これはソフトウェア設計に限定されず様々な構造物において大事な原則です。
何か家電であったり自動車であったりも部品が壊れたらその壊れた部品の交換だけで済むべきです。何か機能の追加がしたければその機能をプラグイン的に差し込むだけで拡張できるべきです。

ただ、いくらこれが大事だとわかっていても、これを実現するためには非常に様々なテクニックが必要になります。
われわれが対象としているシステムや事象というのは、われわれが想像している以上に複雑なものです。

オブジェクト指向、デザインパターンといったものを使うと、これの実現のための最低限の道しるべが出来ます。

なんならオブジェクト資料やデザインパターンというものはOCPのためのフレームワークといっても良いかもしれないです。

20
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16