本書は、プログラムにおけるインターフェース設計へアドバイスを与えるものです。GUIやデザインの話ではありません。高凝集度で疎結合な設計を行うためにインタフェース設計をどのように進めたらよいか、どのように考えてインターフェースを作れば良いかなどを説明しています。
システム開発というのは複雑な作業です。その複雑さを少しでも解消するために分割して統治せよ(Divide and Conquer)という理論を用いることが良いことだとされています。このときに大切になってくるのが「凝集度」と「結合度」になります。
凝集度は高いほど良い、つまり責任範囲が明確でが軸ぶれないほどよいです。結合度は低いほど、つまりそっちはそっちで勝手にやっててねとできるほどよいです。高凝集で低結合(英語で言うと「High Cohesion and Low Coupling!」)なプログラム部品にするために必要なのが「良いインターフェース」なのです。本書は、この良いインターフェースとは何か?どうやって良いインターフェースを設計するか?を解説するものです。
本書の対象読者は、プログラム経験があり設計に興味がある人、DI(Dependency Injection)って流行ってたけど未だに何が良いのかわからない人、テスト容易性が大事って聞くけどどうやって設計したらいいかわからない人です。
200ページくらいしかなく、かなり薄い本になっていますのでサクサク読めると思いますが、実はあまり詳しい説明というのが載っていません。内容が薄いのではなく、説明が薄いのです。「こんな場合こういう考えでインターフェースを切ると良いよ。作り方は二種類ある。長所はこれで、短所はこれ」みたいな説明が多いように思えました。
それでもかなりの良書の部類に入ると思います。さらっと読んで、良く理解できなかった部分は先輩に聞いたり、Webで質問したりして、自分なりに噛み砕いていく。そういう読み方をする本かなと思います。
本書に出てくるキーワード
インターフェイスの三原則
- インターフェイス実装は、そのメソッド名が示す通りの処理をしなければならない
- インターフェイス実装は他に危害を加えてはならない
- インターフェイス実装は、責務を果たせない場合にそれを呼び出し元に伝えねばならない
つまり、「名前どおりの処理をし」、「後始末は自分でする、自分がエラーでも他に迷惑をかけない」、「自分で処理できないときは、呼び出し元に誤りをいれる」ということ。
契約(Contract)、契約による設計(Design By Contract)
インターフェイスの呼び出し元とインターフェイスとの間で交わされる約束のこと。事前条件、事後条件、不変表明の3つからなる。
事前条件はインターフェイスの呼び出し元が守らなければならない条件で、事前条件を満たない状態でインターフェイスを呼び出すと正しく動作しない。
事後条件はインターフェイスが守らなければならない条件で、事前条件を満たした状態で呼び出しが行われた場合に満たさなければならないもの。事後条件を満たせない場合は Java であれば例外をスローしたりする(原則3)
不変表明はインターフェイスのインスタンスが満たさなければいけない内部状態を表すもの。
データインターフェイスとサービスインターフェイス
データインターフェイスとは、属性の設定や取得のメソッドで構成されるインターフェイスのこと。JavaBeans などが該当する。
サービスインターフェイスとは、処理を行うメソッドで構成されるインターフェイスのこと。よくある3階層アーキテクチャのサービス層を司るものや、GUIのボタン押下で呼び出されるメソッドなどを持つもの。
エンティティ、バウンダリ、コントロール
エンティティは、データインターフェイスに相当する。
バウンダリは、サービスインターフェイスに相当する。主に GUI やユーザインターフェイスとして動作する種類のサービスインターフェイス。
コントロールも、サービスインターフェイスに相当する。主にビジネスロジックやビジネスルール、サービスを処理する種類のサービスインターフェイス。
ステートフルインターフェイスとステートレスインターフェイス
インターフェイスも状態を持つことができる。
ステートフルインターフェイスは、メソッドの呼び出しに順序があり、呼び出し順で状態が変わるもの。
ステートレスインターフェイスは、メソッドの呼び出しに順序がなく振る舞いが変わらないもの。
凝集度
責務の似具合のこと。共通のコンセプトに基づいたメソッドばかりで構成されたインターフェイスは凝集度が高いといえる。
結合度
相手がいないと動作できない具合のこと。相手のモジュールの処理に依存していない場合には結合度が低いといえる。
継承とインターフェイス
継承は機能の連鎖。is_a (である)や is_kind_of (の一種である) で表されることが多い。共通の処理や属性をまとめる際に使える。
インターフェイスはロールの連鎖。インターフェイスの継承は provides-a (提供する)で表されることが多い。
(適当に書いてみたけど、説明が難しいというか感覚的な感じなので、本書を読んでください。。。)
手続き型インターフェイスとドキュメント型インターフェイス
リモートインターフェイスとしてのインターフェイスを考える際の種類。
手続き型インターフェイスは、メソッドの処理を定義するタイプのインターフェイス。CORBA や RMI なんかがそれ。
ドキュメント型インターフェイスは、データメッセージをやり取りするタイプのインターフェイス。JSON や XML なんかがこれに当たる。
感想
良書だと思いました。ただし、インターフェイスってこういうものだっていう考えがある人が読まないと、頭が混乱してくる気がしました。それは、インターフェイスという言葉がいろいろな意味で使われているからです。Java のインターフェイスを表していることもあれば、相手とのやり取りそのものをインターフェイスといったり、メソッド定義もインターフェイス定義だよねというような、広い意味でインターフェイスといったりと。
インターフェイス設計の総おさらいのような感じで読むこともできるし、おお!こんな考え方があったのか!という新しい発見もあるしという感じです。
本書には書いてなかった気がするもの
インターフェイスの定義は呼び出し元がするべし!
これは私の持論(?)ですが、インターフェイスの定義というものは、使う側が指定するべきだと思っています。哲学とか入ってきてしまいますが、「自分が今ここにいるのは、他人がそう認識しているから」というイメージです。
「依存関係逆転の法則」的な考え方ともいえると思います。
- Tips
- 「インターフェイスが変わるときは、ユーザの要求が変わったときである。」