Skip to main content
カテゴリ: 原則
種類: システム設計原則
起源: ロバート・C・マーティン、C++ Report Engineering Notebook、1996年
別名: ISP、ファットインターフェイス問題、ロールインターフェイス、Interface Segregation Principle
先に答えるとインターフェイス分離の原則(Interface Segregation Principle)は、利用者が使わないメソッドに依存させてはならない、という設計規則です。ロバート・C・マーティンは1996年の C++ Report コラムで、無関係な呼び出し側を結びつけてしまう「太い」インターフェイスを示して命名しました。実務の検査は単純です。自分が決して呼ばない変更が、再コンパイルや再読解、再テストを強いるなら、依存している契約は広すぎます。

インターフェイス分離の原則とは?

インターフェイス分離の原則は、呼び出し側が実際に使うメソッドにだけ依存すべきであり、他の呼び出し側がたまたま必要とする寄せ集めの契約に依存してはならない、という設計規則です。
クライアントは、使わないインターフェイスに依存するよう強いられてはならない。
これは小さなクラスを求めているのではありません。一つのオブジェクトが多くの仕事をしても構いません。原則が問うのは見え方です。各利用者は、背後のオブジェクトが大きくても、痩せて凝集した面だけを見るべきです。 日常の絵は学校の遠足届です。20分の博物館見学に、泊まりの医療同意も銀行情報もバス運転手の資格も要りません。同じ用紙に載っていれば、保護者は飛ばすか、誤って記入します。法務が泊まりの条項を直すと、短い遠足の用紙も刷り直されます。その卓が頼んでいない一品を厨房が変えた、ということです。 コードでは、work()eat()sleep() を要求する Worker 型が、ロボットに同じことをします。空のメソッド、UnsupportedOperationException、「ここでは呼ぶな」というコメントが傷です。単一責任の原則 は、一つのモジュールに変わる理由が多すぎないかを問います。この原則は、ある利用者にそれらの理由を見せすぎていないかを問います。

インターフェイス分離の原則を3つの深さで理解する

  • 入門: 開けない道具箱を渡さない。絵を掛けるだけなら、コルク抜きは自分の問題ではありません。ただしコルク抜きの変更でベルト一式が再配布されるなら、問題になります。
  • 実務: 実装する側ではなく、呼ぶ側でインターフェイスを分ける。空メソッドと「未サポート」が臭いです。太いオブジェクトが薄い面を複数実装して構いません。
  • 上級: 利用者は、自分が見ている契約へ変更を後ろ向きに押し返します。太いインターフェイスはそれゆえ利用者同士を結合します。静的言語では再コンパイルです。アーキテクチャの尺度でも、マーティン後年の一文は同じです。必要以上のものを含むモジュールに依存するのは有害である。

起源

インターフェイス分離の原則は、「小さいインターフェイス」の標語としてではなく、静的型のオブジェクト指向コードにおけるコンパイルと結合の問題として始まりました。 ロバート・C・マーティン は、C++ Report の Engineering Notebook 第4回 The Interface Segregation Principle1996年)でこれを述べます。前回(1996年5月)は依存性逆転の原則でした。そのコラムの実務の一行が、上の引用です。マーティンが狙ったのは「太い」、あるいは「汚染された」インターフェイスです。クラスのメソッドがグループに分かれ、各グループが別の利用者集合に仕える。非凝集な表面を本当に必要とするオブジェクトはあります。しかし利用者は、それを一つの型として知らなくてよい、と彼は論じます。 論文の最初の傷は、施錠・解錠・開閉を知るセキュリティの Door です。TimedDoor はさらにタイムアウト警報を要するため、設計者は TimerClientDoor に押し上げます。計時のいらないドアは、空実装せざるを得ない TimeOut を継承します。さらに悪いことに、タイマーの修正——閉じて再び開いたドアが誤報しないようタイムアウト ID を足す——が、Door のすべての利用者に再コンパイルを強います。マーティンの診断は、別の利用者なら別のインターフェイス、です。親の nil 仮想関数は リスコフの置換原則 にも反します。 より大きな例は ATM のユーザーインターフェイスです。入金、出金、振替が、一つの UI 型の別々の切片を呼びます。一つの取引が UI に強いる変更が、他のすべての取引に当たります。修正は DepositUIWithdrawalUITransferUI に分け、具象 UI が多重継承することです。それらを「一箇所で全部」と一つのヘッダに包み戻せば、分けて外した結合が戻ります。 マーティンは Agile Software Development: Principles, Patterns, and Practices(Prentice Hall、2003年)で、多くのクライアント固有インターフェイスは一つの汎用インターフェイスよりよい、という対の標語で言い直します。2004年 前後、Michael Feathers はマーティンの「最初の五原則」を SOLID の頭字語に並べます。インターフェイス分離の原則はその「I」です。Clean Architecture(Prentice Hall、2017年、第10章)では、同じ警告をクラスファイルの外へ広げます。必要以上のものを含むモジュールに依存するのは有害である。Martin Fowler のロールインターフェイスは、呼び手の側から同じ切り口を名づけます。インターフェイスは、話しかける対象全体ではなく、利用者が必要とする役割を記述すべきです。 後年の講義では、最初のコンサル洞察を Xerox に置くことが多く、印刷・ステープル・FAX を混ぜたプリンタの Job クラスとして語られます。1996年の論文自体は、その顧客名を出しません。公刊された展示は、計時ドアと ATM の UI です。

