When it comes to integrating with, and depending on, third-party APIs in your business solution, you had better think twice of the implications. As Lorinda Brandon already pointed out in her “Safe Sex with Third-Party APIs” talk, there are a number of aspects related to third-party APIs that you need to consider and handle pro-actively to avoid looking bad to your users and customers when those APIs fail to deliver as required. Let’s have a little deeper look at what you could (or should) be doing at the code level to ensure that the volatility of depending on third-party APIs is kept to a minimum.
“Defensive coding” is a practice that is well described in the programming literature, for example in Defensive Programming: Being Just-Enough Paranoid, Jim Bird outlines some of the basic principles and underlying reasons for defensive coding. And in the just as informative and entertaining AGGRESSIVELY DEFENSIVE PROGRAMMING, Terence Eden gives some pretty awesome and unexpected examples of how defensive coding can help track down the strangest of issues.
So how about APIs? Are there some specific defensive coding techniques developers should put to work to shield them from unexpected events? Sure there are, many derived from those already mentioned in the above references. Let’s have a look at a few obvious (and thus important) ones:
Code for Errors
There is no denying it; errors will happen, especially if you are integrating with someone else’s code over a network. Thus, error handling should be part of your general application logic and not solely as a “try-catch” statement surrounding your entire block of code. Handling errors as an “expected” application event forces you to create a non-disruptive experience for your users (instead of just an error message) and greatly increases the perceived stability of your application.
No matter how fast those third-party APIs are guaranteed to be, there will be situations when they aren’t. This could be caused by network conditions, third-party API overload or a DOS attack – whichever, you need to handle it gracefully. Make sure your API calls have reasonable timeouts, and perhaps even run them in a separate thread so you can use the main thread to provide feedback to your users while the call is waiting for its response.
Validate Data Proactively
The JSON/XML/whatever data returned by a third-party API (hopefully) follows some kind of data definition – either verbal or machine-based (JSON-Schema, XML-Schema, etc). Be defensive and validate that the response actually complies. Date formats, timestamps, decimal numbers, etc can all be subject to “format changes” when system components are updated at the third-Party API site. This can introduce subtle changes not detected by their regression tests (if they have any), or not expected to make any difference. For example, your third-party API might add another 4 decimals to the map coordinates it returns, but your code might be parsing these as strings and thus not handle a change in length. Or they might change from lower to upper case in a field containing weekdays, which your code didn’t expect to handle.
One of the core principles of REST is to make use of the HTTP caching mechanism, and many REST APIs provide caching information with response representations. Unfortunately, most HTTP client libraries don’t have any built-in handling, which results in unnecessary HTTP calls to the third-party APIs and in turn decreases performance of both your service and the third-party API. Make sure that your code caches resources locally as indicated by these HTTP headers and uses this cache as much as possible. The advantage is two-fold – it will greatly decrease your dependency on the availability of the third-party APIs and it might decrease the load on those APIs considerably,making them more responsive when you actually need them.
While all the above recommendations have been about functionality, you can be defensive in regard to performance as well. If you design your code to “notice” when it is under heavy load it can take precautionary actions, for example by throttling requests to third-party APIs and redirecting users to failover servers or simply letting the user know that performance may be suffering.
Obviously you shouldn’t overdo any defensive coding, but the above suggestions aren’t very hard to implement if you keep them in mind from the start – and the consequences of neglecting the underlying issues can be grave for you and your users.
As a side note, it strikes me that coding defensively is a little like preparing your first dinner for your to-be in-laws:
- Sample fresh ingredients when buying (instead of trusting the shop)
- Try the food while preparing it (instead of just trusting the recipe)
- Have a backup plan (instead of trusting your power/water supply)
Knowing that you’ve minimized the risk for disaster like this it is good to know there is only one thing that can go wrong in this situation: You.
- Practicing Safe Sex with Third-Party APIs
- 7 Habits of Highly Effective APIs
- What Makes Beautiful Software?