はじめに
DDD+CQRSの文脈でコレクション操作に関する記述をどこに格納すべきか悩んでます。
自分なりに整理してみたので投稿してみます。
ファーストクラスコレクションはオブジェクト指向エクササイズの言葉です。
アーキテクチャはオニオンアーキテクチャで考えています。
ドメインサービスは1インターフェース1関数1機能な、どこにも属せない関数の置き場と考えています。
アプリケーションサービスは業務知識外のアプリ固有の機能を置く場所と考えています。(ユースケースとか)
1.特定の条件にマッチした集約を抽出したい
リポジトリで実装
特定の集約に関することなのでリポジトリに担当してもらいます。
けどリポジトリには永続化に関することだけに専念してもらいたい気もします。
ファーストクラスコレクションで実装
ファーストクラスコレクションを用意してそこに操作を記述します。
ユーザーが大量に存在するとつらいかも。
ある程度絞った要素に対して追加の操作をする際には便利かも。
ドメインサービスで実装
サービスとして独立させてしまいます。
実装は、リポジトリを介さず直接保存領域を操作するのでも良いかも。
アプリケーションサービスで実装
検索の条件なんて業務知識ではなく各ユースケースの都合と考えて、アプリケーションサービスに置いてしまいます。
2.特定のユースケースに特化した情報を抽出したい
クエリ(CQRS的な)で実装
ユースケース専用のDTOとクエリを用意してそこに条件を混ぜ込めます。
3.集約をまたいだ検索条件でマッチした集約を抽出したい
これが一番悩みます。集約またぎなのでリポジトリに実装するのは抵抗があります。
ドメインサービスで実装
実装は、リポジトリを介さず直接保存領域を操作するのでも良いかも。
アプリケーションサービスで実装
検索の条件なんて業務知識ではなく各ユースケースの都合と考えて、アプリケーションサービスに置いてしまいます。
集約を返す機能なのでクエリとするには抵抗があります。(CQRS的な)
まとめ
コレクション操作を記述する場所には
- リポジトリ
- ファーストクラスコレクション
- ドメインサービス
- アプリケーションサービス
- クエリ(CQRS的な)
がある気がします。
これは元々持っているコレクションをごにょごにょする話ではなくDB等保存領域から引っ張ってくる時の話です。
既に持っているコレクションに対してごにょごにょする場合は
- ファーストクラスコレクション
- ドメインサービス
- アプリケーションサービス
- その場でベタベタに記述
の選択肢がありそう。
public class ユーザー一覧 {
private List<ユーザー> 一覧 => new List<ユーザー>();
public ユーザー一覧(IList<ユーザー> _一覧) => 一覧.AddRange(_一覧);
public IList<ユーザー> ごにょごにょする() => ごにょごにょ;
}
public interface ごにょごにょするサービス {
public IList<ユーザー> ごにょごにょする(IList<ユーザー> _一覧);
}
コレクション操作を記述する場所はどこかに統一したい気持ちになりますが、そうするとドメインサービスかアプリケーションサービスしかないわけで。
そうなると大量にサービスが発生してしまい、把握できなくなって似たような検索条件のサービスが出来上がりそう。
結局ケースバイケースとか状況に応じてとしか言えないのでしょうが、少なくともコレクション操作の置き場所の候補の整理には役に立つかも。
ずれた話をしていたらすみません。
他にも良い置き場所があればご教示願います。