インタフェース
   と
モジュールの
 凝集度
   と
 結合度
 柳川 一芽
            twitter: yangiYA
       WEB: http://ti.que.jp/p/
インタフェースって重要です
• 優れたインタフェース設計なら
 – 改造は簡単です
 – 機能追加は簡単です
 – 公開インタフェースを変更せず、内部実装をリファクタリング
   することでソースを改善できます。
   (インタフェースのリファクタリングは影響範囲が広い)
 – 使う人が簡単に使い方を理解できます
  • � 驚き最小の原則
 – 使う側が使いたい使い方ができます
どうやれば優れたインタフェースに
       できる?
•もっとも重要なコツは、
どうやれば優れたインタフェースに
       できる?
•もっとも重要なコツは、
状況に合わせて
よく考えること
どうやれば優れたインタフェースに
       できる?
•もっとも重要なコツは、
状況に合わせて
よく考えること
だとは思いますが、
どうやれば優れたインタフェースに
         できる?

• それ以外にあえて、

•もう少し分かりやすい
 コツをご提案させて
 いただきます。
良いインタフェースにするためのコツ

• 今からあげるポイントに気をつけて
Javadoc
(かそれに近いドキュメント)
を書いてください。
そうすると、
凝集度が高くなり
結合度が低くなります
•本日言いたいこと
  (結論)です
Javadocを書いてください
• クラスを説明する
• データが取得できない場合何が起こるか
• 取得想定されるレコードは何件かを意識する
• 想定外の件数を取得したら?
• ソートするの?
• 引数は必須?任意?
• 例外とその意味は
• 引数が本当に必要か
本日の結論
 以上です
ご紹介する話題 (結論の背景として)
• モジュールの凝集度
 – 凝集度を高くする
• モジュールの結合度
 – 結合度を低くする
• おまけ
 – オブジェクト指向
  • オブジェクト指向を見直す
 – 契約プログラミング(契約による設計)
• インタフェース
�
• このマークと一緒に、
  テーマと関係ある
  『格言』『金言』『ちょっといい話』を
  付記しました。
 –実は、今回の勉強会の内容より、
  頭にのこるのではと期待してます
その前に、モジュール って?
�   よく、各人のモジュールの意味がズレ易いので、
    あわせておきます
その前に、モジュール って?
�   よく、各人のモジュールの意味がズレ易いので、
    あわせておきます


�   1ひとまとまりのプログラム

�   ボヤっとしてますが、
    今日のところはこれでお願いします。
具体的なものにモジュールを
         当てはめて見ると
�   クラス1つ。
    と考えるとだいたい、当り

�   たまに、
    メソッドとか関数の意味でも使います
モジュール
の凝集度
モジュールの凝集度
• 機能的凝集
• 逐次的凝集
            ↑ 凝集度が高い
• 通信的凝集
                強度が   強い  
• 手順的凝集
              ---良い
• 時間的凝集
• 論理的凝集
            ↓   凝集度が低い
                強度が   弱い  
• 暗号的凝集
              ---悪い
• どのぐらい純粋か 、の尺度
モジュールの凝集度
• 凝集度のいいイメージ
 – ギュー っと機能が集まっている感じ


• 凝集度が高いと
 – モジュールの独立性が高い、つまり、
 – 修正しやすい
 – ソースを理解しやすい
 – � 単一責任原則(Single Responsibility Principle)
モジュールの凝集度
• 古いです
• 「モジュールの強度」
  という呼び方をされる場合もある

 – 1970年末から80年に出てきた概念
 – 当時は「構造化設計」
   っていうプログラム設計手法が主流
 – オブジェクト指向言語は出てきたばかり
  • 1972年 Smalltalk
  • 1972年 C++
•凝集度の説明
•凝集度の説明

• 退屈で分かりにくいですが一応一通りやります
  お付き合いください
暗号的凝集
• 関係のない機能をまとめてしまっている
• なぜ、そこにそのメソッドがあるのが理由がみつからない
• よく使うものをなんとなく集めたとか。。。


• 寸評
 – 自分がいい思っても、
   他人からは意味が分からない感じ
 – 凝集のレベルとしては、・・・もっとも低い
