13

I have a question regarding checking of uniqueness in DDD. I know already have some questions about this on stackoverflow, but they don't really answer my doubt

Is it possible for an aggregate root to hold reference of repository to check the uniqueness when updating/inserting to database? Or this is the task done by application service instead of domain model?

Let's say I want to check whether username of User model is unique when user register There are several approaches that I can think of:

  • User model reference UserRepository, do the uniqueness checking in Validate()
  • Create a domain service to do uniqueness checking, using UserRepository (this seems a bit odd for me because I think normally domain service is used only in case the logic span to more than one domain models)
  • Create a specification object in domain layer, with reference to UserRepository to encapsulate unique checking rule, and application service layer use this to do the checking before update/insert

And if I use dependency injection, I'm still wondering about how to inject UserRepository into User in approach 1, or domain service in approach 2, or application service in approach 3, because in any case, for User/domain service/specification object, I need to instantiate the object manually, so the only option I have seem to be using service locator in IoC to get instance. But service locator is an anti-pattern so I want to avoid it

Any sample code will be much appreciated

David N
  • 133
  • 2
  • 4
  • 2
    I would say you should implement this in the service layer. To be more specific, define a validator class for a specific type of business logic (your command) and handle the validation in a decorator that you wrap around the service class. – Steven May 30 '13 at 08:08
  • Would this be helpful? http://stackoverflow.com/a/11958251/625332 – Dmitry May 30 '13 at 22:59
  • @Steven so I should create a UserValidator to implement the checking for User in service layer? Is it considered leaking of business rule (uniqueness of username) to outside of domain layer? – David N May 31 '13 at 10:27

1 Answers1

11

I think that checking for uniqueness falls into Repository responsibility. Repository knows about all aggregates because it suppose to simulate domain collection, so it is natural to ask Repository for uniqueness (like you would expect from HashMap for example).

// repository
interface Users {
  // implementation executes SQL COUNT in case of relation DB
  bool IsNameUnique(String name);

  // implementation will call IsNameUnique and throw if it fails
  void Add(User user);
}

It is a leaky abstraction in a sense because in a multiuser environment this need to be enforced on a data store side (UNIQUE SQL constraint for example, or locking).

IsNameUnique should probably not be called from User aggregate, I would move this call into Application or Domain Service, depending on how rest of your application is structured.

See Uniqueness validation in CQRS Architecture for alternative approach.

Dmitry
  • 17,078
  • 2
  • 44
  • 70
  • so you are suggesting to follow approach 2 above, to create a domain service to call repository to check for uniqueness? Is it common way in DDD to create a validation service in domain layer like that? I'm new to DDD so not very sure – David N May 31 '13 at 10:24
  • Whether to use this repository from Domain or from Application service depends on your use cases, either one is fine as long as you don't use this method from an aggregate. – Dmitry May 31 '13 at 14:08
  • thanks, finally i decide to go for this approach: http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/ – David N Jun 01 '13 at 09:25