Handle Others’ Versions
Learn about designing for version changes, load application service, making changes to service, full duplex and half duplex testing.
Designing for version changes
When receiving requests or messages, our application has no control over the format. No matter how well the service’s expectations are defined, some non-serious person can pass us a bogus message. We’re lucky if the message is just missing some required fields. Right now, we’re just going to talk about how to design for version changes. (For a more thoroughly chilling discussion about interface definitions, see Integration Points). The same goes for calling out to other services. The other endpoint can start rejecting our requests at any time. After all, they may not observe the same safety rules we just described, so a new deployment could change the set of required parameters or apply new constraints. Always be defensive.
Loan application service
Let’s look at the loan application service again. As a reminder, from Table 1, Example Routes, we have some routes to collect a loan application and data about the borrower.
Now suppose a consumer sends a POST
to the /applications
route. The POST
body represents the requester and the loan information. The details of what happens next vary depending on our language and framework. If we’re in an object-oriented language, then each of those routes connects to a method on a controller. In a functional language, they route to functions that close over some state. No matter what, the post request eventually gets dispatched to a function with some arguments. Ultimately the arguments are some kind of data objects that represent the incoming request. To what extent can we expect that the data objects have all the right information in the right fields? About all we can expect is that the fields have the right syntactic type (integer, string, date, and so on), and that’s only if we’re using an automatic mapping library. If we have to handle raw JSON, we don’t even have that guarantee.
Making changes to the service
Imagine that our loan service has become really popular and some banks want in on the action. They’re willing to offer a better rate for borrowers with good credit, but only for loans in certain categories. So you add a couple of fields: the requester data gets a new numeric field for creditScore
, and the loan data gets a new field for collateralCategory
and a new allowed value for the riskAdjustments
list. Sounds good.
Here’s the bad news. A caller may send us all, some, or none of these new fields and values. In some rare cases, we might just respond with a “bad request” status and drop it. Most of the time, however, our function must be able to accept any combination of those fields. What should we do if the loan request includes the collateral category, and it says “mobile home,” but the risk adjustments list is missing?
-
We can’t tell the bank if that thing is going to get opened up like a sardine can in the next big blow.
-
Or what if the credit score is missing?
-
Do we still send the application out to our financial partners?
-
Are they going to do a credit score lookup or will they just throw an error at us?
All these questions need answers. We put some new fields in our request specification, but that doesn’t mean we can assume anyone will obey them. A parallel problem exists with calls that our service sends out to other services. Remember that our suppliers can deploy a new version at any time, too. A request that worked just a second ago may fail now.
Full duplex testing
These problems are another reason we like the contract testing approach from Help Others Handle Your Versions.A common failing in integration tests is the desire to over specify the call to the provider. As shown in the figure, the test does too much. It sets up a request, issues the request, then makes assertions about the response based on the data in the original request. That verifies how the end-to-end loop works right now, but it doesn’t verify that the caller correctly conforms to the contract, nor that the caller can handle any response the supplier is allowed to send. Consequently, some new release in the provider can change the response in an allowed but unexpected way, and the consumer will break.
Get hands-on with 1400+ tech skills courses.