Code generation vs metaprogramming

The Active Record pattern is an "object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data". Metaprogramming in Lisp/Scheme, and to a limited extent Python and Ruby would generate a class library at run-time, for example to perform object-relational mapping with the ActiveRecord pattern. In Python at least, the only code you see is a the metaclass and decorators, with some custom logic added on.

Metaprogramming Benefits/Drawbacks
Metaprogramming keeps code small and simple. Meta-changes take place in one piece of code (the metaclass), and database modification is simple, making metaprogramming efficient for rapid prototyping. However, runtime reflection reduces performance (mitigated through caching of the analysis), and since the concrete code does not exist until run-time, there is no static checking of method calls or IDE auto-completion and contextual help for methods. Step-through debugging is complicated for runtime-generated methods compared to concrete methods. Metaprogrammingmay also run into language limitations (not with Lisp macros),necessitating code-generation to produce 'scaffolding' in certain cases. Code generation in PHP, Java, C#, generates the code of the class library from templates. Custom logic is added in sub-classes or re-opened partial classes. 

Code Generation Benefits/Drawbacks
Code Generation incurs no runtime performance hit, because analysis is during generation & compilation. Compilers can check uses of the generated code and IDEs provide contextual documentation and auto-completion, and debuggers transparently step through the generated code. Code generation templates may also be more general than the limited metaprogramming features e.g. of Python/Ruby. However, the entire library must be re-generated when changing the templates or database schema, which may encourage over-architecting and reluctance to revise the model later, due to the added difficulty of implementing changes (unless planned out so as to support easy/quick re-generation). Also, debugging generated code involves a very slow edit(template)-generate-compile-run cycle, instead of the edit(metacode)-run cycle of metaprogramming. 

Code Generation & Source Control
Code templates should be checked in, but it seems so is the generated code.  If pure generated code were not checked in, then code would be a 'pre-build' step, with the drawback of configuring and running the generator locally before the first compile.

I would tend to prefer metaprogramming in most cases, if only because I like small, tidy code. One might imagine that the generated code is not really code to avoid feeling like the code is bloated, because you may end up with as much as 90% of the code in your application being auto-generated. C2 Wiki helpfully points out that compilers are code generators of assembly and machine language, and interpreters are generators of bytecode.  So everyone uses code generation... the question here is whether to generate code for the language one is typically writing in. Code generation uses a higher level language to output code in a lower-level one, so needing code generators for Java/C# means that in some sense Java/C# are too 'low-level' for certain tasks.

Popular posts from this blog

Cutting down on clutter with the Outbox Method

A comparison of file synchronisation software