論理的凝集
• 似た機能が集まっているが、
  よく見ると異なる機能が1つのモジュールに含まれている。
• 機能種別(フラグなど)をパラメータで指定して、
  実は複数の機能を提供しているような場合


• 寸評
 – よく見かけるけど、if文がいっぱい。
   (残念な感じがするプログラム。凝集度も低い)
 – 機能種別が増えると収集がつかなくなる。
 – 機能追加は正しく動いているソースを修正することになりやすい
   • � オープン・クローズドの原則 (Open-Closed Principle)
 – private メソッドで、種別が on・off だけなら効果的な場合もある
   • � DRY - Don't Repeat Yourself.
時間的凝集
• ある時にまとめて実行する処理をまとめている
 – 「初期処理」 とか  「エラー処理」 とかをまとめたモジュール
   のような感じ
• 別名
 – 一時的凝集

• 寸評
 – 凝集のレベルとしてはそんなに高くないけど
   効果的な場合あり
   • 同じような機能をいろんなところで作らないですむ。
   • 近い箇所で実行するソースがまとまっていると、
     ソースを理解しやすい
手順的凝集
• 複数の機能を実施する順番を取りまとめる
• でも、共通したデータを扱ってない
• 別名
 – 手続き的凝集


• 寸評
 – 時間的凝集より、「順番」という概念を気にしている分、凝集度
   高い
 – GoFの Facade パターン って、これに近い
   • 複雑な手続きを一箇所に集めるパターン
通信的凝集
• 関係あるデータ使って、
  いくつかの機能を実行するモジュール
• 機能の順序はあまり意味がない
• 後述の逐次的凝集と分類しない場合もある
• 別名
 – 連絡的凝集

• 寸評
 – 凝集度高め
 – いいと思う
逐次的凝集
• 関係あるデータ使って、かつ、
  実行する機能の順番に意味がある。
  (通信的凝集かつ手順的凝集のようなもの)
• 前述の通信的凝集と区別しない考え方もある
• 別名
 – 連絡的凝集


• 寸評
 – 凝集度はかなり高い
機能的凝集
• 1つの関連の強い機能をまとめたモジュール
• 機能に必要なデータがある場合は
 – データのうち必要なものを機能として公開する
• 例
 – 1つのテーブルのI/Oに特化した機能・・・Daoですね
• さらに分類することもある
 – 機能的強度 ・・・ 機能を重視 (凝集度最高)
 – 情報的強度 ・・・ データ重視

• 寸評
 – 凝集度は最強
•一通り説明してみました。。
•一通り説明してみました。。

• でも正直なところ、
  とおり一遍の説明では
  イメージが湧きません
–(分類方法も何種類もあったり、似てたり
 するし)
•凝集度をイメージで捕らえて
 みようと思います
•まずは、
 リファクタリングして、
 凝集度が
 低いものを高くする
 イメージ
凝集度 低
凝集度 低
凝集度 低
凝集度 高
• 関係が深い機能は1箇所に

• 異なる機能は別々に

• グチャグチャに絡まっているものをほぐす

• 呼び出す側と呼び出される側は明確に
 – (コールバックなどは控えめにね)
• 次は、
  新しい機能を追加した場合の
  モジュール改造 イメージ

• 凝集度が
  高い場合と、低い場合とを
  比べます
低い凝集のモジュール改造。。
低い凝集のモジュール改造。。
–白丸はモジュール
–白丸の大きさはモジュールの規模
–黒丸は改造
–黒丸の大きさは改造の規模

• イメージです
低い凝集のモジュール改造。。
高い凝集のモジュール改造 1
高い凝集のモジュール改造 2
高い凝集のモジュール改造 3
イメージでした
モジュール
の凝集度

 おわり
モジュール
の結合度
モジュールの結合度
• モジュールとモジュールが
  どのくらい強く結びついているか


• 『疎結合』という言葉は
  「モジュールの結合度」が低いということです


• 疎結合を関係が深いキーワード「Webサービス」
 – 「Webサービスにしたから疎結合」ではなく、
   「疎結合なインタフェースでWebサービスを提供する」
   であるべきです
モジュールの結合度
    データ結合
•
•   スタンプ結合
             ↑ 結合度低い
               良い
