It seems like in every job I take, I eventually end up developing an API, or a programming language, or a macro processor, or something similar. I don’t know if this is characteristic of the sorts of jobs I take, or if it’s just a reflection of the sort of approach I tend to take to solving problems. I suspect both factors are at play.
My latest foray into tool development started innocently enough. At Zing, we develop software and hardware for portable entertainment devices. Examples would be MP3 players, satellite radios, and portable internet radio streaming devices.
Anyway, one of the guys on the development team suggested that we ought to implement a bit of software to simulate the actions of a user – pressing buttons, spinning the scroll wheel, changing the volume, that sort of thing. Apparently Palm used a similar system (called a Gremlin) to flush out some of the more obscure timing-related bugs in their software.
Our version was called the UI Monkey (after the Infinite Monkey Theorem). The initial implementation was fairly straightforward, generating random user-input events and feeding them into the event queue on the device.
Then someone wanted a way to record and play back events, so we could do some testing automation. That was straightforward enough, though anyone who’s implemented UI automation on such a low level can tell you than the resulting scripts are very fragile, in that any tiny change to the UI will break the script.
Once I had the basic framework in place, more requests came in, everything from “can we have the monkey scripts check for success?”, to “how about implementing a way to repeat a bunch of actions over and over?”. Since the whole Monkey code structure was based on sending and receiving UI events, other features had to be hacked in as “special” events, which each had their own syntax. After I had finished “goto”, and had started working on some other features, I decided it was time to take a step back from the ledge and re-evaluate my options.
Despite the great amount of interest expressed in UI automation, nobody else was using the system I’d created. Given the sheer impenetrability of the syntax, I can’t really blame them, but it was a little disappointing. I decided it was time to come up with something a little less insane, and a bit more appropachable.
The one thing I was pretty sure of was that I didn’t want to implement my own scripting language from scratch. While designing your own language is an interesting project, and gives you a lot of power, it always takes a lot longer than you’d expect, and you’re never really done. Implementing a “Monkey library” on top of a more-standard language seemed like a better bet.
I considered using C# as our UI scripting language. Unfortunately, C# requires a fair amount of boilerplate code just to make a basic loadable assembly, and a lot of the folkks that want to do scripting aren’;t familiar with the development tools. So, some kind of scripting language seemed to be in order. As it turns out, we already have a scripting language interpreter embedded into our product (which is another story, and a great example of the Law Of Unintended Consequences at work).
So, I threw out all of the crazy hacky code I had been writing, and re-built the Monkey on top of Lua, a light-weight scripting language. Instead of an event recording and playback system, we now have a set of event-related primatives, and a real programming language to call them from, with functions, for loops, if-then-else, and variables. The integration of the Lua and C++/C# code was pretty easy, as well.