There is no such thing as orchestration. Have you noticed it so far in this series? Probably no, so far I’ve intentionally avoided mentioning it. But this doesn’t change the fact that there is no such thing as orchestration. Let me explain.
Looking for a ViewModel Composition framework? Take a look at the open source ServiceComposer.AspNetCore.
The Composition Gateway is totally ignorant about request handlers and event subscribers that take part in the composition process. There is nothing dictating to anyone what to do. We have an incoming HTTP request and the Composition Gateway has a way to understand which subscribers should be allowed to subscribe to events and which handlers should be invoked. This is it.
It goes even further. Handlers simply raise events without knowing which subscribers are subscribed. There might be none. Handlers, like the Gateway, don’t dictate anything to anyone.
Before diving into this new chapter it’s advisable to review what we’ve talked about so far. All the articles related to ViewModel Composition are available in the ViewModel Composition category.
Let’s imagine the Composition Gateway was about to orchestrate the entire process, for example:
- it knows that there is an incoming request to visualize a Product page.
- In order to do so it needs to invoke the following services:
- marketing that owns name and description.
- sales that owns price.
- warehouse that owns availability.
- shipping that owns shipping options.
- Once it has all the data it can compose them into this new document that will be returned to the UI/caller.
If we give the Composition Gateway knowledge about business scenarios we’ll end up with tight coupling: every single time we need to change the way something is displayed, we’ll have to touch the Composition Gateway. Even the name orchestration suggests coupling.
One of the goals of designing systems using Services Oriented Architecture is to build systems where logical services are well isolated from each other. In our sample scenario we’ve already identified four services:
Each one owns a specific set of data. We can now easily “vertically” expand those boxes and allow each service to select the best, or the required, technical solution they need to fulfill business requirements:
- Marketing decides that their best bet is to go with a document oriented database that exposes an HTTP layer that can be directly queried from the UI. And for security reasons they’ll have a reverse proxy in front of it to handle non-authenticated requests.
- Sales and Warehouse decide to have a set of back-end services, proxied by a web API layer, both talking to a traditional RDBMS.
- And finally Shipping is outsourced to a third party system, and thus all that is built is a web API that acts like a proxy to the third party system.
By removing any orchestration from the Composition Gateway we can push these vertical slices even further into the UI territory:
Thanks to ViewModel Composition techniques, services can now own part of the UI, at the least the part related to composing data for the UI. We’ll dive into the UI-specific part in the future.
But there are a couple of more things we gain from this approach. If services own the full vertical slice, they can introduce caching, inside service boundaries. Each service will fully own its caching layer, if any.
And why not read models, or architectural patterns such as CQRS or Event Sourcing where they fit? We’ll talk more about read models in the context of a single service in the future.
I personally find it interesting to see how encapsulation and the single responsibility principle, which are often brought up in the context of code design, can be applied at a much higher level: system architecture. Vertical slices are the result of applying encapsulation and the single responsibility principle to services. Once we have full encapsulation, each service can make decisions, either business or technical, without affecting (or worse, breaking) any other service in the system.