Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unique validation in DDD

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

like image 455
David N Avatar asked May 30 '13 04:05

David N


1 Answers

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.

like image 60
Dmitry Avatar answered Nov 06 '22 02:11

Dmitry