そもそもレイヤーとは
- ソフトウェアのサブシステムはレイヤの積み重なったものと考えられる
- 各レイヤはその下のレイヤに依存する
- 下位のレイヤは上位のレイヤを意識しない
- 各レイヤは上位のレイヤから下位のレイヤを隠蔽する事が多い
例えば通信するアプリケーションのレイヤーを考えてみる。ここではアプリケーション全体ではなく、システムの大枠をレイヤーとして捉える。
アプリケーションはTCP通信を行う、TCP通信は光ネットワークを通してデータの送受信を行う。この時、光ネットワークが何らかの理由によってメタル回線に置き換わっても、無線通信に置き換わっても、TCPやアプリケーションといった上位レイヤには影響を与えない。
次に、アプリケーションのレイヤーを考えてみる。
アプリケーションのレイヤは主に
- Presentation Layer
- Domain Layer
- Data Source Layer
の3つに分類できる。この場合も、前の例と同じで「Data Source Layer」でのデータ取得先がOracleからMySQLやPostgreSQLに置き換わったとしても、その他のレイヤには影響が出ないことが分かる。
レイヤー化のメリット
- 他のレイヤを知らなくても、例えば光ネットワークに関して知らなくても、TCP上のアプリケーションを作成することができる。
- 代替実装でレイヤを置き換えることができる(光→メタル)
- レイヤ間の依存を最小にできる(光をメタルにしても他のレイヤに影響が出ない)
- レイヤを構築すると、高水準サービスがそのレイヤを使用できる
レイヤー化のデメリット
- レイヤは一部の物事をカプセル化してしまう
例えば画面上に項目をひとつ追加する場合、全てのレイヤに情報を追加する必要がある。 - レイヤ化するとパフォーマンスを損ねる場合がある。
アプリケーションのレイヤ化で起きる問題
上位、下位の関係が守れていればアプリケーション層からインフラストラクチャ層への依存といった層を跨いだ依存も許されるため、以下のような設計も可能となる。
ここで問題となるのはData Source LayerのクラスがDomain Layerのクラスに依存してしまう点。Domainに「Hogeクラス」を定義していた場合、Datasource LayerのHogeDaoはDBからデータを取得したあと、Hogeクラスを返す作りとした場合にDomain Layerに依存してしまうことになる。
レイヤーアーキテクチャでは「下位のレイヤは上位のレイヤを意識しない」つまり、下位のレイヤのモジュールが上位レイヤのモジュールに依存してはいけないので、SOLIDの1つである依存関係逆転の原則(DIP)を使って解決する。
DIP+レイヤーアーキテクチャ
依存関係逆転の原則(DIP:Dependency Inversion Principle)を適用すると、先程の上位レイヤ、下位レイヤの関係が変わってくる。
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.https://en.wikipedia.org/wiki/Dependency_inversion_principle
A.上位モジュールは下位モジュールに依存すべきではない、双方とも抽象に依存すべき。
B.抽象は詳細に依存すべきではない、詳細は抽象に依存すべき。
この法則を基に、依存関係で問題となった箇所を修正する。
Domain LayerにData Source Layerのinterfaceを定義し、DataSource Layerで実装することで、Hogeクラスの依存を無くした。
参考
http://www.atmarkit.co.jp/fdotnet/designptn/designptn07/designptn07_01.html
https://qiita.com/nel215/items/40b18dba41ab7b3a9564#%E6%A6%82%E8%A6%81
マサカリはお手柔らかにお願いします。