•   制御結合
•   外部結合
•   共通結合
•   内容結合     ↓   結合度高い
                悪い
• どのぐらい、独立しているかの尺度
• 一通り説明します

• 凝集度の説明よりは、
  分かりやすいのではと思いますが、
そんなに分かりやすくないです。

• お付き合いください
内容結合
• 絶対番地を用いて直接相手モジュールを参照したり、相
  手モジュールに直接分岐する



• 寸評
 – むしろ、『モジュール』とは呼んでいけないレベル
 – goto のある言語では、これができてしまう
 – Javaなど goto のない言語ではまずできない、
   できたら逆に芸術的。
共有結合
• 共通領域(グローバル領域)に定義されたデータを参照する。


• 寸評
 – 結合度が高い。保守開発の影響度が広くて、改修しにくい。致命的
 – マルチスレッドで予測不能の振る舞いをするリスクあり。
   (安全に使えない)
 – Javaで見かけるパターン
   • staticフィールド、シングルトンオブジェクトを不用意に使ったもの
   • 大きなオブジェクトの参照を呼び出し先に渡しまくったり、
     public でどこからでも参照できたりさせる
 – 正しく設計したシングルトンパターンオブジェクトでは使います。
    • 属性を持たないロジックだけのシングルトンは、
      共有結合とは関係ない。
外部結合
• 必要なデータだけを外部宣言し、ほかのモ
  ジュールから参照を許可し共有する。

• 寸評
 – 共有結合とほとんど同じ。改修しにくい。
  • 利用する側が、使う項目を明確にして、
    その項目以外使わなということが分類上違う模様
    (でも、保守開発で影響度をきにしないといけなくなること
    は、ほとんど変わらないと思う。)
制御結合
• 機能コードなど、モジュールを制御する要素を引数
  として相手モジュールに渡し、モジュールの機能や
  実行を制御する。
• モジュール凝集度の論理的凝集度がこれに相当
  する。

• 寸評
 – 論理的凝集とおなじく、if文がいっぱいで、
   よく見かけるけど残念なレベルです。
 – 論理的凝集の繰り返しになりますが、
   private メソッドで、種別が on・off だけなら効果的
スタンプ結合
• 相手モジュールで、
  構造体データ(レコード)の一部を使用する場合でも、
  構造体データすべてを引数として相手モジュールに渡す


• 寸評
 – Daoで取得したテーブルのDTOをそのまま引数で渡すような
   場合が該当する。必要な項目を限定すべきだが、面倒なので
   ついやってしまう。(プログラムを作るうえで面倒だという感覚
   は重要でトレードオフの対象になると思う)
 – 引数を渡した先で書き換えられる危険を増やしていることに留
   意する必要がある。(難解なバグになるかも)
   • � 防御的コピー.
データ結合
• 相手モジュールをブラックボックスとして扱い、
  必要なデータだけを引数として渡す。


• 寸評
 – 結合度は最も低い。
   全部これにできることが理想
 – 値渡しなら、呼び出し側で引数が変えられる心配なし
 – 参照(ポインタ)渡しの場合は、
   引数を渡した先で書き換えられる危険性がある
•結合度も
 イメージで捕らえてみようと思
 います
結合度 強い



A機能            B機能
結合度 弱い



A機能            B機能
A機能            B機能
             インタフェースが
             コンパクト


• パラメータと戻り値の項目数が少なくすれば、結合
  度が低くなります(ざっくり言ってみました)
モジュール
の結合度

 おわり
•オブジェクト指向
    について少し
思い出そう:オブジェクト指向

• オブジェクト指向といえば思いつくキーワード
思い出そう:オブジェクト指向

• オブジェクト指向といえば思いつくキーワード
 – カプセル化
 – 継承 (インヘリタンス)
 – ポリモフィズム、・・・




• でも、一番大事なことは。。。
思い出そう:オブジェクト指向
• 『データ』と『処理』を
  一まとまりにする

• メッセージの協調(連続)で、
  機能を実現
思い出そう:オブジェクト指向
• 『データ』と『処理』を一まとまりにする
 – データ
  • 意味のあるデータの集まり
 – 処理
  • メッセージとかメソッドとかサービスとか呼ばれるもの


