John Baylor experiments

Self-Modifying Code or Self-Creating Code?

[aside: Why write an email that will be read by just one or two people when you can instead write a blog post that will be seen by... uh... one or two people?]

I was recently discussing the problem of tracing program execution through code that doesn’t exist.  Sometimes, usually to understand and debug a program, you need to trace through it. If the code doesn’t exist, its hard to follow where it goes. Actually, the code exists, its just not in source control or otherwise easily searchable.  Let me explain.

In Ruby, whose source code is a lot like its executable format, its trivial to write code that writes code – so you, the programmer, don’t have to. The Rails web framework uses this a lot, for creating whatever form of ‘find’ strikes your fancy: find_by_firstname, find_by_firstname_and_gender, find_by_pet_species_and_viciousness, etc. – as long as your database table has the appropriately named columns then it will find what you’re looking for with no work on your part!  Actually, some work is required – you need to know that most any routine starting with ‘find’ is probably auto-generated by Rails and thus will be un-findable in the source tree.

A more complex example is the routing helpers – a shorthand way of saying “put a link here on this web page that will take the user to that web page over there.  Until you realize that most any method ending in ‘path’ is a URL helper then you’ll be confused by code that references user_edit_path or formatted_pet_list_path or formatted_pet_species_list_path.  The last one says that you want to get the path to a specially-formatted list of the various pet species represented by the system (e.g. “http://myPetSite.com/pet_species/list.csv”). Fairly clear once you know what it does, but fairly obtuse until you get to that point.  And it is, trust me on this, shorter, more maintainable and more clear than the alternative (after, of course, you learn to read it).

So this difficulty in finding the source to “formatted_pet_species_list_path” (or something like that) started a discussion that eventually got around to the idea that Ruby and Rails uses code to write code.

“Its the 11th commandment”, said one, ” – thou shalt not write self-modifying code!”

Yes and no. Call me irrationally exuberant or say that I drank some sugary flavored colored water – but I don’t think its as cut-and-dried as it used to be.  This commandment, when Moses brought it down from on high, was written for a compiled language, where the source was very very different from the executing code, and it actually did modify the code being executed.  This is bad bad bad – its hard to understand, it leads to intractable bugs, it’ll make you go blind, melt glaciers and other bad stuff.  No argument there.

But is this what Rails is doing with Ruby? I’d say its different.  Instead of modifying existing code it is merely creating code that did not exist before. Its more akin to a pre-processor that could, just before compiling a program, generate all the permutations of finding database rows from columns X, Y and Z (and any number of others).  Looked at this way, it appears to be similar to a C++ template – generic code that a programmer has written to simplify the writing of code that does similar things in similar ways.  The main difference is that with Ruby there is no pre-processor – the routine gets created at the time it is first used.

The “template” in this case is a routine called method_missing that gets handed the name and arguments of any routine that doesn’t exist.  It looks for a function name matching the form ‘find_by_X‘ where X makes sense for the database table in question (of course, if it doesn’t match the correct format then it just passes the name and arguments onward for some other routine to either make sense of or to burp up an error).  Once the routine is created it is available to be called again, with none of the overhead incurred when it was first created. More importantly, it was created with no additional overhead on the part of the programmer – to write it, test it, debug it or modify it. This, in my opinion, is a huge advantage – but I’m a lazy developer who doesn’t want to write or debug any code that I don’t have to.

Kool-aid anyone?

Blog format shamelessly lifted from Mojombo, creator of Jekyll