ぎにょろぐ

Androidアプリ開発に関する事やその他雑記など

オブジェクト指向入門 第三章を読んだメモ

前回に引き続き、オブジェクト指向入門という本を読み進めていったので、そのメモです。第2章は当たり前の内容が多かったため、サラッと読み流す程度にしておき、3章をじっくり読んでみる事にしました。以下はその中で興味深かった事などのメモです。

概要

  • 「モジュール性が高い」とはなにかについて解説する。
    • 5つの基準(criteria)
    • 5つの規則(rule)
    • 5つの原則(principle)

5つの基準(criteria)

「モジュール性がある」と呼ぶ価値のある設計手法は、下記の5つを満たさなければならない

  • 分解しやすさ(Decomposability)
  • 組み合わせやすさ(Composability)
  • 分かりやすさ(Understandability)
  • 連続性(Continuity)
  • 保護性(Protection)

分解しやすさ

  • 複雑な問題の解決において、単純な問題に分解し、個々に作業を進められるだけの独立性を持っている事。
  • 分解しやすくない構造の例:ファイルやDBなどの初期化に関して、同じタイミングの事だからといってモジュール内の実装を知って一つのモジュールがまとめて初期化するなどといった、モジュールが自立せず情報が漏洩している構造

組み合わせやすさ

  • もともととは全く異なる環境においても、互いを自由に組み合わせる事により、新しいシステムの生産を助けるならば、組み合わせやすさは高い。
  • モジュールを作るに至った直接の目標から出来る限り独立するべき
  • トップダウンでモジュールを分解すると、組み合わせやすさが損なわれる傾向がある。それぞれのモジュールがそのコンテキストでの問題解決に密接に結びついているため。

  • ボトムアップトップダウンを組み合わせることが大事

分かりやすさ

  • 保守過程で重要
  • 悪い例:特定の順序で起動されたときのみ機能するよう設計されたモジュール。例えば、 UnixA | B | C といった形でモジュールAの後、モジュールCの前に起動した場合のみ正しく動くモジュールBなど。モジュールAやCを理解しないとBの理解は困難になる。

連続性

  • 問題の修正や小さな変更があった際に、出来る限り影響がそのモジュール内、もしくは少数のモジュールで閉じている事

    変更はソフトウェアを構築する過程における中心的な部分を締めている

感想

  • 例が分かりづらい

保護性

  • 異常な条件、エラーが起きた場合、影響をモジュール内、もしくは最悪周辺の少数モジュールにのみにしか広がらない場合、保護性が高い
  • いい例:入り口での値の検査
  • 悪い例:例外機能(Exception)。上手く使わないと保護性を損なう恐れがある

5つの規則

モジュール性を保証するために守らなければならないもの

  • 直接的な写像(Direct Mapping)
  • 少ないインタフェース(Few Interfaces)
  • 小さいインタフェース(Small Intefaces, small coupling)
  • 明示的なインタフェース(Explicit Interface)
  • 情報隠蔽(Information Hiding)

直接的な写像

  • 問題領域を記述するいいモデルが既に存在する場合、ソフトウェアとしてのコードとのマッピングを明快に保つことが望ましい。例えば、桁数に制約のある概念(注文個数)などをInt型として扱うのは、マッピングが上手く出来ていない。
  • 関連する基準:連続性、分解しやすさ

少ないインタフェース

  • モジュール同士の通信、依存を出来る限り少なくする
    • モジュール同士が呼び合う、データ構造を共有する など
  • 関連する基準:連続性、保護性
    • モジュール間の関係が多いと、変更やエラーの影響が大きくなる

小さいインタフェース

  • 2つのモジュールが通信する場合、更新される情報ができるだけ少なくする
  • 共有されるデータが大きいと、データが全てのモジュールで誤用される可能性がある
  • 関連する基準:連続性、保護性
  • ざっくりいうとグローバル変数は悪だよねという話

明示的なインタフェース

  • AとBのモジュールが通信する時、そのことがAまたはBから、あるはその両方のテキストから明らかにわかること。モジュールの接続部分が明らかになっている事
  • 関連する基準:分解しやすさ、組み合わせやすさ
  • データの共有は間接的結びつき

情報隠蔽

  • モジュールの中からいくつかを公開情報として選び、その公開情報でもってして他の世界(モジュール)から認知される事が期待される。
  • 関連する基準:連続性
    • 公開されている部分が小さいほど、モジュールに対する変更の影響は小さくなる。非公開の部分を変更しても、他のモジュールは影響を受けない
    • 例えば、テーブルの構造(ハッシュテーブル or 逐次配列)がどちらかという情報が隠蔽されていれば、どちらを採用しようと呼び出す側には直接影響はない
  • あくまで呼び出す側のモジュールは、公開されているインタフェースにのみ依存すべき(内部の実装に依存しない)
    • 情報隠蔽によって、内部の実装に依存するようにかけないようにするべき

