ドメイン駆動設計と相互依存性

@j5ik2o https://t.co/CM8DigG9qZ かなり参考にしてます! 例えばユーザは複数グループに所属でき、ユーザの所属一覧とグループのユーザ一覧と両方欲しい場合、所属エンティティの属性にユーザとグループ内の値オブジェクトをコピーすればいい感じですかね…
2014-03-19 13:35:51
@pnkts あ、だいたいわかります。ユーザはグループではないのでグループを表す属性は持ちませんし、その反対も同様です。なので、ユーザには所属する複数のグループへの参照を持つか、グループが所属される複数のユーザへの参照を保持するかという話になりますね、たぶん(続く
2014-03-19 13:49:39
@pnkts まず相互依存の関連は維持管理がシビアなので最初から前提にしないで一方向になるようにしましょう。つまり便利な関連は排除し本質的な関連だけにする。仮にユーザにグループへの参照があるとした場合で説明すると。
2014-03-19 13:54:05
@pnkts ユーザとグループはそれぞれ独立したグローバルな識別子を持つエンティティであり、集約です。ユーザには所属するグループへの参照としてグループIDの集合を属性に持ちます。このグループIDの値はユーザの値です。なので集約内の属性としてIOすれば言い訳です。
2014-03-19 13:56:58
@j5ik2o 識別子自体は参照ということなので集約間で共有できるわけですね。モヤモヤしていたところが解消されました!ありがとうございます!
2014-03-19 14:02:00
.@pnkts 言語上の参照で保持しちゃうと集約内部か外部かが見分けがつかないので基本識別子を使うしそれはランタイム表現なんですよ。集約であるエンティティはランタイム上のライフサイクルを超えうるのでたとえばストレージなどに存在する場合は表現できなくなります。なのでIDがよいです。
2014-03-19 14:06:56
@j5ik2o ユーザが値オブジェクトだったら匿名性バッチリですね! つまり所属というエンティティを新たに作るとユーザとグループの境界が曖昧になり不味いので、どちらかに片方の参照を集約しておくということですかね。
2014-03-19 14:11:20
@pnkts ユーザは値オブジェクトになりますか?見分ける対象の場合はエンティティにしないとだめですよ。 http://t.co/8ZKZiFGmoi
2014-03-19 14:55:41
@pnkts 実装から考えるのではなく、ドメイン層というのは概念から考えないとダメなんですよね。ユーザが値オブジェクトかエンティティかはどういう概念のものを扱おうとしているか最初に整理しないといけませんね。実装都合で、やーこれはVOだな、Eだなというものではないのでw
2014-03-19 14:57:57
@j5ik2o たしかに順序がありますね。モデルと設計は一致させなければならないのに早々と実装に振り回されると釣り合いが保たれないです。
2014-03-19 15:26:32
@pnkts 仮にユーザがVOの場合は見分けが付かなくなります。ユーザを認証するようなアプリケーションの場合はそれぞれのユーザを識別するわけですが、VOだとこれが不可能になりますね。最初にユーザとは何か?とかどういう使われ方をするモデルなのかを定義しないといけませんね。
2014-03-19 14:59:50
@j5ik2o ユーザのように明らかに要識別の物はわかりやすいですが、今までRDBMの機能に縋ってた身としては関連テーブルまでもEと錯覚してしまいがちです。
2014-03-19 15:32:13
@pnkts class User(id: UserId, groupId: GroupId, name: String); class Group(id: GroupId, name: String);
2014-03-19 15:08:43
@pnkts UserRepository#findById(uid): User; UserRepository#findByGroupId(gid): Seq[User]; GroupRepository#findById(gid);
2014-03-19 15:10:13
@pnkts その属性がいい感じにRDBMSのテーブルにマッピングされるように考えればいいですね。UserRepository#findByGroupIdを可能にするならばインデックスを効かせたいのでUSERテーブルとUSER_GROUPIDSテーブルみたいな感じにするかな。
2014-03-19 15:38:03
@j5ik2o かなりすっきりしてきたと思います。集約のルートのみにしかリポジトリが存在しないことでクライアント側から好き勝手アクセスして混沌化することを防げるのも納得してきました
2014-03-19 15:45:22
@pnkts 概念があって実装クラスって感じなので、最初の概念がデカいと集約自体も実装がデカくなるので、I/Oもボトルネックになりやすいと考えるとよいですー。実は二つのエンティティが隠れているのでは?ということで考え直すことで性能もよくなったりします。
2014-03-19 15:48:54
@j5ik2o ありがとうございます。リポジトリ層で完結できればクエリのチューニングで対応してそもそも規模が大きすぎるならモデルの見直しを意識していこうと思います。
2014-03-19 15:55:12