@kawasimaさんのアーキ部「データの詰め替え戦略」に参加した
自分も経験があるが、各レイヤ間をデータが跨ぐときのデータ詰め替えが多すぎる問題
詰め替え不要なのか、詰め替え必要なのか、どうやって詰め替えるのかの戦略の話だった
全てをメモできていないので、kawasimaさんのscrapboxを見ながらまとめる
まず、詰め替え戦略に関しては『Get Your Hands Dirty on Clean Architecture 』という本に以下のように書かれていると
- No Mapping (レイヤ間でモデルを共有し、詰め替えをしない)
- 2-way Mapping (各レイヤで独自のモデルを持ち、レイヤを跨ぐ呼び出しは上位レイヤが詰め替えの責務を負う)
- Full Mapping (各レイヤで独自のモデルを持ち、レイヤを跨ぐ呼び出しには専用のモデルを使う)
モデルを共有するとは
モデルを共有するとは、例えばデータアクセス層のテーブル定義をそのままEntityにするといったようなことが挙げられる
テーブル駆動設計だとそうなる可能性があるが、これだとテーブル変更=ドメインモデルの変更になってしまうので、大胆なテーブル変更がしにくい問題がある
他に、プレゼンテーション層とドメインモデルの共有もなくはないようだが、プレゼンテーション層の出力がJSONなどの場合にドメインモデルをそのままJSONシリアライズすると機密情報漏洩に繋がることがあることから極力避けた方が良いとのこと
独自のモデルを持つとは
モデルを共有すると結合度が強すぎるので、モデルを共有せずに、各レイヤそれぞれにモデルを持つということ
そして真に結合度を弱くするためには、モジュール間のデータのやり取り専用のモデル(DTO)を作ることにもなる
ただ、同じ役割のものをプログラム上でのクラスなどで表現することになる可能性があり、プログラムが冗長になる恐れがある
本当に必要なのかの見極めが必要
Balancing Couplingの統合強度
モデルを共有するのか、独自のモデルを持つのかの見極めは、Balancing Couplingの統合強度を考えると良いとのこと
DTOを作らなければ統合強度が強いモデル結合になるが、それに加えてモジュール間の距離も同時に考慮に入れるべきという考え
距離が十分近いなら統合強度が強いモデル結合でも(DTOを作らなくても)問題ないということになる
上の図より、強度が強くて距離が近いというのは高凝集のことであり、強度が弱くて距離が遠いというのは疎結合のことである
これは従来から良しとされている設計原則に沿う話であるが、よりわかりやすく説明されていると感じた
距離
ここでいうモジュール間の「距離」とは知識が共有できているかどうかになる
ただの「データ」に解釈を与えたものを「情報」だとして、「情報」を元に判断したり別の情報に変換したものを「知識」と定義するならば、「知識」が共有ができていないということは解釈に違いがあるということになる
解釈に違いがあるならば、別のモジュールとしてコーディングして結合強度を弱める必要がある
強度と距離を意識して実装を考えていきたい