Design by contract is nothing new. The term was first coined by Bertrand Meyer in the 1980s, and was influenced by his work on the Eiffel programming language. For those of you who haven’t been attempting to implement it for the past couple of decades, design by contract is essentially writing your API connections first and then the rest your code.
For me personally, it really came to the forefront in my past life as an enterprise developer when Web Services, WSDL and SOAP were finalized and we adopted SOAP version 1.0 to modernize our application server monitoring solution. Like many teams at the time, we didn’t really embrace design by contract. Instead we designed the contract based upon the API’s we had already created. To be fair, the constructs for really designing by contract then did not have the maturity that they do today.
Design by Contract Today
Fast forward 15 years later, and the WSDL/Web Services tool chains are robust and mature. We’ve also seen the advent of RESTful services and several competing standards for the contracts for REST such as RAML, Swagger, etc. Yet many teams, including my last one, continue to code first, and then generate the contract from their code later. This is not sustainable for modern, large scale IoT projects and products.
Due to the heterogenous skill sets and complexity of IoT, rarely does one team or even one organization actually own all the pieces. There are edge smart devices, interim gateways, middle tier layers, data access layers, presentation layers, mobile access layers, and the list goes on and on.
With so many moving parts, building contracts based on implementation is very risky. When you allow the implementation to drive the contract — the contract changes. When a contract changes in a n-tier solution, the ramifications are felt at every tier.
My Own Dog Food-ing
In addition to my day job, I have the privilege of being the CTO of an aquaponics farm out in East Texas. In the interest of full disclosure, the farm is owned and run by my wife. One of the farm’s goals is to use automation and high-fidelity data to optimize the farms outputs and minimize its inputs. I find myself trying to implement an industrial strength IoT solution for our greenhouse on my nights and weekends.
It’s a small project, but it shares many characteristics of larger IoT projects. The edge devices were still in development and with an uncertain production schedule. My schedule is I can code, or I can solder, I can’t do both at the same time. I also have to deal with intervening service and presentation layers under development.
To combat these problems, I chose Swagger 2.0 and started with the API definitions first. Truly designing by contract, and I’m very glad I did. Establishing the interfaces first helped deal with the chaos of getting the greenhouse online in a very short period of time. First off, there was a platform change on the device side, going back and forth from an ARM based microcontroller, to an ARM based SOC implementation.
Basically moving all the device code from C to Python. With a decent spec, and the helpful swagger code gen, those moves were made much less painful as all I had to re-implement was low-level I2C and one wire code. All the really hard work of managing types, making requests, and understanding data flow was already managed for me.
I could also leverage open source and community code better because I had a contract. It was easy to borrow the pieces I needed and feel that confident everything would integrate at the end.
How Design by Contract Helps IoT
Based on my research, most IoT projects go over budget and take longer than anticipated. With contracts, you can develop and test each layer of an IoT application in parallel. Each layer only fulfills its contract, and so performing test driven development is easy.
Last week, I was finishing fabrication on the greenhouse device and completing the re-write of the code from C to Python. The other layers thankfully had been stable, and having that contract available throughout made the porting process that much easier.
Late Sunday afternoon, everything was built, and coded and for the first time. I tested the entire solution from device to gateway to private cloud storage through to presentation and mobile, and it worked the very first run! This was only possible because, despite a hectic schedule and uncertain timelines, I could test each component in the trail and ensure interoperability.
Had I followed typical software development practices and then finalized the contract, those last minute changes in implementation would have required additional time on each and every component. That would have been a disaster and I only needed to coordinate with myself!
Thankfully, the requirements for each piece were clear from day one and each application tier knew exactly what it’s inputs and outputs were so last minute changes didn’t cascade. So many of us, historically, have treated design by contract as something that costs too much time to do right. Given the multi-vendor and multi-disciplinary nature of many IoT projects, I submit you can’t afford not to.