A few weeks ago I had the opportunity to attend Greg Young’s “Advanced CQRS and DDD” workshop in London.
While some of the material Greg covered in the workshop was familiar, mainly around the concept of asynchronous messaging and it associated headaches, some of it was new ground.
Over the three day workshop we evolved a scenario that modeled a restaurant business process consisting of the following basic work flow ;
- Waiter takes the order from customer and gives it to the cook
- The cook adds ingredients and cooks the order and gives it to the assistant manager
- The assistant manager adds the prices for the meal items and gives it to the cashier
- The cashier takes payment from the customer and marks the order as paid
The first implementation involved basically creating a document that represented an order, creating classes to represent the actors mentioned above and having each of the instances call the required method on another instance.
Tightly coupled, synchronous and hard to change the business process if required.
Once we had this in place we evolved the system using a common interface (IOrderHandler) and a series of decorators that added abilities to each of the underlying “actors”. These decorators involved things like having a concurrent queue to recieve “messages” on, having a thread to process messages asynchronously and some decorators that injected various “faults” into the system, such as messages being dropped or sent multiple times.
At a certain point when you are moving towards maximal decoupling, it also becomes apparent that your actual “business process” is becoming more and more abstracted and hard to grok.
Enter the “Process Manager” pattern, in this case we created a new actor called the “Midget” whose job it was to handle the routing of messages from one actor to another, essentially representing the business process in a single place. Think about that for a second, if you have a single class representing the flow of a process (via messaging) you also have a single place to understand that flow and also the option of having alternative business processes if required.
We actually went down the route of implementing an alternative business process, in the form of the waiter flagging a customer as “dodgy” which in turn changed the business process to be (at this point we have refactored to use a publish/subscribe message bus)
- Waiter takes the order from the customer, creates a “Dodgy Customer Midget” to handle the business process
- Dodgy Customer Midget places a command on the message bus “CalculateOrder”
- Dodgy Customer Midget waits for the event “OrderCalculated”
- Meanwhile, the assistant manager reacts to the command “CalculateOrder”, does his work and then sends an event “OrderCalculated” with the order itself as payload
- Dodgy Customer reacts to the event “OrderCalculated” …
etc… until the business process of making the dodgy customer pay first, BEFORE his meal is cooked, has occurred.
Another very interesting concept we discussed and implemented was avoiding the deserialization of the message / payload and writing a wrapper class that can manipulate the structure directly. The reason for this is the following ;
Say a process called “A” sends a message with two fields called “Name” and “Title” to process “B”.
Process “B” then deserializes the message into its structure, which only has the “Name” property. At this point you have now lost information from the original message. When it comes time for “B” to potentially send that message on, lets say to “C” then when “C” receives the message and deserializes it, even if “C” has a structure to accept “Name” and “Title”, the information for Title is lost.
By keeping the raw message itself, in our case a JSON payload, and instead writing a wrapper to manipulate the structure directly (in this case using Newtonsoft and JObject calls) you can change the bits of the message you know about, while leaving the rest untouched.
I put together a very small demo that highlights the concept being used between method calls that would simulate the reply/request of messages in a distributed system, available on github here -> decoupled-messaging-demo
Some of the topics we didn’t go into a lot of detail on during the course, which was a bit unfortunate, but luckily Greg had nothing to do on Monday night so I suggested we head out and grab a beer and some food at a local pub. Greg knows London extremely well and had a great place in mind.
Over the course of a few beers and some food, I managed to ask a lot more of the hairy questions I had regarding DDD, eventually consistent databases and CQRS in general. Between the technical talk I also found out that we had some common ground around both being huge fans of Ice Hockey (as well as both having played in the past) and having experience with Boxing and martial arts. Big thanks to Greg for his time and the great conversation over beers that night !