Good practice for contextual business logic

Firts off, congratulation for the very good done job with Axon V3. I’ve started playing around with it and it is a pleasure.
BTW, I hope the best for Allard and the Axon Dev team in 2018.
I have a question regarding the way to implement contextual business logic. I fully agree with the principle to put CommandHandler methods in Aggegrates but I find it a bit limitating when contextual business logic is needed.
Let’s take a concrete example: considering the Complaint management system from the “Bootiful CQRS Webinar with Axon”, what if I want to check that the company is known (against some reference data) while processing a FileComplaintCommand?

I’ve identified the following options to implement the check:

  1. in the Complaint Aggregate itself: it doesn’t sound good in terms of design, creating a dependency on some external reference data breaks the separation of concerns and make the Aggregate hard to unit test,

  2. in a dedicated CommandHandler in front of the Aggregate: may be better in terms of design but heavy to implement since 2 commands are needed (one for the check, and one for the creation of the Aggregate),

  3. in a CommandHandlerInterceptor: may be technically feasible but I don’t think that such interceptors are intented to implement business logic. I would tend to use them for non functional requirements such as security,

  4. in a standard Java class (such as one annotated with @Service using Spring) in front of the Aggregate: that class would act as an intermediate between the REST interface and the Aggregate,

In my opinion, the 4th option is better. Am I right? Any advice, feedback or good practise would be very appreciated

Hi Jean-Francois,

First off, nice to hear you’re happy with Axon 3.x!
Always nice to hear to people are enjoying playing around with it.

To answer your question however, I typically see two scenario with business logic validations:

  1. Is the validation going to perform an outbound call (database/REST/etc)?
  2. Is the validation doable based on the Aggregate’s state and the command coming in?

In case of 1, I typically recommend putting the check in the service which is publishing the command on the command bus. This thus reflects option 4, which you’re suggesting feels like the cleanest location.

If you’re in scenario 2 however, that check most definitely works fine in the aggregate itself.
And if you decide to put that validation in a (stateless) service, you can let Axons ParameterResolver resolve that service as a parameter in your command handling function just as easily. So in short, for scenario two, I’d go for option 1 in your suggestions.

Hope this helps!

Cheers,

Steven

Thank you Steven for your quick answer.

My post was mentioning the first scenario where the validation is going to perform an outbound call (database/REST/etc).

Things are perfectly clear now :slight_smile:

Hi Jean-Francois,

Is was guessing as much, but I wanted to give you an as complete as possible answer to how I’d make the cut off.

Glad to have been of help! :slight_smile:

Cheers,

Steven