要点

インターフェイス分離の原則が本領を発揮するのは、複数種の呼び出し側が一つのオブジェクトを共有し、同じメソッドは共有しないときです。豊かなオブジェクトの禁止ではありません。見知らぬ人にコンパイルさせるメソッドを、どこまで許さないかの規則です。
1

利用者は、見えているものへ変更を後ろ向きに押す

私たちは通常、変わったインターフェイスが利用者を壊すことを心配します。マーティンが足した力は逆向きです。利用者がインターフェイスを変えさせ、その太い型の他の利用者が払います。給与とインターン名簿が一つの「従業員ポータル」型を共有すれば、税務の欄がインターンアプリを再ビルドさせます。関心の分離 は仕事を分けます。この原則は、その仕事を見るを分けます。
2

空メソッドは設計ではなく告白である

eat() を例外で実装するロボットや、fly() を空操作にする鳥は、「特殊化した労働者」ではありません。大きすぎる親の子です。その穴は置換可能性も壊します。太い型の利用者は、そのメソッドを信頼できません。面を分け、公開したメソッドを実装者ごとにすべて守れるようにします。
3

オブジェクトは太くてよい。面は痩せていなければならない

TimedDoor は、ドアともタイマーとも話さねばなりません。マーティンの答えはアダプタオブジェクトか、二つの細い基底の多重継承です。同じオブジェクトが複数の帽子をかぶって構いません。呼び出し側は帽子を一つ取り、ラックごと持っていかない。クラブの役が会計と鍵係を兼ねて存在してよい。おやつ当番が依存すべきは「おやつを持ってくる」であり、銀行ログインではありません。
4

いつも一緒に動くメソッドは分けない

メソッドごとに一つのインターフェイスが目標ではありません。同じ理由で変わり、同じ呼び出し側がいつも一緒に使うメソッドは、一つの面に残します。YAGNI が効きます。第二の利用者が別の切片を必要とするまで、役割を発明しない。分けすぎは、一塊のまま動く型の迷路です。

応用場面

一つのオブジェクトや帳票が複数の聴衆に仕え、一方の聴衆向けの変更が他方に落ちてはならないときに、インターフェイス分離の原則を使います。すべての呼び出し側がすでに一式で使っている凝集した道具箱を砕くために使わないでください。

次の呼び出し側が来る前に、公開した面を分ける

印刷ジョブがステープルしないなら、staple() に対してコンパイルさせない。読み取り専用の帳票が保存しないなら、save() を実装させない。各呼び出し側に、守れる役割を渡します。オープン・クローズド原則 は、そのあとで細い差し込み口を持ち、新しい呼び出し側が古い口を開き直さずに入れます。

代理が本当に担える職務やボランティア役割を書く

運転免許、食品衛生、泊まりの医療同意を求める「保護者ヘルパー」票は、ケーキだけ持ってくる人を遠ざけます。この当番がすべき仕事を列挙し、それだけを尋ねます。票の半分を飛ばさねばならない代理は、登録できたのではありません。使わない欄に阻まれています。

公的な帳票を役割として刷り、マスター一式にしない

短期査証、図書館カード、入館証が、一つの「任意の公的申請」PDF を共有すべきではありません。市民は余分な来訪と誤った添付でその食い違いを払います。一部の申請者が決して使わない欄は、親の帳票に置きません。八ポイントで「該当しなければ飛ばす」と書くのではなく、帳票を分けて隠します。

日常の表面から管理権限を外す

給与、取締役会議事録、本番の緊急停止を読み込むインターン向けポータルは、太い型と同じ規則に反します。役割が必要とする切片に依存します。それは権限だけでなく知識に対する 最小権限 です。停止スイッチの変更が、インターンのホームページを再配備してはなりません。

事例