• メッセージの協調(連続)で、機能を実現
 – オブジェクトからオブジェクトへ、
   (短い)メッセージを送る行為が繰り返され、
   全体の機能を実現する。
 – メッセージを送る ≒ メソッドを呼び出す
思い出そう:オブジェクト指向
• 『データ』と『処理』を一まとまりにする
 – データ
                   機能的凝集
  • 意味のあるデータの集まり
                   高い凝集度
 – 処理
  • メッセージとかメソッドとかサービスとか呼ばれるもの。


• メッセージの協調(連続)で、機能を実現
 – オブジェクトからオブジェクトへ、
   (短い)メッセージを送る行為が繰り返され、
                           スタンプ結合
   全体の機能を実現する。             データ結合
 – メッセージを送る ≒ メソッドを呼び出す    低い結合度
思い出そう:オブジェクト指向

• オブジェクト指向って、

 –凝集度を高くし、
 –結合度を下げる


設計手法です。
いつも使っている
Javaって、

オブジェクト思考
ですか?
(使ってない人も使ってることにしといてください)
オブジェクト指向設計
         とは言いにくいケース
• クラスにstaticメソッドしかない
 – ユーティリティライブラリ

• フィールドとgetterとsetterしかない
 – データトランスファーオブジェクト(DTO)

• メソッドはあるがフィールドが1つもない
 – サーブレットクラス、
   シングルトンのビジネスロジック、
   ステートレスBean(EJB)
オブジェクト指向で全部作ら
          なくてもいいけど・・
• オブジェクト指向、全然使ってないように感じます


