データベースに格納されたデータに依存するビジネス ルールの検証を実装する最善の方法を見つけようとして苦労しています。以下の単純化された例では、Username 属性が一意であることを確認したいと考えています。
public class User() {
public int Id { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string GenerateRandomPassword() {
}
}
public interface IUserRepository : IRepository<User>
{
bool UsernameTaken(string username);
}
public interface IUnitOfWork : IDisposable
{
void Commit();
IUserRepository Users { get; }
}
私はすでに、リポジトリをエンティティに注入する(そしてそれが無効な状態になるのを防ぐ)、拡張メソッドの作成など、それを達成するためのさまざまな方法について多くのことを読んでいます.
ただし、これらのいずれもそれを行うための最良のアプローチではないと思います。
そこで、アプリケーション サービスを使用して、仕様を使用してエンティティの検証を調整することにしました。
public class CreateUserService : ICreateUserService
{
private readonly IUnitOfWork _uow;
public CreateUserService(IUnitOfWork uow)
{
_uow = uow;
}
public User Create(User user)
{
var usernameAvailableSpecification = new UsernameAvailableSpecification(_uow.Users);
if (!usernameAvailableSpecification.IsSatisfiedBy(user))
{
throw new ValidationException("Username already taken");
}
user.GenerateRandomPassword();
_uow.Users.Store(user);
_uow.Commit();
return user;
}
}
最初は、よさそうだった。しかし、サービスは仕様の実装に密接に結合されており、仕様の依存関係を手動で処理する必要があるため、単体テストはやや困難です。仕様を抽象化することも考えましたが、正しい方法かどうかはわかりません。
実際に私は DDD を学んでいて、この種の検証を担当するレイヤーをまだ明確に考えていないため、私が間違って始めた可能性もあります。
どんな助けでも大歓迎です。