インターフェイス分離の原則を公開 API として番号付きで見る窓は、Java のマウスイベントリスナーです。一つの GUI パッケージが結合理論の全体だという主張ではありません。 JDK 1.11997年2月19日)は、古い AWT の継承イベントモデルを委譲に替えます。リスナーを実装して登録します。マウスの通信量は意図して切られました。MouseListener はボタンと境界の五メソッド、mouseClickedmousePressedmouseReleasedmouseEnteredmouseExited を持ちます。MouseMotionListener は動きの二メソッド、mouseMovedmouseDragged を持ちます。O’Reilly の Java AWT Reference は理由を数で述べます。この分割により、クリックだけを聞き、数千回の移動イベントに煩わされずに済みます。この切れ目が原則の働きです。動きを追わない呼び出し側は、動きに依存しません。 残ったクリック側はなお太いです。多くの教材は五つのうち一つだけを扱い、残り四つを空にします。JDK 自身の答えも 1.1 以来MouseAdapter です。メソッドが空の抽象クラスで、関心のあるイベントだけをオーバーライドします。Oracle の Java SE ドキュメントは今もそう書きます。Java SE 262026年)時点でも、五メソッドのインターフェイスとアダプタの両方を出荷しています。WindowListenerメソッドと WindowAdapter で同じ型を繰り返します。 アダプタは便宜であり、分離された契約ではありません。呼び出し側は、自分が決して呼ばないメソッドを列挙した型に対してなおコンパイルします。MouseListener に六つ目のマウスメソッドが足されれば、直接の実装者はみな変わらねばなりません。Java 82014年3月)はデフォルトメソッドを足し、空の本体をインターフェイス自身に置けました。公開されたリスナー型は、それを軸に作り直されていません。新しい設計が写すべきは、アダプタの継ぎではなく、1997年の動き/ボタンの切れ目です。空メソッドを刷る前に、利用者の必要で分けます。限界の注記:押下、ドラッグ、解放を一組で扱う描画ツールは、それらのメソッドを一つの面に残すべきです。失敗は、無関係な聴衆を混ぜた契約であり、メソッドが二つ以上あるインターフェイス全部ではありません。

限界と失敗パターン

切り方が利用者より細かいとき、インターフェイス分離の原則は失敗します。すべての呼び出し側がいつも lockunlockisOpen を一組で使うなら、三つの一メソッド型は結合を減らさず、移動だけを増やします。それらは一つの役割です。一つの面に残します。 公開済みの太い型への後付けとしても失敗します。MouseListener がその展示です。アダプタは空メソッドを覆い、ボタンイベントに本来必要な切れ目は入っていません。1997年のアダプタを「パターン」と呼んでも、新しい API に写して安全にはなりません。写すのは動き/ボタンの切れ目であり、五つの空スタブではありません。 よくある誤用は、メソッドごとに一つのインターフェイスを作り、なお一揃いで変わる型の山です。儀式であり、分離ではありません。もう一つの誤用は、この原則を単一責任の原則の改名と見なすことです。責任はモジュールが変わる理由です。分離は呼び出し側が見せられるものです。モジュールの変わる理由が一つでも、無関係な三つの呼び出し側に同じ太い窓を見せることがあります。予期しない空メソッドは フェイルファスト ともぶつかります。プログラムは失敗しますが、太い型が普通だと広告した呼び出しで失敗します。

よくある誤解

英語名は「インターフェイスはメソッド一つ」「interface キーワードのある言語だけ」「アダプタがあれば分けなくてよい」と衝突します。
マーティンの ATM の切れ目はメソッド数ではなく利用者です。入金は入金の面を必要とし、その面に入金メッセージが複数あって構いません。同じ呼び出し側がいつも一緒に使うメソッドは、一緒に残します。誰も独立を求めていなかった一メソッド型は成功ではありません。金メッキのあとに残った埃です。
マーティンの1996年コラムが C++ の抽象クラスを使ったのは、その雑誌だったからです。同じ形は API、文書、ポータル、職務記述に現れます。枠が「任意の手伝い」「任意の添付」「任意の従業員」と言うなら、代わりの人はその枠が使わない欄やモジュールを背負わなくてよいはずです。一つの関数のために太い共有ライブラリを取り込むマイクロサービスは、class キーワードなしの同じ失敗です。
アダプタとデフォルトメソッドは入力を減らします。契約は減らしません。呼び出し側は無視するメソッドを列挙した型になお依存するので、後からの追加はなお波及します。空の本体は先送りした切れ目です。役割がそのメソッドを使わないなら、役割の型はそのメソッドに触れてはなりません。

関連概念

これらのページは同じ問題の隣にあります。複数の聴衆が一つのオブジェクトや帳票を使い、それぞれが他者の荷物を背負わずに済むにはどうするか。

単一責任の原則

モジュールごとに変わる理由は一つ。この原則は、ある利用者がそのうちどれを見せられるかを問う。

リスコフの置換原則

太い親の空メソッドや未サポートは、置換の穴であると同時に分離の失敗である。

オープン・クローズド原則

新しい呼び出し側は細い差し込み口に入る。太い口は新人が来たときに古い人を開き直す。

関心の分離

異なる決定を分けておく。分離は、それらの決定が異なる利用者にどう見えるかである。

YAGNIの原則

第二の利用者が別の切片を必要とするまで、役割を発明しない。分けすぎは投機的アーキテクチャである。

最小権限の原則

必要なアクセスにだけ依存する。この原則は権限だけでなく、メソッドとモジュールへの同じ切れ目である。

一言で言うと

呼び出し側が、決して使わないメソッドを実装・取り込み・読み飛ばさねばならないなら、契約は広すぎる。役割で面を分け、太いオブジェクトには帽子を複数かぶせればよい。