Programming the Future with Composable Systems
This article by Mike Amundsen discusses programming the future with composable services.
A job control document is a list of URLs of endpoints to do a thing execute a task, reverse a task, repeat a task, cancel the whole job, or do the next task. It’s a document of a bunch of URLs that depend on some other state information that describes the job.
This is what composing is. I’m going to list the URLs of all the services and their endpoints for everything they do and then give it to anybody who wants it. There’s some security and other things around it. It is like code for an abstract class.
And this looks the same no matter what services you’re composing; whether they’re simple or complex, whether there are values, entities, or aggregates doesn’t matter.
Why composable services?
Composable services have been a holy grail for most of us dealing with APIs. Once you get APIs, you can link them together. But, we have to custom bespoke code for every API integration, and then if somebody changes that, we are in big trouble. We want to try and avoid it.
But here’s the other big reason I’m talking about composable services, which comes from Daryl Plummer at Gartner. He talks about composable business as an organization made from interchangeable building blocks. He means the ability to put creative people to the task in a short time with low latency and complexity.
Gartner’s four principles of composable business
- More speed through discovery – the ability to discover talent inside your organization.
- Greater agility through modularity – the ability to move that talent to where it’s needed.
- Better leadership through orchestration – build the right team in the right room at the right time, remote or local.
- Resilience through autonomy – give that team autonomy so they can do what they need to do. They’re the experts, not me.
Leadership knows what needs to be done. They don’t know why or how. And that’s where talent comes in. And this works great for composable services. Composable business needs composable services.
What does composability look like?
- It is not enough for a service to be “on the web.”You must take advantage of the web features; the ability to link from one place to another, use a forum to ask for arguments, and move that state from one place to another is important. Having a public URL is not enough; I need to discover the URL. I have to look up somewhere, like a kind of DNS. So what I use in my projects is a runtime service registry. I’m replacing a URL with a form. What I’m doing is replacing a fixed address with a variable. And that means that I can start to take advantage of things.
- Composability must be designed-in. You don’t get services for free; you have to plan ahead of time and make them behave like other services. Usability, security, or observability must also be part of the story. Composability is available through a feature called idempotency. Idempotent means you get the same answer every time. “Put,” “Get,” and “Delete” are idempotent, “Post” is not. Composable services are reversible. I have to have some rollback or undo features.
- Composable services must be fully described at runtime, including every detail of an argument, method, and URL used. This description has to be available at runtime, not at design time. This can be a huge challenge. The easiest way to do runtime descriptions for all the detailed actions is an HTML form; address, method, the media type that I’m going to send, media type I’m going to receive, and all the arguments.
- Composable services share state, not data models. If I want to read data from a persistent place, if I want to do any computation and save it somewhere, if I want to share some information or approve a purchase order, that is stateful. So I have to share state and especially when we start linking services together, sharing state is going to be important. I need to be able to pass state from one service to another without knowing anything about that other service. We can have a shared state resource out there that is tied to our thread, our process, or our instance. You can use any security system you want. And that means I can write results into the shared resource, which may be needed to fill in forms for the next service in the list of services I’m doing.
- Composable services are self-describing
The biggest thing that I think is a challenge is how self-describing this has to be. We have to make up for a lot of description elements. But we don’t have to describe the instance; we need to describe the abstract class.
Parallel Tasks and Sequential Jobs
A task does one thing and one thing well. That’s where you execute, repeat, revert or cancel. Tasks run in parallel. A job is a set of related parallel tasks. Jobs are sequential.
A proposal for RESTful Job Control
We want to create a way to compose things that have never met before and use them to create a solution without having a lot of custom code to do it. And we can do it through configuration or a document entry. We want to create this network of the way things interact with each other.
Dealing with challenges
Composability is a set of external behaviors.
We have to start rethinking the way we code our services. To do that, we don’t often think about what it will take to roll back. We need to think a lot about parallel and sequential actions and options.
A shared state is a foundational element. Creating a shared state document and keeping that within our transaction space, and securing it will be a little bit of a mental challenge. But it’s not that hard. It’s not that difficult once we get the hang of it.
To conclude, the future of APIs is composable services, and the future of composable services is RESTful Job Control.