Vendor Lock In Anti-Pattern
Porter's Five Forces is a framework taught in business school for analyzing the competitive landscape of an industry. Students learn the framework then apply it to multiple case studies to understand the motivation and actions taken by companies and thereby gain exposure to the strategic thinking necessary to successfully run a competitive business.
The framework breaks down the major influences to an industry into four groups: Threat of New Entrants, Threat of Substitute Products, Bargaining Power of Suppliers, Bargaining Power of Buyers. In software, we rarely have the opportunity to think at this macro level. Nor are we expected to. However, this framework is useful not only to upper management but can also effectively be applied in software architecture and design decisions. I'd go as far as to assert that it SHOULD at least be considered in such planning.
In particular, lets explore it as it applies to Bargaining Power of Suppliers. Data providers and integrated 3rd party APIs are really suppliers into our information business. For various reasons, whether to beat out competitors' entry into new markets or to reach MVP as quickly as possible, 3rd party integrations are often performed in a sub-optimal manner. Failure to consider the future utility of replacing that integration can lead to the Vendor Lock In.
Some years down the line the vendor may go out of business or increase prices beyond an acceptable level. They may fail to live up to their SLAs or experience an unacceptable deterioration in quality of service or availability. They may be beat out by a higher quality service or provider. Any number of reasons may arise that require action.
A vendor customer that experiences this has several courses of action at their disposal. They may simply replace their vendor with another. They may internally develop a replacement product. They may acquire their vendor. They may even want to add a number of similar vendors and aggregate the data. When the time comes to take action the question becomes, "How much will it cost?" With a sub-optimal integration, the answer is too frequently a disappointing, "Too much." This may limit the company's ability to compete or even hamstring their supplier strategy altogether.
It's therefore best to consider from the start how to design an integration such that it can be altered or replaced in the future with minimum complexity and risk. There's no prescription here. The answer depends on the nature of the system you're addressing.
Solutions
A number of well known software design patterns and tools exist at least in part for the purpose of avoiding lock-in. ORMs or Data Access Layer allow us to build applications that are indifferent to the choice of database technology. Containerization and Kubernetes allow us to abstract infrastructure away from specific offerings like AWS. However there are times when you need a custom solution for your specific application.
If passing data between services, we can capture the data as sent in a Data Transfer Object and perform a transformation to a target object. Java's Mapstruct provides a means of generating boilerplate code for the transformation with the ability to customize yourself.
The types of validation and enrichment necessary may vary between providers but generalize surprisingly well. A good approach is to build well encapsulated rules with a shared input/output interface. By doing so you enable Unix-style Inter-Process Communication that can be used to chain processes in a manner customizable to each data provider. The chaining itself can be configuration driven and exposed via an internal UI so that onboarding each successive vendor becomes a matter of piping together pre-existing rules in sequence and perhaps writing a few new rules.
As is generally the case with software, this means exerting more discipline and effort initially in order to save time and money long term. We don't want to go to overboard though. It's best to postpone abstraction until it's obvious or necessary. The trade offs should be considered explicitly. In general, following best practices like strong encapsulation and minimal coupling should set the stage for adopting the correct abstraction once it presents itself.
Comments
Post a Comment