I was a hands-on developer and chief technology officer during the days of object-oriented programming, three-tiered web platforms, service-oriented architecture (SOA), and hosting on virtual servers in the data center.
So much has changed since then.
The applications developers build are leveraging real-time data streams, connecting with machine learning models, and interfacing with SaaS and enterprise systems.
Today’s development tools have evolved significantly. They enable globally distributed development teams to operate independently, release frequent changes, and respond to issues quickly. Continuous integration and continuous delivery (CI/CD), continuous testing, infrastructure as code (IaC), and AIops enable teams to automate integration, deployment, infrastructure configuration, and monitoring.
The changes also include cultural and practical transformations such as adopting continuous planning in agile, instrumenting shift-left testing, proactively addressing security risks, and instituting site reliability engineering.
I reached out to several experts to go a level deeper and suggest best practices on how the development process changes when building and deploying cloud-native applications and microservices.
High velocity requires coordination and operations awareness
My first concern with development teams that target building many small, atomic, or frequently deployed microservices is when their deployment velocities don’t account for the required collaboration and safety guardrails.
I spoke with Jason Walker, field CTO for BigPanda, about his experiences with development teams that successfully build, deploy, and enhance microservices. He acknowledges, “The most significant impact is velocity, and the dev-test-deploy cycle time is drastically reduced. Developing in the cloud for a cloud-based service and leveraging an ecosystem of microservices for inputs, an agile team can move very quickly.”
Walker suggests that the working environment must help teams stay on track and deliver business value while operating at high velocities. He offers several best practices:
- Leaders at all levels must understand and align the strategic goals to prevent teams from drifting away from business objectives.
- Scrum masters should embrace agile metrics, score stories accurately, and track team velocity over time, noting and accommodating variability for long-term planning.
- Knowledge management processes and delivering accurate, up-to-date documentation have to be baked into the software development life cycle to prevent modular teams from sprawling away from each other and developing incompatibilities.
- An actionable monitoring strategy is necessary. Synthetic and client telemetry can be useful macro-indicators of overall service performance, and the signal-to-noise ratio in monitoring has to be measured.
Code refactoring enhances microservices
One of the more important coding disciplines in object-oriented programming and SOA is code refactoring. The techniques allow developers to restructure code as they better understand usage considerations, performance factors, or technical debt issues.
Refactoring is a key technique for transforming monolithic applications into microservices. Refactoring strategies include separating the presentation layer, extracting business services, and refactoring databases.
Robin Yeman, strategic advisory board member at Project and Team, has spent most of her career working on large-scale government and defence systems. Robin concedes, “The largest technology barriers to utilising agile in building or updating complex legacy systems are the many dependencies in the software architecture, forcing multiple handoffs between teams and delays in delivery.”
Robin suggests that refactoring should focus on reducing dependencies. She recommends, “Refactoring the software architecture of large legacy systems to utilise cloud-native applications and microservices reduces dependencies between the systems and the teams supporting them.”
Refactoring also improves microservices in important ways, such as:
- Updating the domain models when the business model evolves
- Paring down services to conform to the single-responsibility principle
- Improving messaging in event-driven architectures
- Enhancing observability and error validation
- Addressing changes to devops pipelines or container configuration
Kit Merker, COO at Nobl9, offers this advice to organisations transitioning to cloud-native applications and microservices. “You can’t just rewrite everything -- you need to phase the transition. One best practice is to set clear service-level objectives that are implementation agnostic and manage the user’s impression of your service even as you are transitioning to cloud-native implementations.”
Embrace microservice design patterns
Design patterns have always been used as tools to structure code around common problem sets. For example, categories of object-oriented design patterns are creational, behavioural, and structural; they’re used to solve common problems in software design. SOA design patterns have been around for more than a decade and are a precursor to today’s REST API and cloud API design patterns.
Using microservice design patterns is critical for long-term success. Technology organisations target independent, resilient, auto-provisioning services that support failure isolation, continuous delivery, and a decentralised governance model. That can be challenging if development teams don’t have a common language, microservice architecture, and implementation strategy to develop with design patterns.
Tyler Johnson, cofounder and CTO of PrivOps, explains that developing microservices is a key strategy for reducing complexity. He says, “One way to describe cloud-native applications is as a set of distributed, interacting, complex systems. This complexity can quickly become unmanageable, which is why a modular, standardised microservices architecture including standardised devsecops tooling, APIs, and data models is necessary.“
Michael Bachman, global architect and principal technologist at Boomi, suggests that using the composite microservice design pattern enables developers to focus on the user experience. This design pattern is particularly important when developers build applications connected to multi-cloud services and SaaS platform APIs.
Bachman explains, “The composite is a collection of endpoints presented through an abstracted view. Developers can go to a service catalog, make calls to a composite, and don’t care about what goes on underneath. We’re getting closer to the end user and enabling a trusted experience through a composite service at the high end of the stack.”
In summary, building cloud-native applications and microservices requires development teams to excel at longstanding software development practices such as collaboration, code refactoring, and developing reusable and reliable services. Since teams are developing these services at a significant scale, it’s important to learn, adapt, and mature these best practices.