September 10th, 2015
(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: firstname.lastname@example.org
Microservice practitioners, usually have come from an evolutionary design background and see service decomposition as a further tool to enable application developers to control changes in their application without slowing down change. Change control doesn’t necessarily mean change reduction – with the right attitudes and tools you can make frequent, fast, and well-controlled changes to software.
Whenever you try to break a software system into components, you’re faced with the decision of how to divide up the pieces – what are the principles on which we decide to slice up our application? The key property of a component is the notion of independent replacement and upgradeability – which implies we look for points where we can imagine rewriting a component without affecting its collaborators. Indeed many microservice groups take this further by explicitly expecting many services to be scrapped rather than evolved in the longer term.
The Guardian website is a good example of an application that was designed and built as a monolith, but has been evolving in a microservice direction. The monolith still is the core of the website, but they prefer to add new features by building microservices that use the monolith’s API. This approach is particularly handy for features that are inherently temporary, such as specialized pages to handle a sporting event. Such a part of the website can quickly be put together using rapid development languages, and removed once the event is over. We’ve seen similar approaches at a financial institution where new services are added for a market opportunity and discarded after a few months or even weeks.
This emphasis on replaceability is a special case of a more general principle of modular design, which is to drive modularity through the pattern of change . You want to keep things that change at the same time in the same module. Parts of a system that change rarely should be in different services to those that are currently undergoing lots of churn. If you find yourself repeatedly changing two services together, that’s a sign that they should be merged.
Phil Calçado says of his own experience:
These two teams, App and Web, were really isolated—we even lived in separate buildings across Berlin. We pretty much only saw each other during all-hands meetings, and our main communication tools were issue trackers and IRC. Still, if you were to ask anybody from any of the teams about how our development process worked, they would describe something like this:
1.) Somebody has an idea for a feature, they write a couple of paragraphs and draw some mockups. We then discuss it as a team.
2.) Designers shape up the user experience.
3.) We write the code.
4.) After a little testing, we deploy.
But somehow there was a lot of frustration in the air. Engineers and designers complained that they were overworked, but at the same time product managers and partners complained they could never get anything done on time.
The actual flow was something like this:
Somebody comes up with an idea for a feature. They then write a fairly lightweight spec, with some screen mockups, and stores that in a Google Drive document.
The spec stays in this document until somebody has time to actually work on it.
The very small design team would get the spec and design the user experience for it. This would then become a card in the Trello board owned by the Web team.
The card would sit on the Trello board for a while, at least a 2-weeks iteration, until an engineer was free to pick it up.
The engineer would start working on it. After converting the design into a proper browser-based experience using fake/static data, the engineer would write down what changes in the Rails API they would need for this experience to work. This would go into Pivotal Tracker, the tool of choice for the App team.
The card would sit on Pivotal until somebody from the App team was free to look at it, often taking another two-week iteration.
The App team member would write the code, integration tests and everything required to get the API live. Then they would update the Trello issue, letting the Web team know their part was done.
The updated Trello card would sit in the backlog for a while more, waiting for the engineer in the Web team to finish whatever they started doing while waiting for the back-end work.
The Web team developer would make their client-side code match whatever kinks from the back-end implementation, and would give the green light for a deploy.
As deployments were risky, slow, and painful, the App team would wait for several features to land into the master branch before deploying it to production. This means the feature would be sitting in source control for a couple of days, and that very frequently your feature would be rolled back because of a problem in a completely unrelated part of the code.
At some point, the feature finally gets deployed to production.
There would be heaps of back-and-forth between those steps as people needed clarification or came up with better ideas, but let’s ignore this for now.