In the first part of this series, we laid out a set of principles to help you understand when microservices can be a useful architectural choice. In this post, we dive into one of those factors in more detail, exploring the facade pattern to simplify how you interact with external dependencies.
In computer science, there are three answers that work for every question you’ve ever been asked: 42, “it depends”, and “another layer of indirection.” As we discussed in the previous installment, microservices do not live alone. In fact, they work in concert to deliver business value.
In this post, we turn to the idea of “Facade External Dependencies.” This factor is similar to “Failure Isolation” but with a twist. Instead of guarding against the inevitable failures of our services, we seek to protect them. “From what?” you ask. From external dependencies that change frequently or are complex to use. This pattern is common in software. Often, this is a vendor dependency, where one service provider is swapped for another. It could be a something large (like an ERP system), or something relatively simple (like a mapping service).
Calling your external dependencies directly? It might be better to abstract them away instead
Enterprise systems—monoliths and microservices alike—will inevitably rely on some set of third-party dependencies. Traditionally, your monolith would directly call those other systems or APIs. This was (often) done to ensure acceptable performance. When it came time to change the dependency (for whatever reason), you’d update your system accordingly. Sounds simple right? Yes, for a simpler time.
Today, your applications—and the systems they often rely on—are increasingly complex. When you need to simplify these interactions, microservices can be an appropriate architectural choice.
A microservices architecture offers you a solution. Rather than directly calling these dependencies, we can instead place an abstraction layer (that we control) in between the core app and the dependency.
Third party systems are designed to solve a large set of problems, many of which may not be relevant to your application. Instead of forcing your service to understand the nuance of a complex interaction, you can build a microservice that exposes a simplified interface. That’s the essence of the facade pattern.
This approach is nothing new. In fact, it is one of the twenty-three original Gang of Four patterns found in the classic book Design Patterns: Elements of Reusable Object-Oriented Software. Facades don’t just facilitate evolutionary architecture. They can also be used to simplify a complex service.
The story gets even better – your facade microservice can do so much more! Imagine a third party service that requires a bit of context that doesn’t change from invocation to invocation. Perhaps a payment gateway uses your corporate headquarters location for a calculation, or the vendor requires a token authorizing your use of their API. Rather than have each and every consumer incorporate that bit of business information, your facade microservice can inject the context into the third party call. Not only does this approach simplify calling the service, it also makes it far easier to update in the future.
But wait, there’s more! A facade can perform additional functionality before or after making the underlying request. In part 2 of this series, we talked about the data-driven strangler approach. While obviously useful as part of a larger refactoring, a facade gives you a perfect place to inject needed behavior into your call stack. Want to log the results of the underlying invocation? Or maybe you need to create an audit trail for every call to the third party system. In either case, your facade microservice makes such interactions trivial.
That’s the facade pattern in a nutshell; let’s finish up with a bit of advice on microservices in general.
PSA: Use a service registry to wrangle your microservices
As we near the conclusion of this series, you’ve almost certainly noticed an unavoidable consequence of a microservices architecture. Instead of a singular monolith, you now have dozens (perhaps hundreds) of services. Not only are there more services – they are changing faster than before. Your services are coming and going as they scale up, scale down, or are replaced. Thankfully, the open source community has a way to help you manage all this thrash: the service registry. Eureka from Netflix is a popular option and many Pivotal customers opt for Service Registry for Pivotal Cloud Foundry (which is based on Eureka).
Regardless of which library you use, both are simply implementations of the service discovery Pattern. Instead of a brittle, hardcoded configuration, a service registry allows your application to dynamically find and call services.
Clients register themselves providing useful metadata such as host and port. The registry also looks for a regular heartbeat from registered services. If the heartbeat fails, the registry removes that instance to prevent failed calls.
Sure, you can always stand up your own instance of a service registry. But is day-to-day management of tooling your core business? Probably not. If you want to focus on your custom code instead, you can leverage Service Registry for Pivotal Cloud Foundry, part of Spring Cloud Services. It’s a simple way to create and manage your service registry. Try it out for yourself on Pivotal Web Services, a hosted version of PCF, simply select it from the Marketplace:
Why architects are more important than ever before
This ongoing series has repeatedly touched on matters of architecture, but what does that term mean? Ask 20 engineers and you’ll get (at least) 20 different answers. Let’s close out with a common definition of architecture and the implications.
Architecture is often described as the decisions that are hard to change later, or the decisions we wish we’d gotten right early in a project’s lifecycle.
But that doesn't work in the era of disruption. It’s time we realized that change is inevitable. And this all-too-common view of architecture has fostered an attitude in many companies that amounts to “we’re agile, we don’t have architects.”
Regardless of titles or roles, you already have people in your organization making architectural decisions. You owe your customers more than just accidental architecture! Microservices can provide additional flexibility allowing you to refactor easily as new requirements emerge. As always, please microservice responsibly!
Read the rest of this series:
Part 1: Should that be a Microservice? Keep These 6 Factors in Mind
Part 2: Multiple Rates of Change
Part 3: Independent Lifecycles
Part 4: Independent Scalability
Part 5: Failure Isolation
Part 7: The Freedom to Choose the Right Tech for the Job
Want to learn more about microservices? Join us at the next SpringOne!
Want more architectural guidance for your modern apps? Be sure to download Nathaniel's eBook Thinking Architecturally.