Microservices are a good architecture principle. But to tailor them seems quite difficult and it’s discussed widely over the community. The post discusses the possibility to create microservice along a business process – whereas one business process step is one microservice.
“The term “Microservice Architecture” has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services.” Martin Fowler, James Lewis 2014 (https://martinfowler.com/articles/microservices.html)
Obviously if a service is a microservice or not, has nothing to do with number of lines of code or if it has only one interface. No, it is one business function, which can be deployed and run independently. I don’t want small services only, because they are small. I want to have small services, because they make my entire application more stable and more performant. OK, all of that sounds very understandable, but how get I a microservice for an application (I don’t even speak of legacy applications).
Obviously, it makes no sense to tailor them in the same manner as our good, old n-tier application. If I have a service for UI, business logic, and persistence, those wouldn’t be independently deployable. Of course, I can do it technically, but with each new business function I would have to deploy all three services. In such a manner, I don’t have any advantage over my good, old monolith.
I need to tailor along the business functionalities. OK – sounds nice, but how can I do it? I want to explain it, using a sample.
Let us assume, that we would have a Call of Bids process, we want to implement. To find out the business functions, which should be independently deployable we look at the business process – the business functions should be recognizable then. A first sketch of it could look like following:
- An Engineer creates the planning e.g. for a new house. The planning is stored as new planning documents.
- The Engineer creates the necessary drawings and adds them as new to the planning documents.
- The Contractor checks the planning documents and create a new bid based on that.
- The Manager checks the bids and awarded one bid of one contractor.
As we can see, the business process is not good enough to base our microservices on it. The contractor falls out of heaven. Why should he send a bid? So, we need something which contains the planning documents on one hand and a list of contractors on the other hand. Moreover, that business object “Call of bids” contains all bids given by all invited contractors. Only in such a way, it is possible to evaluate bids in an efficient way. Our second approach looks then like this:
- The engineer creates the planning documents including all necessary drawings. (‘I’m sorry the drawings aren’t so interesting for our model L). The planning documents get the status NEW.
- The engineer creates the Call of Bids which gets the status NEW and which contains a list of contractors. Those contractors are supposed to bid for the project. Please let us assume that we have a closed Call of Bids, where all contractors are listed. It makes the sample more understandable and don’t spoil the effect I want to explain.
- The contractor gets the information that he is supposed to bid for the project. He creates the bid and send it back. The bid gets the status NEW. (At least in my sample – you might think a status transition from NEW – DRAFT – SENT might be better. And I must agree with you, but please stick with me in that sample.)
- When all bids are given, the manager can evaluate the bids. The bids get the status EVALUATED.
- Based on the evaluation, the manager can award one bid which gets the status AWARDED.
So, what does the sample above mean to microservices? If we want to tailor microservices, we want to deploy them independently. To tailor microservices inside of one business function makes only few sense because with each change of such a microservice all services need to be deployed. In the sense of a Design Driven Development, we need to find the borders of concerns. And those borders of concerns are exactly our business functions.
The business functions can be determined by
- Change of status of the main business object or
- Change of handling business role
Let me explain it in our sample. For the steps CREATE PLANNING DOCUMENTS and CREATE CALL of BIDs, the handling role is the Engineer in both cases. But the main business object of the process is Call of Bids is not even apparent at the first step. It can be questioned if that step even belongs to the process. Anyhow, the status of Call of Bids is changed from NOT EXISTING to NEW, which indicates a border of concern.
In the next transition from CREATE CALL of BIDs to CREATE BID the handling business role is changed from Engineer to Contractor. And after that transition from Contractor to Manager.
In the last transition, the handling role remains, but the status is changed from EVALUATED to AWARDED. That status can be prolonged even from a single bid to containing Call of Bids.
So, with the explained approach, we would have the following services
- Create Planning Documents
- Create Call of Bids
- Create Bid
- Evaluate Bids
Those services can be implemented and deployed nicely without affecting each other. Of course, there might be changes necessary, which will influence every step, but out of experience I can say, those are seldom and need to be planned carefully anyhow. But they can be implemented step by step without necessity of a Big Bang.
Hmm, I feel that you are not satisfied with the solution. You hear your manager: “It’s too expensive. I can’t pay a database for each of those services. I can’t use any synergies. Are you crazy?” To be honest, I hear those arguments too from my manager. You can solve that issue with Supportive Services, I will explain them in my next blog post.