3

データベースに格納されたデータに依存するビジネス ルールの検証を実装する最善の方法を見つけようとして苦労しています。以下の単純化された例では、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 を学んでいて、この種の検証を担当するレイヤーをまだ明確に考えていないため、私が間違って始めた可能性もあります。

どんな助けでも大歓迎です。

4

1 に答える 1

3

CreateUserServiceこれは、ドメイン サービスを作成する (そして、別のアプリケーション サービスで作業単位を処理する)ことを除いて、私がモデル化する方法とほぼ同じです。ユーザー名の一意性は、実際のビジネス ドメイン (ここでは、「ユーザーと認証」境界コンテキスト) に由来するビジネス ルールのように見えるため、このアプローチでは、ドメイン サービスと仕様の間の密接な結合をあまり恐れません。 .

と仕様の間の密結合が依然として心配な場合はCreateUserService、実際に仕様をさらに抽象化できます。正当に思えますが、YAGNI の原則を思い出してください。

于 2014-08-29T20:51:06.853 に答える