Introduction
プログラムをレイヤーに分ける意味は以下の二つがある。
1. プログラム全体の理解を助ける
2. レイヤーごとの開発を可能にして、開発効率を上げる
1. プログラム全体の理解を助ける
(これは書いてあったことじゃないです。)
例えば、美容院(レイヤーに分けている例)と床屋(レイヤーに分けていない例)で対比します。
自分が小学生の時に行っていた床屋では、散髪するそれぞれの椅子の前に髪を洗い流す台がありました。
自分が今行っている美容院では、散髪する椅子と髪を洗い流す台が別々のスペースにあります。
ちょっと無理やり感ありますが、床屋の場合だとお店に入った瞬間には何をおこなのかわかりづらいですね。
椅子の目の前に洗面台があります。洗面台があるので、そこで髪を洗うのだろうということはわかります。
しかし、以下のような憶測を可能にしてしまいます。
1. 切った髪が床に散らばると片付けるのが面倒だから、洗面台に頭を向けて切るのか?
2. 髪切る時に手に髪がついちゃうと施術がしづらくなるので、施術者が髪を手から洗い落とすために使うのか?
その反面、美容院は散髪スペースには余計なものがないので変な憶測をうむ余地がありません。
2. レイヤーごとの開発を可能にして、開発効率を上げる
先ほどの美容院と床屋の対比を使いまわします。
例えば洗面台を最新のものにしたいとします。
床屋(レイヤーに分けていない例)では、散髪スペースと洗面台の場所が分かれていません。そのため、洗面台を改修するとなると散髪スペースも工事に巻き込まれてしまいます。お店を休む必要がありますね。
しかし、美容院(レイヤーに分けている例)の場合はどうでしょうか。
散髪スペースと洗面台が分かれているので、洗面台を改修しても散髪を行うことは可能です。
レイヤーを分けると、お店の一部の改修と営業を同時に行うことができるというわけです。
How?
さて、レイヤーを分ける時に注意しないといけないことがあります。
レイヤーはむやみに分けても意味がありません。
多すぎると開発効率を下げるばかりか、(レイヤー間で位置が異なる場合)パフォーマンスの悪化を引き起こすこともあります。(ネットワーク通信が増えてしまうため)
少なすぎると並行して開発を行うことができなくなるので、レイヤーに分ける本質的な目的を達成できません。
レイヤーを分ける指標
通常は以下の指標をいくつか複合してレイヤーを分ける
1. ハードウェア間の物理的な距離
=> RemoteとLocalを分ける
2. 変更頻度
=> viewはpersistenceに比べて頻繁に変更されるため分ける
3. Abstraction dimension(抽象化した時の対象で分ける?)
=> View/Application Logic/ Persistenceで分ける。表現とロジックとデータで分けている様子
4. Granularity dimension(粒度で分ける?)
=> Business object / Business process で分ける。ドメインのデータとその処理で分ける。
現在開発中のAndroidで言えばdomain/modelとdomain/interactorで分ける?
- model:データの値自体を表現する。(例えばAgeオブジェクトは18才以下か否かを表現する)
- interactor:データのビジネス的な意味を解釈する。(例えば18才以下か否かがサービス的に意味するところ、つまりアプリの機能をある程度制限しなければならないことを解釈する。)
レイヤー間の取り決め
レイヤー間はinterfaceを用いてやりとりを行う。 (Explicit interface)
レイヤー内でinterfaceの実装を完結する。 (Encapsulated implementation)
Bridge or Object Adapter を用いて、インターフェースと実装をつなぐ。
低レイヤー(DBアクセスなど)は高レイヤー(ビューなど)の機能に頼ってはいけない。
参照が許されるのは、高レイヤーから低レイヤーの方向のみ。
例えば以下の二つのレイヤーしかない場合を想定します。
1. ビューレイヤー
2. DBレイヤー
この場合ビューからDBレイヤーにアクセスするためには、DBレイヤーのinterfaceに対して問い合わせを行います。
DBレイヤーからビューにリクエストの応答を返すときは、リスナー等を用いてリスポンスを返します。 (Observer, Commands, Messages)
高レイヤーへの参照が許されていないため、ビューレイヤーのinterfaceに問い合わせを行うことは許されていないためです。
この制限がある理由としては以下の2点です。
- 構造が複雑に絡み合ってしまうため
- 低レイヤーの移植を可能にするため
What's next?
Explicit Interfaceについて!
※ は関連のあるパターンを示しています。