5つの原則

  • 言語としてのモジュール単位(Liguistic Modular Units)の原則
  • 自己文書化(Self-Documentation)の原則
  • 統一形式アクセス(Uniform Access)の原則
  • 開放/閉鎖(Open-Closed)の原則
  • 単一責任選択(Single Choice)の原則

言語としてのモジュール単位

  • モジュールは使用される言語(プログラミング言語、設計言語)に対応していなければならない
  • 注文機能 = 注文モジュールとして一致していなければならない。注文モジュールなのに発注も出来てはいけない

自己文書化

  • モジュールを設計する人は、モジュールについての全ての情報をモジュールの一部として作るように努力すべき
  • モジュールの分かりやすさに影響
  • 情報隠蔽と併用することにより、詳しすぎる情報を省く。内部実装の情報までドキュメント化すると詳しすぎて情報量がパンクしてしまう。
  • モジュールの中にドキュメントを含めるべき
    • GithubのReadmeみたいな形?
  • ソフトウェアを開発する人が、モジュールそのものの内部を知らずに顧客モジュールを書けるようにするためのもの

統一形式アクセス

  • 関連する基準:連続性、情報隠蔽
  • 例えば、出金の入金のプロパティを持つ口座オブジェクトが存在した場合、口座残高プロパティを書きのように定義できる
    • 都度入出金プロパティをもとに計算する
    • 口座残高プロパティとして定義し、入出金プロパティが変更されるたびに再計算して更新する
  • このような設計はトレードオフになり、後で仕様を変更する事になる事が多い。どちらの実装でも 口座.口座残高() のように統一された形式でアクセスされると、これを使用するモジュールが気にする必要は無い。これは、連続性の基準を満たしているといえる。

開放/閉鎖の原則

  • モジュールは開いていると同時に閉じているべきである
  • モジュールに対する拡張欲求と閉鎖欲求は並行して存在する
    • 機能を作るにあたり、既存のモジュールの仕様では求める要件を満たせない。モジュールのデータ構造にフィールドを追加したり、メソッドを増やすなど行って、新たな機能を作成したい。
    • 既にそのモジュールに対しては複数のモジュールが依存している。そのため、既存の振る舞いをあるモジュールの要件を満たすためだけに修正すると、他のモジュールの振る舞いも意図しないものになってしまう。
  • クラスの継承を使えば、もとのクラスに必要な一貫性に影響を与えずに、変形に必要なものを提供することが出来る
  • 一方で、もとのモジュールの不具合を拡張によって直すべきではない。それは、直接もとのモジュールで修正すべきである。

単一責任選択

  • 開放/閉鎖の原則と情報隠蔽の原則の両方の論理的帰結
  • ソフトウェアシステムが選択肢を提供しなければならないとき、そのシステムの中の一つのモジュールだけが、その選択肢のすべてを把握すべきである
  • 特定のクラスのある概念が拡張される(例えば、区分が増えるなど)すると、そのクラスに依存するすべてのモジュールの処理を書き換えなければならない。連続性を満たしてないともいえる。
  • 責任が単一じゃないクラス = 神クラスという形で想像すると分かりやすいかも。
  • この原則は、ソフトウェアにおける知識の分散についての原則とも言える
  • 組織で採用されている手法に例えると、「必要に応じて知らせる方式」
  • この原則は、開放/閉鎖の原則の結果としてみることも出来る
  • 多相性(Polymorphism)と動的束縛(dynamic binding)がこの原則を満たす具体的なアプローチである。

感想

第二章も面白かったです。SOLID原則と似たような概念が出てきたのですが、最初の3つの原則は言語でサポートしていたり、無意識的に行っている事が多いかなと感じました。

その点、SOLID原則全てを意識するよりこれらの原則を意識するほうが難易度が低そうですね。

SOLID原則は知っているけどなぜ必要なのかはモヤモヤしていたので、「5つの基準」から段階的にその必要性から原則に発展していくこの章の構成はとても腑に落ちる形で読みやすかったです。(登場する例はイメージしづらくて読みにくいですが)

個人的には、開放/閉鎖の原則がなんとなく「修正に対しては閉じていて、拡張に関して開いていること」という言葉だけで理解した気になっていたのが、より具体的にその必要性とどのようにな設計がこの原則に則っているかがはっきりイメージしていたため、ブレイクスルーになりました。仕事でのAndroidアプリ開発におけるモジュール、Viewコンポーネントの設計に早速役立ちそうです。

一気に第二章を読み切ったのですが、しんどかったのと睡眠時間が削られてしまったので、次はもうちょっと細切れに進めていこうかなと思います。