集約・集約ルート(DDD)
クリーンアーキテクチャ、DDDの学習をしていて、「集約・集約ルート」という言葉が理解できなかった。
集約だから、何かを一箇所に集めるのかな?そして、集めたものの根本が存在するのかな?という認識だった。
データ中心でモデリングを行うと、
- ドメインモデルの整合性の確保がアプリケーション層の実装次第になる
- 保存先が変更になった際にアプリケーション層も修正することになる
といったように、ドメイン層→アプリケーション層と依存方向が向かってしまう。変更頻度が少ない方が多い方に依存することは、コード修正の回数が増えてしまう、保守が面倒という点で問題になる。
そこで、ドメインモデル中心の「集約・集約ルート」という分離方法が効果的になってくるそう。
集約とは?
トランザクション整合性を保ちながら更新を行うオブジェクトのまとまり。
集約は主に「エンティティ」から構成されている。(IDで識別することが重視されるため)
「集約ルート」しか操作してはいけないというルールがある。
集約ルートとは?
外部から集約を操作できる唯一の場所。
そうすることで集約全体の整合性を担保してデータ更新することができる。
集約の例
送金と送金先口座のエンティティがあった場合に、外部から更新できるのは集約ルートである「送金エンティティ」からのみ。「送金」という一連の動作で必要なオブジェクト群に途中で変更が生じて整合性がずれることを防止する。
集約: 送金
集約ルート: 送金先口座
集約ルートからしか操作してはいけない例
userというオブジェクトがあったとしたら、セッターで直接変更してはいけないが、メソッドを通じてなら変更を許すという考え方。
class User
attr_reader :name
def initialize(attrs)
@name = attrs[:name]
end
def change_name
raise NotImplementedError
end
end
user = User.new(name: "太郎");
user.name = "次郎"; // ×
user.change_name = "次郎"; // ○
メリット
メソッドにはすでにnull: falseのようなバリデーションロジックがかかっていると想定される。そのため、メソッドを通して値へ変更を加えるとデータ整合性を保つことができるから。
外部から内部のオブジェクトを直接操作せず、それを保持するオブジェクトに依頼することで不変条件を維持できる。
これを「デメテルの法則」とも呼ぶ。
後書き
クラス設計の時も似たような概念があった。「カプセル化」である。
attr_readerで属性のカプセル化をした目的は、属性の持つ値を更新できる箇所を一つにしてDRY原則を守ることだった。
集約も、値を更新する場所を一つに決めることでデータ整合性を保つ目的がある。
似ている。
現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法 | 増田 亨 |本 | 通販 | Amazon
オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 | Sandi Metz, 髙山泰基 | 工学 | Kindleストア | Amazon