A rare retrospective on a decade-long research project
Philip Levis looks back on the history of TinyOS1, one of the earliest sensor networking platforms, reflecting on its evolution, and design choices and their consequences. It is an honest look at what worked and what didn’t. Such retrospectives are rare, and I really wish more researchers did this.
On the tradeoff between growing the language to support complex (but necessary) functionality, and keeping it simple:
Early on in TinyOS development we made the decision to design a language to better support its pro- gramming and concurrency model. The nesC language allowed TinyOS to achieve near-optimal resource effi- ciency (minimization) and a surprisingly low bug rate (prevention). Having a new language also allowed us to evolve and extend features as new problems arose. Language evolution is a two-edged sword… each stage of this evolution added new features, moving TinyOS and nesC further from C and raising the barrier to entry. Furthermore, the most effective software patterns, such as static virtualization, used all of these features in complex and novel ways. By focusing on expert TinyOS users and making it possible to write larger software, TinyOS 2.x became less accessible to new users. Making it harder to write buggy code had the unfortunate result of making it just plain harder to write code.
On the importance of quick rewards for beginner users:
In retrospect, the focus on expert users missed a great opportunity: hobbyists and the “Maker” do-it-yourself crowd…In comparison to TinyOS, Arduino is feature-poor: programs are single- threaded C programs for simple sensing and actuation. But for hobbyists, the resulting simplicity is extremely desirable. Building a gumball machine that “only dispenses treats when you knock the secret rhythm on its front panel” (an article in a recent issue of Make maga- zine) doesn’t require static virtualization, network types, and compile-time data race detection.
And on that long-contested question in software engineering, the usefulness of reusable components, and how hard it is to actually achieve that23. TinyOS has a fine-grained component model, but it turned out not to help.
The main goal of this approach was to ease experimentation. But taken to its conclusion, fine-grained components have significant drawbacks we did not foresee…the drawback of fine-grained components emerges when trying to understand a system for the first time. There are so many tiny pieces of functionality spread across files, with numerous levels of indirection, that keeping track of it all can be a headache. The structural complexity is far beyond what the underlying code complexity requires. Our conclusion is that a well designed and carefully implemented operating system is more helpful than an operating system toolkit or operating system software designed with reuse in mind. Our experience with deveoping more traditional operating systems supports this conclusion. It is easier to take the Linux boot code and modify it for your needs than to work within a component framework for its generalized boot module
(All emphasis mine.)