Sorry folks, I don't want to spam the list but creating the Axon
Example Application raises several questions and I hope you can all
benefit from a good example...
So here are some more questions on new Axon 0.7 features:
1) Why is AggregateIdentifierFactory abstract and not an interface?
I didn’t see the point in creating an interface for it. I don’t want to prescribe how anyone should generate AggregateIdentifier instances. Axon just needs an instance. Whether you want to use a factory or a constructor to generate one is up to you.
In my projects, I don’t let command handlers generate identifiers. Either the aggregates do it, or (better) the client. Aggregates have a default constructor that generates a UUID-based identifier.
I made it package-visible because it is an internal implementation. If you need an instance, you should use the AggregateIdentifierFactory. If that doesn’t create the AggregateIdentifier you want, you should create your own implementation for the AggregateIdentifier interface.
And yes, it is generic. This generic form makes it very easy when working with Hibernate, for example. It would be easy to create a AggregateIdentifierUserType that only stores the string representation in the database and always resolves back into a DefaultAggregateIdentifier implementation. That can only be done if it is generic. The usertype isn’t there yet, though, but it will be, soon.
But to be honest, I am not sure about the factory vs constructor way of creating aggregate identifiers. If you guys think it’s easier, I could ditch the AggregateIdentifierFactory and make the DefaultAggregateIdentifier public with a few constructors.
In my projects, I don't let command handlers generate identifiers.
Hmm... What about the "ContactCommandHandler" in the sample app?
I don't want to prescribe how anyone should generate AggregateIdentifier instances.
Axon just needs an instance. Whether you want to use a factory or a constructor
to generate one is up to you.
I don't think the abstract class is a good idea - It makes things more
complicated for the ones like you who want to use an UUID based
identifier. The others like me that prefer a clean separation of the
creation process won't benefit too because I'll need to do it in every
project again.
Why not do it the simple way for all kinds of users?
1) You create the UUID on the client side
Use "new AggregateIdentifierUUID(uuidStrFromClient)" - No factory at
all.
2) You create the UUID inside the CommandHandler
Use "new AggregateIdentifierUUID()" - No factory necessary too
(creates a random UUID ).
3) You like to incorporate your own process of creating aggregate
identifiers
Yeah, the sample app is running a littlebit behind on implementing the best practices. I heard someone is creating a very cool full-fledged sample app, so keeping up the silly address book isn’t high enough on the priority list ;-).
I was 50/50 on the factory vs constructor, but I believe you have a valid point there. IDE’s tend to be more friendly towards constructors (just type "new " & ctrl+space to get some hints). I’ll create two implementations instead. One that uses UUID (either provided or generated), and one that allows Strings (provided only).