Sunday 25 October 2015

Playing Nicely with Each Other



Nearly every app or piece of software of any reasonable size will end up having to integrate with another system, most commonly some kind of server.
This kind of integration can very often be a painful experience, two systems designed to come together seamlessly end up singing from different song sheets.
This pain also often results in aspersions being cast and blame being apportioned, "this is a server issue" or "it all looks fine in our logs".
So are we always doomed to this integration hell or are there things we can do to smooth the road?
Here not Everywhere
First of all integration shouldn't be all pervasive, code you don't control is dangerous, when you integrate with another system the surface area of your code that is exposed to this danger needs to be kept to a minimum.
When explaining the integration you need to be able to draw a circle around the class, package or namespace thats responsible for getting the job done. If you end up having to draw multiple shapes on the page to explain it all your probably just explaining how any changes in the system your integrating with are going to cause large scale destruction in your code.
Its also important, as always, that the integration is represented by a well engineered abstraction within your code. You never want your code to be exposed to details, this is especially true when you don't control those details.
For example you may be making a server call to get user data from a server, the only relevance to the rest of the code is that this data will be retrieved asynchronously from some source, the fact its an HTTP request or a SQL  query is detail. You need to throw another value into the header or adjust the query go right ahead its all in this class here.    
Its Not You Its Me
When it comes to testing your integration its important that your in a position where you can vary one thing at a time.
To go back to our example of making a server call, it should be possible to test your code against an idealised stubbed version of the server, whether this be loading data from a file or a more formal approach that provides some kind of virtualised backend.
Equally its important that on the server end you have some way to exercise your API that doesn't involve the application.
Obviously at some point everything needs to come together but before you leap headlong into it you need to have established some kind of confidence that your code works. If you don't have that confidence when something does go wrong you'll be left shrugging and probably laying the blame with the other guys.
Having this ability to stub or fake the interaction with the other system will also naturally force us to think about the interface, "exactly what is the JSON schema going to be?", "what format do you want us to send that in?". 
Independently Verified
Once we have defined the nature of that interface were in a really good position to practice some TDD and give ourselves another way to prove the integration is working.
As is the case with most things unit tests provide an effective first line of defence against things getting broken and can also be useful in playing out some "what if" scenarios.
We are now able to prove our individual classes work with our unit tests, prove our system as a whole works by using our replacement or fake server before finally attempting to actually integrate.
Despite all of this careful preparation things will still go wrong, quite often because one of the systems fails to comply with the agreed contract, "if I give you this your supposed to give me that".
In order for us to know whats going wrong we need to have identified exactly what that contract is and we need some way of verifying that individual elements when given the correct input will supply the correct output.
This isn't about apportioning blame its about having a way to quickly identify what needs fixing and fixing it, were all in this together after all.     

No comments:

Post a Comment