
Jesse Schalken
I would also like to strongly discourage code generators.
Any code that has to be "generated" can and should have its common characteristics separated out with only unique characterstic remaining typically with an interface (i.e. type class) or polymorphic type dividing the two, creating a separation of concerns (this is really just abstraction).
Every software project which I've worked on that used a code generator turned into a nightmare, because when we find we need to change something about the generator's output, all the already generated code has to be updated manually while at the same time maintaining all of the unique modifications that have been since the code was first generated. It's a horrible duplication of program logic and maintenance work.
Of course code generation is perfectly fine when the output is not intended to be read and maintained by a human. For example, a compiler is technically a code generator, but it is purely for optimization purposes and the output is not intended to then be maintained by a human manually. A compiler might unroll a loop repeating the loop body a hundred times causing obvious duplication of logic, but it's fine because the assembler output is not intended to be maintained by a human, only the source input is. Efficiency and maintainability cannot be satisfied at the same time, which is why assembly sucks (not maintainable) and so do dynamic/scripting languages (not efficient), and compiled languages like Haskell are awesome (source code is highly maintainable, compiler output is highly efficient).
Anyway, from my experience if you're generating code intended to be maintained by a human, you're doing it wrong. Though I am very interested to hear counter examples.
*ahem* http://code.haskell.org/graphviz/utils/AttributeGenerator.hs Yes, it's ugly; the point is is that every time I want to edit what I do with the different Attributes in graphviz (e.g. I'm thinking of having "smart" Gen functions for QuickCheck tests that will generate specific types of Attributes suitable for DotNodes, etc.) I don't have to do so by hand and possibly edit code that's already there: I merely add the appropriate code-writing functions into that script, remove the already existing code, run the script and paste the result. Note that this is code that is generated at _write_ time, not build time; as much as possible the code is also generated to be human-readable: http://hackage.haskell.org/packages/archive/graphviz/2999.10.0.1/doc/html/sr... (but I have stuffed up in the past and tried editing it by hand only to have breakages because I did it piece-meal rather than doing so all in one go, which the script allows me). That is, the script is just there to help me out rather than doing some fancy auto-generation stuff which I have no control over. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com