ドメインモデルでどうやって一意制約チェックを実装するか

まずは、ナイーブなOO的な発想?で、全てのデータをメモリに読み込んでやる方法。これは基本的には難しいですよね。よっぽど少数のデータであればOKかも知れませんが。

次は、ドメインモデルでやらないで、その手前の処理(入力チェックなど)で行う方法が考えれますね。この方法はドメインモデルとして一意制約チェックをする方法にはならないので今回はNGですが、個人的にはこの方法はよく利用します。ドメインモデルをある程度理想的な条件が成り立っているモデルとすることで、複雑さを低減することができます。

では、どうするか?
チェックは検証ルールと考えればいいので、ドメインモデルでは対応する検証ルール用のクラスすなわち一意制約用の検証Specクラスを作成して利用するようになります。チェック方法は、Repository経由でチェックするIDのオブジェクトを読み出せるかどうかで簡単に判断できます。

public class HogeHoge一意制約検証Spec
{
  public bool IsSatisfiedBy(HogeHoge candidate) {
    return HogeHogeRepository.FindByID(candidate.ID) == null;
  }
}

使い方は永続化のタイミングなどで検証処理を呼び出すだけです。

HogeHoge o = new HogeHoge();
// HogeGogeのプロパティを設定

HogeHoge一意制約検証Spec spec = new HogeHoge一意制約検証Spec();
if (spec.IsSatisfiedBy(o)) {
  Console.WriteLine("OK");
} else {
  Console.WriteLine("NG");
}

このSpecクラスはいろいろ応用が利くので便利に使っています。