Friday, October 16, 2015

A red, green, and blue silver lining

The Arduino platform was created more for design students than professional code-slingers.  Which is cool -- that's a noble rationale, actually.  But it comes back to bite in one way.  See, the folks who adapted its (C++-ish) programming language from the Java-ish "Processing" language aren't really able to support one reality of the modern programmers life.  And that's unit-testing. 

Again, I'm not criticising, because as it turns out, it's sort of a net win.

But first some background/terminology for non-programmers.  "Unit testing" is the act of testing the smallest possible chunks of one's code.  In modern development environments, you tend to write a function hand-in-glove with its test.  The test defines what the expected outcome is for any inputs set.  Then you (or some more automated process) runs the test against your actual code and verifies that the function did what it was expected to do.

(Aside:  Later during the application development process, there are other forms of testing, such as integration testing--did your feature break somebody else's function?--plus performance-testing, and vulnerability scans, etc.  For the purposes of this blog item, we're only focusing on unit-testing.)


In the Arduino world, which relies on the micro-controller taking input from physical sensors, or outputting to physical widgets, simulating that in software would be a boil-the-ocean endeavour.  That's mainly due to ever-growing number of widgets that are compatible with the Arduino.  For a community-supported foundation running on the proverbial shoe-string, that's too much to ask.  And, in any case, I think I can safely say that the community would muuuuuuch prefer to see those limited resources devoted to the core platform.

So for a complex project that involves multiple widgets, one solution is to write your code as separate projects, test it in a more atomic (meaning indivisible) fashion, and roll the tested code into the master project.  For example, my "master" project is a lighting system for the Office Finches.  There are a number of elements that go into that:
  • Two sets of bright white LEDs that are controlled by an integrated circuit because the Arduino itself doesn't have enough "pins," (i.e., input/output ports) for the number of lights needed.
  • One triplet of red, blue, and green lights that can fade in and out.  With 256 possible brightnesses available for each LED, this comes out to over 16.7 million combinations of red, green, and blue.  The idea is to gradually fade these colours in and out to compensate for the lack of full-spectrum daylight.
  • A real-time clock to determine what time it is to turn the lights on in the morning and when to turn them off at night.  (The Arduino, having a fairly primitive microcontroller, does not have an internal clock in the sense that we know it.)
    A passive infrared sensor that is activated (only in the dark) to determine whether one (or more) of the Office Finches has fallen off her/his perch.
  • One triplet of "soft" white LEDs to be used as an "emergency" night-light.  They are gradually raised if motion is detected by the infrared sensor over a few seconds, and gradually lowered when the finches have settled back in.
  • A photo-sensitive resistor to determine whether it's dark enough to warrant the emergency night-lighting.
As I write, I'm testing the red-green-blue lighting.  The "night-light" feature has been tested, as it was the nucleus of the whole setup.  Tomorrow will probably be devoted in part to deciphering some really old (in computer years) documentation for the real time clock and setting that up for unit-testing (again, in a separate project).

Normally, having multiple copies of the same functionality is frowned-upon in software development.  The reason being that it means that you have to remember to deploy bug fixes or improvements across those copies, which costs time for the coders as well as the testers.

But in this case, I rarely modify the "test" copies of the code once they're verified and rolled into the master project.  Which leaves me with bite-sized bits of single-function code that can be used as reference for (or imported lock-stock-and-barrel into future projects.  As long as I name them descriptively and document the functionality (which of course I do--'cuz that's how we roll chez fivechimera), it's All Good.


In this case, what I'd normally consider a "primitive" lack of testing infrastructure turns out to be a net win.  It's another one of those things they don't teach you in Programmer School.  That's not the point, after all--their job is to mold you into a cog that can be plugged into the machinery...at least for the first year or three.  But eventually, you figure out when and where "the rules" can (productively) be broken.  That's one of those career inflection-points where you slough off another bit of your "programmer" skin to reveal the "software developer" underneath.