One of the things which often throws people off when looking to identify their service boundaries is the UI design. Even those who know that the screen a user is looking at is the result of multiple services working together sometimes stumble when dealing with forms that users enter data into.
Let’s take for example a screen from the Marriott.com online reservation system (below). This screen collects information about the guest staying at the hotel (name, phone number, address, etc) and credit card information.
While we might have wanted to keep guest information in a separate service from the credit card information (which may very well be the corporate card of someone responsible for travel), the above screen would seem to indicate that the data would be collected together, validated together, and would also have to be processed together.
The traditional way
In standard layered architectures you would have all the data submitted by the user passed in a single call from a controller to some “service layer” (possibly running on a different machine), which would then persist that data in one transaction.
Even if some attempt was made to separate things out, there likely would be some “orchestration service” that received the full set of data and it would make calls to the other “services”, passing in the specific data that each “service” is responsible for.
I am putting quotes around the word “service” to indicate that I don’t consider these proper services in the SOA sense (as they lack the necessary autonomy) – they are more like functions or procedures, whether or not they’re invoked XML over HTTP is besides the point.
What to do?
Like so many other things, the solution is simple but a bit counter-intuitive as it doesn’t follow the way most web development is done, i.e. one submit button => one call to the server.
Let’s say the “Red” service is responsible for guest information and the “Blue” service is responsible for credit card data. In this case, each service would have its own javascript come done with the page and that script would register itself for a callback on the click of the submit button. Each service would take the data the user entered into its part of the page and independently make a call to “the” server (could be to 2 separate servers) where the data is persisted (potentially to 2 different databases).
This raises other questions, of course.
Now that the data submitted is being processed in 2 transactions rather than just one, we may need to figure out how to correlate the data. In this specific case, it’s not such a big deal as there is no direct relationship between the guest and the credit card – both need to be independently correlated to some reservation ID.
That reservation ID would likely have been “created” on a button click on a previous screen by some other service. The reason why I put the word “created” in quotes is that this could be as simple as having the client generate a new GUID and put that in a cookie (which would cause the reservation ID to end up being submitted along with subsequent requests). Another alternative would be to put the reservation ID in the session.
It’s quite possible that the reservation ID would only be persisted much later in the service that owns it when the user actually confirms the reservation on the website.
In any case, what we can see is that each of the commands of our respective services can now be processed independently of the others in an entirely asynchronous fashion thus vastly improving the autonomy of our services.
Some words on CQRS
This style of UI composition where services leverage javascript code running in the browser isn’t technically difficult in the slightest. The rest of the implementation of each service – having a controller that takes that data and passes it on for persistence can be quite simple.
I’d say even more strongly, most of the time you shouldn’t need to use any fancy-dancy messaging to get that data persisted – that is, unless you’re still stuck with the big relational database behind 23 firewalls type data tier. Embrace NoSQL databases for the simplicity and scalability they provide – don’t try to re-invent that using messaging, CQRS, persistent view models, event-sourcing, and other crap.
There are other very valid business reasons to embrace CQRS, but they have nothing to do with persistence.
Also notice, this is all happening within a service boundary / bounded context.
In closing
If you aren’t leveraging these types of composite UI techniques, it’s quite likely that your service boundaries aren’t quite right. Do be aware of the UI design and use it to inform your choices around boundaries, but be aware of certain programming “best practices” that may lead you astray with your architecture.
Also, if you’re planning on coming to my course in Toronto to learn more about these topics, just wanted to let you know that there’s one week left for the early-bird discount.
Finally, it’s good I have a birthday that comes around once a year to remind me that my time here isn’t unlimited and that I had better get off my rear and do something meaningful with the time I do have. If you get value from these posts, leave a comment or send me a tweet to let me know – it does wonders for my motivation.
Thanks a bunch.