Where to put global rules validation in DDD

I'm new to DDD, and I'm trying to apply it in real life. There is no questions about such validation logic, as null check, empty strings check, etc - that goes directly to entity constructor/property. But where to put validation of some global rules like 'Unique user name'?

So, we have entity User

public class User : IAggregateRoot
{
   private string _name;

   public string Name
   {
      get { return _name; }
      set { _name = value; }
   }

   // other data and behavior
}

And repository for users

public interface IUserRepository : IRepository<User>
{
   User FindByName(string name);
}

Options are:

  1. Inject repository to entity
  2. Inject repository to factory
  3. Create operation on domain service
  4. ???

And each option more detailed:

1 .Inject repository to entity

I can query repository in entities constructor/property. But I think that keeping reference to repository in entity is a bad smell.

public User(IUserRepository repository)
{
    _repository = repository;
}

public string Name
{
    get { return _name; }
    set 
    {
       if (_repository.FindByName(value) != null)
          throw new UserAlreadyExistsException();

       _name = value; 
    }
}

Update: We can use DI to hide dependency between User and IUserRepository via Specification object.

2. Inject repository to factory

I can put this verification logic in UserFactory. But what if we want to change name of already existing user?

3. Create operation on domain service

I can create domain service for creating and editing users. But someone can directly edit name of user without calling that service...

public class AdministrationService
{
    private IUserRepository _userRepository;

    public AdministrationService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public void RenameUser(string oldName, string newName)
    {
        if (_userRepository.FindByName(newName) != null)
            throw new UserAlreadyExistException();

        User user = _userRepository.FindByName(oldName);
        user.Name = newName;
        _userRepository.Save(user);
    }
}

4. ???

Where do you put global validation logic for entities?

Thanks!

62
задан Sergey Berezovskiy 7 June 2011 в 08:14
поделиться