んだです。メモです。
今回は、インターフェース分離原則(ISP)について。
インターフェース分離原則(ISP)とは??
「クライアントが使用しないメソッドに依存するよう強制されるべきではない」という原則。
ISP違反な実装
例えば、こんなインターフェイスがあったとします。
interface OrderService { // ブラジャーの注文 public function orderBra($cup); // パンティの注文 public function orderUnderwear($color); // ブラジャーとパンティのセットの注文 public function orderSetup($cup, $color); }
パンティだけの注文を実装してみます。
class UnderwearOrderService implements OrderService { public function orderBra($cup) { throw new \Exception('ブラジャーだけの注文は出来ません。'); } public function orderUnderwear($color) { return 'ご注文は:' . $color . '色のパンティです'; } public function orderSetup($cup, $color) { throw new \Exception('上下の注文は出来ません。'); } }
orderBraとorderSetupは出来ないので、例外を投げます。
BraOrderServiceも同じく、orderUnderwearとorderSetupは例外を投げます。
class BraOrderService implements OrderService { public function orderBra($cup) { return 'ご注文は:' . $cup . 'カップのブラです'; } public function orderUnderwear($color) { throw new \Exception('パンティだけの注文は出来ません。'); } public function orderSetup($cup, $color) { throw new \Exception('上下の注文は出来ません。'); } }
ISP違反は、何が良くないのか??
利用していないメソッドに依存してしまうと、そのメソッドが変更されたときに無関係のメソッドにも影響してしまうから。
たとえば、 パンティを注文するメソッド(orderUnderwear)の引数を 「色」だけではなく、ヒモパンとかTバックとか「種類」も追加したいくなったとする。
public function orderUnderwear($color); ↓↓↓↓ public function orderUnderwear($color,$type);
この修正で、本来関係ないブラジャーの注文も修正しないといけなくなる。。
class BraOrderService implements OrderService { public function orderBra($cup) { return 'ご注文は:' . $cup . 'カップのブラです'; } // このメソッドも修正。。。 public function orderUnderwear($color) { throw new \Exception('パンティだけの注文は出来ません。'); } public function orderSetup($cup, $color) { throw new \Exception('上下の注文は出来ません。'); } }
この無駄な修正を避けるために、利用しないメソッドに依存する実装は避けようという原則。
リファクタリング
インターフェイスを分離します。
インターフェイス パンティ。
interface OrderUnderWear { public function orderUnderwear($color); } class UnderwearOrderService implements OrderUnderWear { public function orderUnderwear($color) { return 'ご注文は:' . $color . '色のパンティです'; } }
インターフェイス ブラジャー。
interface OrderBra { public function orderBra($cup); } class BraOrderService implements OrderBra { public function orderBra($cup) { return 'ご注文は:' . $cup . 'カップのブラです'; } }
以上。