• DTO、や、StrutsのFormにちょっと編集メソッドを加える
  と、オブジェクト思考っぽくなります。
  (すごく簡単。手始めとしてはオススメ)
 – getPrice() ==> "10000"
 – getPriceForView() ==> "10,000 -"
   • こっちのほうが、タグを使うより簡単にコードの重複が減らせるます
      – � DRY (Don't Repeat Yourself.)
ぜひ、
オブジェクト指向
    を
 見直してみて
  ください
インタフェース
どんなインタフェースが良いのか
• 結合度をを低くする
 – 引数はすくない方がよい。引数なしが最も低い
   • DTOを渡すのは引数をたくさん渡すのと同じ
   • 機能を実現するための必要最小限の引数を
• 返却値は(できれば)凝集度を高く
 – こちらはそんなにがんばらなくてもいいと思います
• インタフェースで使う人が機能を想像できる
 – � 驚き最小の原則
• 「作りやすいから」ではなく「使いやすいから」で決める
 – � TDD(Test Driven Development) - 作る前に使え
インタフェースを重要視する
• 契約プログラミング (契約による設計)
 – 『事前条件』『事後条件』『不変条件』を明らかに
 – インタフェースは使う側の持ち物。
   作り手側の都合で簡単に変えてはいけない。


• 条件を明らかにするコツ
 – 条件をシンプルに。そのためには。。。
   (繰り返しですが)
  • 凝集度を高める
  • 結合度を低くする
良いインタフェースにするためのコツ

• 今からあげるポイントに気をつけて
Javadoc
(かそれに近いドキュメント)
を書いてください。
そうすると、
凝集度が高くなり
結合度が低くなります
Javadocを書いてください
• クラスを説明する
• データが取得できない場合何が起こるか
• 取得想定されるレコードは何件かを意識する
• 想定外の件数を取得したら?
• ソートするの?
• 引数は必須?任意?
• 例外とその意味は
• 引数が本当に必要か
•本日言いたいこと
   (結論)に
  戻ってきました
•個別のポイントに
 コメントしていきます
•が、そのまえに
全部Javadoc書くのは面倒です。。。
• 以下のような部分を優先して
  Javadocを書くのをオススメします。

 – protected 以上のクラスとメンバーに


 – より重要な機能が記述されているクラスに
  • 「サービス」とか「ビジネスロジック」とか
    「Model(MVCパターンのM)」とか
    呼ばれるクラス
•個別のポイントに
 コメントしていきます
クラスを説明する
• 何の機能かを簡潔に書きます(1文で何者なのかを表現
  できればより良い)
 – 説明に合致しない機能が定義されていませんか。
   詰め込みすぎではないですか
 – 説明した機能を実現していますか


• ポイント
 – 説明できなければ設計がおかしいのかも
 – 凝集度が低いとうまく説明できません
データが取得できない場合
             何が起こるか
• 返却例
 – NULL
 – 空のリスト
 – 例外
 – Nullオブジェクトパターン のオブジェクト


• ポイント
 – 『事後条件』を明らかにしてください
取得想定されるレコードは何件かを意識
        する
• まず、1件返却なのか複数件返却なのかを明確に
 – 1件なら、Listや配列を返してはいけない
 – 複数件なら返却件数を意識してください。
   • 20件程度、 1000件程度、 とてつもなく多い
 – 返却件数に限界があるのならドキュメントに明示してください
   • システム的に限界は
   • 運用的に限界は

• ポイント
 – 『事前条件』『事後条件』を明らかにしてください
想定外の件数を取得したら?
• 考えていないはだめ、明示することが大切
 – 例外?
 – falseを返却する?
 – 先頭n件を返却する
 – その他具体的に


• ポイント
 – 『事後条件』を明らかにしてください
ソートするの?
• ソートするなら、ソートキーを明示してください。
• 複数件返すのにソートしないのであれば、
  順番が保証されないことを明記してください。


• ポイント
 – 『事後条件』を明らかにしてください
引数は必須?任意?
• 任意なパラメータを避ける
 – 「オーバーロード」とか「デフォルト引数」とかを使って
• 任意はパラメータを用意する場合は、
  設定するか否かで何起こるか明記してください
• どれが必須で、どれが任意か明示してください

• ポイント
 – 結合度を低くしてください。
   • 任意なパラメータは実質的に制御結合(結合度が高い)になっている
     可能性があります
 – 複数任意なパラメータがあると、
   組み合わせの数は爆発的に増えて説明困難になる
例外の意味は
• スローする例外の意味を説明してください
 – ドメイン上の意味がある異常
   • 意味ある例外を作ってスロー
 – 処理の継続ができない異常
   • 汎用的のランタイム例外をスローするのがいいケースが多い
    – バグ、環境障害、のケースはこれ
• 例外がない言語の場合、呼び出し元に異常を伝える方
  法を明示する

• ポイント
 – 『事後条件』を明らかにしてください
引数が本当に必要か

• メソッド内で使っていない引数は無いですか
• DTOを渡すのは、引数をたくさん渡していることと
  同じです。
• 引数にとらなくても、
  メソッド内で何とかならないか考える。
 – 何とかなるなら、引数にすべきか否か再考する

• ポイント
 – 結合度を低くしてください
 – � KISSの原則 (Keep it simple, stupid. or Keep it short and
   simple.)
個別のポイント
  おわり
最後に
ケーススタディー
を少しやります
ケーススタディー:引数検討
• ケース
 –「キー1」を渡して情報を受け取る
  「WebサービスA」の
  クライアントを作る

 <<DFD図>>
            サービス
  キー1         A    取得結果
ケーススタディー:引数検討
• インタフェース1
 – 引数
  • キー1


• インタフェース2
 – 引数
  • キー1
  • WebサービスのURL
ケーススタディー:引数検討
• Webサービスクライアントの本質を考えてみる

 – 重要なのは、「キー1」を渡して情報をうけとること
 – WebサービスのURLは重要でない。
  • 変わってもいいもの
  • 開発環境によって変わりそう
  • テストでは、テスト用のURLを使いたくなりそう
ケーススタディー:引数検討
• インタフェース1
 – 引数
   • キー1

• インタフェース2
 – (インタフェースはコンパクトにと説明しましたが、
   こちらをオススメします)
 – 引数
   • キー1
   • WebサービスのURL

• インタフェース1を作りたい場合、
  インタフェース2 を呼び出して作ればいい
インタフェース

 おわり
おわりに
• プログラミングは感覚が大事だと思います。


• 感覚を磨くには、
 – たくさんコードを読む
 – たくさんコードを書く
 – 先人のノウハウを吸収する
 – そして、よく考える


• 地道な積み上げ大事
• 今日の勉強会の内容が、
  今後の皆さんの何らかのきっかけ
  になってくれたら幸いです
ご清聴ありがとう

 ございました

モジュールの凝集度・結合度・インタフェース