Writing Code That Writes Code
• Chris Liscio
• Chris Liscio
Introduction</b> <p> Because I have limited time to work on FuzzMeasure, I make sure that my development time is well-spent. Automation is a common technique that indie developers will suggest to help deal with the “one person, many jobs” struggle we all face. Much of the suggestions for automation seem to revolve around support efforts (retrieving lost license keys, building customer databases, etc). </p> <p> Indie developers often go an extra step, and add automation to the process of software release. Gus and I both have automated build scripts that pull a tagged release branch from our subversion repository, build it, strip it, and then construct a disk image. If I chose to do these tasks manually, I could possibly slip up and forget one of the details. Furthermore, since releases aren't always so close together (as much as I'd love to “release early, release often”), remembering exactly what needs to get done to build a release image gets challenging. </p> <p> In general, when you automate common tasks, you get time savings and repeatability — both very important benefits to indie developers. Time savings means more time to spend working on important code changes and support issues. Repeatability provides peace-of-mind to the developer, and helps build a solid reputation externally. </p> <p> So, how could we possibly save ourselves even more time? What else could we automate as developers? </p> <p> What if we automate the task of writing code? I can understand if some of you don't recognize this concept, because not everyone gets into situations where you can take advantage of automated code-generation. As usual, I'd like to use an example to help explain where this comes in handy. </p> A Recent Example <p> In FuzzMeasure, I need to add various filters for octave bands, third-octave bands, and A/C-weighting. When I started this task, I thought it might be a great idea to simply add the logic to FuzzMeasure that designs the filters based on various parameters. One of those parameters is sampling rate. </p> <p> Well, writing filter design code is highly non-trivial. It involves a lot of theory I'm not willing to learn right now. Even if I did decide to spend the time writing filter design code, then I'd be wasting time on making FuzzMeasure unnecessarily flexible. </p> <p> The way I got around this was to use Octave to design all my filters. The obvious benefit of this approach is that there are widely-known methods available for designing high-quality instrumentation-grade filters using Octave. I would use Octave to dump filter parameters, and write all the code to do filtering manually. </p> Employing Automation <p> After writing all the filter parameters into my code and testing if it'd work, I remembered that different sample rates warrant different filter parameters. I was half way through adding support for one other sampling rate when I realized how much time I was wasting, and how easily I could introduce mistakes. </p> <p> I then spent an hour or so writing a quick set of Octave scripts that write my code. Run the script, and out comes a .m and .h file that contain my filter parameters. At the top of the script is a list of sample rates that will get dumped. </p> <p> Had I decided to hand-write the code with the filter parameters, I could have easily lost about 4 or 5 hours (that's a good, solid day of work I often get to spend on a Saturday at home). After writing the scripts to dump the filter parameters in the same way that I was hand-writing them, and testing the code, I learned that I had a bug in the way I was hand-entering the values all along! </p> <p> Had I written the hundreds of lines of code by hand (about 1500), and then had to re-modify them all, it would have taken forever! The fix turned out to be a quick change to my code-writing script in Octave, and then the hundreds of correct lines came out all correctly in no time at all (ok, maybe about 20 seconds, because filter design is fairly math-intensive). </p> <p> At the time I first did this (a month ago), I thought that the scripts only saved me a bit of time in one shot. When I brought home my MOTU Traveler, I realized that I had missed a potential sampling rate (176400) in my list of filter parameters. Last night I added another entry in my list of sampling rates, and my filters were all ready! It took only a minute to update everything. </p> Conclusion <p> If you find yourself in the middle of writing a bunch of code that seems repetitive, take a step back and see if you could automate the process of writing that code. </p> <p> It won't work in all cases (how I'd love a “write FuzzMeasure” script — Step 1 - Come up with app idea, Step 2 - run script, Step 3 - Profit), but there are a myriad of situations where you can save yourself a lot of time. </p> <p> For example, you could easily write a script, or use a tool to generate a stubbed out .m file using only a skeleton .h file. I have tried to write some vim scripts bound to keys that try to do it, but in the end I tend to use Accessorizer. I also still tend to write a lot of that manually, because I simply haven't gotten into the groove of using helper tools. That's a whole other issue, though. </p>