sounds like a very good approach, to me. Doing the ‘set validation’ inside the repository is a better approach than I used to take (although I prevent it as much as possible). The repository is conceptually part of a Domain, so there is nothing wrong with this logic there. As Nicolas states: it’s part of the Repository contract. The way he repository does the validation should leak out. That’s part of the infrastructure.
However, be very careful when using ‘natural keys’ as aggregate identifiers. It got me in big trouble (long time ago). Imagine a user name is a unique attribute. User A creates an account. After a while, the account is deleted. Now, another user want to use username A as well. Impossible. You cannot create the Event stream, because there already is one.
Nicolas, you’re probably not aware of it, but you’ve pointed me to one of the missing pieces of the puzzle. I wanted to implement set validation in Axon, but didn’t want developers to be bothered with yet more configuration to get it going. Your approach led to the idea of adding an annotation to a field (or method) on the aggregate. The repository would the automatically do the validation when adding or saving an aggregate. It’s too late to include it in 2.0, but 2.1 should be possible. Getting validation going is then as simple as annotating the fields that must be unique across instances.
Regardless, set validation should always be avoided when possible. It’s a concepts that limits scalability (it reduces the A and P guarantees of CAP). When possible, simply have the clients do a query before sending a command. When duplicate entries are detected, solve them by sending another command to fix the issue (e.g. block a user account). In many cases, it’s not really an issue at all.