Stop ruminating and build a prototype!
Most of my time spent as a second-semester college senior was in an open lab class. My partner and I elected to hack a Power Wheels car such that it could be remotely controlled via the Internet. In case you aren’t aware of Power Wheels, these are life-sized toy cars: big enough to be occupied by up to two children (or one ridiculous-looking adult).
One month into our project, we had developed our systems to a point where we could control the car from a remote command prompt. We could type commands to move the car forward and backward, turn the steering wheel, and honk the horn. Best of all, this was all running on Wi-Fi and batteries. Our vehicle was untethered—how cool!
root@gaucho:~$ echo 'H' > /dev/ttyS0 # Honk the horn
The final big task was to create a driving interface for regular people, to replace the unintuitive command line interface. My partner and I had been working under the assumption that I was the software/firmware lead and he was the hardware lead, so building this remaining component fell solidly into my domain.
Of course this task was no surprise, and I had been passively digesting these problems since the beginning. Driving this car from the Internet is complicated!
A week passed. My partner asked how the interface was coming along.
I told him that I basically knew what to do, but I had nothing to show at that moment. “Sure,” I said, “I could make the car move, no problem, but before I write the code I want to be done thinking about the design.” I wanted to avoid needing to do a nasty rewrite in the future.
He was satisfied. Then another week passed, and again he asked me about the interface.
Again I told him about how I was considering our many issues, and that it was complex. “I could do it,” I reiterated, “but it would be wasteful. We’ll have to throw it away if it’s not completely fleshed out.” Still I wanted to ruminate on the issues before writing (and possibly wasting) any code. Still I hadn’t made any visible progress.
Eventually he got tired of my reasoning, which must have sounded like excuses. He finally pointed out, “you keep saying that you could do this, so… well, why not just do it?”
Now I felt like my credibility was in question. Rather than rehashing my strategy of waiting for rumination to spark into a complete solution, I had to prove myself!
In a day or two I whipped up a prototype based on my best thinking about the architecture, and soon we were driving our car using big friendly HTML buttons. Ta-da! Now anyone could drive the car.
Now that we had our end-to-end prototype, we were able to start testing for the dreaded corner-cases and polishing for demo day.
Even though I thought the architecture was immature, the code I had implemented based on imagination proved to be good enough to address our complex issues. This was a pleasant surprise!
Having our prototype in-hand also exposed new problems beyond what we had imagined, like how the solder joints on some of our motor wires started to fracture with overuse. We also rebooted the car often and spent time wondering anxiously about whether it had “booted enough” to expect the website to control the car. We created solutions for both.
Using imagination to predict and address problems before they occurred may have been a great time saver. However, had we not prototyped early, these problems might not have surfaced in time for us create solutions for a successful demo day.
Developing a prototype, even if it’ll become scrap, will provide a realistic understanding of the scope of systems issues which will need solutions in the future. So, like my partner said, why not just do it?
Stop ruminating and build a prototype!
I was considering the problems we would hit: network latency/dropouts, network load, the car’s IP address being reassigned, what the controls would look like, and what would happen if two users tried to steer at the same time! If these corner-case scenarios could be imagined in detail, then I could architect a solution to support our needs from the start and avoid a major rewrite in the future. ↩
Which, in retrospect, sounds dumb. ↩
The interface was a website hosted on a fast engineering workstation, and a tiny CGI script listened on the car for HTTP requests. The car would boot up and tell the engineering server it’s IP address, which would be relayed to clients for them to start sending their control requests via AJAX. ↩
We were able to resolve the mechanical problems because we had plenty of time to observe our system in use, and prevent extra torqueing and glob on more solder. We also implemented a script to honk the horn twice when the network connection was established. ↩