#昨日、こんな記事がありました。
@bigwheel 集約の境界と整合性の維持の仕方に悩んで2ヶ月ぐらい結論を出せていない話
ヒャッハー新鮮な話題だあ!
とてもいいですね。やはり議論には具体的な議論対象が必要です。
ただ気になったのが、ユーザにユーザ自身に関する情報と、組織がユーザに対して持っている情報が両方ユーザに有る事です。それって同じところにある必要あるでしょうか?
###名簿は人間を含みません
この組織が所属してる人を使って何かをするってんならそりゃ集約でしょう。例えばこれが野球だとか戦争だとかならばチームとして統制の取れた動きが必要です。または関連したデータでもいいです。一般に明細を集約の中に含めるのは、集約が明細の合計である必要があるからです。例えばある伝票はその明細の合計として振舞うので伝票を送るならその明細も同時に送る必要があります。
ですがここで行っているのは人数の管理だけです。この組織は単なる集合とかコンテナであり関連するデータとは言い難いものがあります。集約じゃないんじゃないでしょうか?そういや合成集約ですが去年こんな記事を書きました。組織に人間を所属させるではなく名簿を管理すると考えれば十分じゃないですかね?
###ユーザが組織に使用権があるか問い合わせるモデル
というわけで組織を名簿にして、対象のユーザから「俺使える?」と問い合わせるモデルを提案します。組織のほうにユーザのリストとその使用権を保持します。ユーザと組織を別集約にするという事ですね。
これは一種の循環参照になって気持ち悪いと言えば気持ち悪いのですが、ユーザ名簿からユーザへはIDを持っているだけでメッセージを飛ばしません。オブジェクトの参照もしません。つまりオブジェクトグラフではないことになります(強引?)。
やりとりするIDと使用権は値オブジェクトなので問い合わせる分には問題はないでしょう。例えば名簿にユーザID,使用権、登録順になるなんかを入れて、問い合わせに応じてそのユーザが使用権あるか&登録順で数えて人数のうちに入っているかを返せば万一人数がオーバーしても大丈夫です。
###ユーザに有効無効を持たせるとえぐい
ユーザが有効であるか無効であるかを決めるのは組織なのでユーザ側に持たせるのはお勧めしかねます。具体的にはユーザ名やメールアドレスはユーザが変更できるのに組織が有効無効を変更できるのはそれ別問題じゃないの?ということです。こうすることで例えば組織がユーザ数を拡大したときとかに待機ユーザを有効にする、なんてのが組織の名簿上でできます。これをユーザに持たせると同一トランザクション内でユーザへの更新が大量に走りパスワード変更とぶつかったりするわけですよ。
###ユーザ登録の具体的な挙動
1.ユーザを作ってリポジトリに入れます。
2.ユーザのIDをもって組織に利用申請を出します。組織は利用者を登録しリポジトリに入れます。シーケンスを発行しておくと登録順が明確になって安心ですね。
3.もし同時に複数のユーザから登録申請が来て超過した場合はトランザクションではじいてもいいし、暫定的に受け入れたよって返事をしてもいいでしょう。
4.どちらにしろユーザは作れたが有効にならなかったという結果になるのでユーザをそのままにして枠の拡張を促すなり登録失敗として削除するなりします。
5.ユーザは許可が下りるまで誰も読まない記事を書いて待ちましょう。
もし組織と個人の間にもっと色々ななんかがあったらゴメーヌ。
でもその場合でも私が言いたいのは「組織の中の個人と単なる個人は別の存在でもよくない?」です。