The decision to build products using a service-oriented (or microservice) architecture has enormous technical and organizational impact that is reflected in everything from how teams write code, to how they communicate, to how the organization itself is structured. Given the breadth and depth of impact this decision has, it pays to reflect on why an organization chooses a service oriented architecture, how an organization can support such an architecture, and how teams and individuals can support the organization in successfully adopting a service oriented platform.
As a software development approach, adopting services is a response driven by the needs of an organization. The hope is that, by adopting services, the organization can better provide business value — either to customers directly, or indirectly by minimizing the cost of building software.
By looking at services as an organization, rather than an individual, we can see a few different perspectives on the architecture and its benefits.
To harness the full promise of services requires us as an organization to align these perspectives around the same set of goals. This requires organizational and individual commitment to carry out effectively.
The remainder of this article will present a few personal opinions on how individuals and teams can support building a services, and how the organization can provide the required governance and management to best support service teams.
Get Team and Management Buy-In
In building software, there are always multiple paths to a finished product: as a development team, choose the path with the most leverage to the organization. This typically means building loosely coupled services with strong contracts between them. These constraints are what allow services to be composed into broader solutions. Making this decision might actually go against competing concerns like raw application performance, testability, or development effort.
As an organization, we need to make sure that managers and product owners understand the service oriented vision, so that we can better understand the long term ramifications of individual team decisions to the broader organization.
Typically, buying into the vision requires you to look up from your keyboard for a few hours each week to understand the broader scope of your work and how it affects the organization. Ultimately, we move faster as an organization by making informed decisions together, as opposed to just going faster as an individual.
Contract First Services
As soon as you break a system into collaborating components, you are introducing interfaces between them. Interfaces act as contracts, with both sides needing to exchange the same message formats with the same semantic understand.
To enable this, a “contract-first” approach should be used for service design. The service provider should focus on the messages that the service will accept and produce, paying attention to the platform-independence of their message schemas. A starting point on service design are the four tenets of service orientation (originally published in 2004, yes, 2004).
Tenet 1: Boundaries are explicit
Services interact by sending messages across boundaries. These boundaries are formal and explicit. No assumptions are made about what is behind boundaries, and this preserves flexibility in how services are implemented and deployed.
Tenet 2: Services are autonomous
Services are not subservient to other code or other services. A service simply reacts to a message. How that message was created and what will happen to any response the service creates is immaterial to the action that this service will take.
Tenet 3: Services share schema and contract, not class
Only messages pass from service to service, code does not.
Tenet 4: Services interoperate based on policy
Services don’t just blindly access each other. They need to determine areas of compatibility and agree on how they will interact.
To allow each service team to function as part of the organization, each team needs the core competencies required to deliver a service to production. This may vary between service to service, but in general each team should have members who understand how to develop horizontally scalable web services. This implies knowledge of data management, queueing, caching, and other scale-out techniques, and common service integration patterns.
If you identify that your team does not have a core competency, talk to your manager about it. Alternatively, if management sees a team struggling to deliver a service, maybe they are missing a core competency that might help.
Standardization and Governance
In a nutshell, “governance” means the set of practices, policies, and processes that are put in place to increase the likelihood that a service functions as intended.
As an organization, we need to embrace governance where appropriate by enforcing standard ways of developing, documenting, and supporting services. Any constraints put in place are not there to limit development creativity. Rather, constraints allow developers to explore a solution space while still following the guiding principles of the organization, and adhering to the broader vision of the platform.
Process and standardization can emerge from the bottom-up, where developers identify particular repeated pain-points, or top-down, where management sees areas where teams are struggling with. Whichever method surfaces the practice, it is important to clearly document and communicate what that message is, ensuring that the organization as a whole moves in the same direction.
To support other internal teams using your service, try and consider each service as delivering a product to a customer — that customer being another internal team. How can we market, document, and sell our service to internal customers? How can we discover feature requests or report bugs to internal service providers? If you were forced to communicate with internal teams the same way you communicated with an external customer, what would you do differently? Start doing that today.
100% of the code written across the organization today has no value. That code only has value when it is deployed on production and is run by a paying customer. Developers are paid to solve customer problems through running software. And the best way we can understand how our code provides value is to understand how it is being used in production.
Is that tight for-loop optimization that took three days to develop actually executed in production? Has the caching solution you designed and developed over three months lead to more cache hits or more cache misses? As developers, we need to understand and take ownership of how our software runs in production to provide the most value we can. As an organization, how can we help developers understand the impact of their code on production? How can we get code into customers hands faster, so that the investment the organization has made in code provides a return faster?
Onwards to Microservices
When undertaking a significant architectural change it is easy as developers to focus strictly on the technical problems. However, more often than not, organizational and “human” problems are equally challenging. By taking more time to solve or surface the human problems, the entire organization will be able to take advantage of the compounding returns provided by microservices.
From an organizational perspective, a switch to microservices should be treated with foresight and planning. By making sure each manager, product owner, and development team understands the broader vision, you will help everyone make decisions for the “greater good” of the organization. By enforcing process where necessary, you will make it easier for teams to communicate and support each other in standard ways.
Ultimately, microservices are not a panacea. They are a decision that an organization makes with a specific goal in mind. To make the most of that decision, make sure that everyone understands the goal and the reasoning behind it.