Tearing Down Technical Dependencies
Technology is impossible without dependencies. One software module depends upon another. An application depends on the firmware sitting below it to access resources, while that firmware likewise depends on the hardware that it’s interfacing with. And, especially in IoT, that hardware depends on how it interfaces with the physical world it’s a part of.
We may need them, but software dependencies bring a host of problems with them. First, they are a major source of bugs, which arise from often invisible incompatibilities. Second, when a dependency changes, we likewise need to update the tech that depends upon it, and this can leave us in a never-ending refresh cycle. And, of course, integrating diverse technologies poses a huge challenge, especially when they’ve been developed in silos and we wait until the end to put them together.
That’s why we need a tempered approach to dependency management. We need to pick our dependencies wisely.
For instance, Very uses Nerves as our IoT platform of choice because it gives our developers such granular control over their dependencies. While this embedded Linux can integrate dependencies from everything ranging from C to Python, one of Nerve’s defining features is its ability to only ship what we need.
Most Linux distributions ship the entire kernel by default alongside a swath of software that ranges from “almost always important” to “is this really necessary?” With Nerves, however, you’re in the driver’s seat. You get to choose what drivers to install, which bootloader to include, which network utilities to use, and much more.
We’re always looking for creative ways to cut down on dependencies. However, for the dependencies we do embrace, we keep a fundamental truth at the front of our minds.
Rebecca Grinter, PhD in Information and Computer Science, writes that,
This insight into the correlation between technical dependencies and social dependencies is just as true now as when Dr. Grinter wrote it in her 1996 dissertation. The only difference, especially when it comes to IoT, is that we’re now simultaneously working across the entire tech stack, including device hardware, firmware, server backends, and user front-ends.
Building Team Dependencies
The result of this focus is Very’s culture of blending teams from across expertise domains. While we may be a fully remote company, that doesn’t stop us from constantly communicating, continually integrating, and perpetually iterating. We’re fully committed to the most important agile development principles as we interpret them:
- Continuously deliver value to end-users.
- Ensure features are production-ready before moving on to new features.
- Test early and often.
- Make a decision at the last responsible moment, and not before.
An especially crucial part of our IoT development process is agile hardware development. While many organizations use a waterfall methodology where they finish building hardware before starting on the firmware, which in turn must be finished before starting on the server backend—and so on—Very’s agile approach enables us to collaboratively and concurrently work on these different parts of the stack.
Take the example of designing custom circuitry. Our hardware and firmware engineers are all equipped with Voltera 3D printers for printing their own circuit boards. The hardware engineers can work together on a prototype by putting their hands on the same components, and once an iteration is complete, the firmware engineers can print the board and start writing code. If something doesn’t work, they can tell the hardware people, who will build the next prototype.
Then, once we have a minimum code base for interacting with the hardware, the server engineers can then begin simulating their target environment so that they can start working. As a result, the front-end developers now have a mockup server to interface with.
The real takeaway is that this methodology fosters genuine relationships that are built on trust. So, when the one type of developer trusts another domain’s engineers, they’re able to depend on each other to create a fully integrated system.
These dependencies, the ones that involve relying on our co-workers on a basic, human level, are the key to successful technical dependencies.
At the end of the day, we’re left with a blueprint for a reasonable IoT product. They are as follows:
- Understand your dependencies.
- Minimize dependency, both in hardware and software.
- Mock/simulate target-specific dependencies.
- Integrate early and often.
By building up interpersonal dependencies and stripping away technical dependencies, we’re able to create products that are robust, fault-tolerant, and feature-rich. Of course, we care about the software APIs that tie our programs together, but what’s even more important are the interpersonal APIs that unite us into a team.
And, as a result, we can finally say: