I have a pretty deeply ingrained abhorance of code generation. Note bytecode enhancement at runtime; that I'm really into. There's no baggage with that, no chance for the build process to screw it up, no need for a developer to go modify the output, no chance for bad merges or lost changes.
I've never like code generation; my early exposure to NeXT and InterfaceBuilder really showed off why it wasn't necessary for GUIs and I still don't think its needed for enterprise apps.
Code generation is a last resort that should only be used when real techniques fail. For me, real techniques are combinations of components and service-oriented architectures .. the kind of stuff you see in Tapestry and HiveMind.
In MDA, you define your system in terms of objects and relationships ... but then you spew out code representing that system that isn't isomorphic to the system you defined. If it was truly isomophic, you would be able to reconsititute your original model from it, but that's simply not reasonable.
In my vision of a proper MDA, the objects and relationships in the model would be directly expressed by matching objects and relationships in the runtime image. In Tapestry terms ... application extensions and helper beans; in HiveMind terms, services and implementations. In both cases, I would expect that the MDA would provide a library of the components (and service implementations) referenced in the model and the runtime image.
Tapestry has room for meta properties in all the key elements; it is quite reasonable for a tool to plug in meta data into pages, components and helper beans to support seamless round-trip engineering ... reading the output to reconstitute the original model. Wouldn't be, couldn't be, perfect ... but it would be better than spewing out code.
Still, if the underlying problem is the complexity of J2EE in terms of getting reasonably sized projects working ... then J2EE is overused and should be bypassed. EJBs don't lend themselves to real, lightweight, agile development models (XP or not) ... they are too reliant on the container and on the runtime environment to be easily tested outside of that container. Any reasonable development model involves running frequent tests ... for example, Tapestry has around 400 tests that run in 40 seconds (and I want to speed that up significantly). HiveMind has 160 tests that run in three seconds. Did I break something? Click the test button.
At work, for me to test an EJB change requires a build (to package the EJB and deploy it) which is currenlty taking about ten minutes. You read that right ... we have some issues with our build environment (they're being worked worked on, but ... "House built on a bad foundation ...")
So, with every change requiring a minimum of ten minutes to validate (usually, much, much longer) agile is dead. Refactoring to use HiveMind (or other microkernels) could support a fast, robust, agile methodology ... and bring into question whether MDA makes sense.
Meanwhile, my other peeve with MDA is that it assumes there will be one uber-developer (the architect) who can create the model, and create the code generation scripts (or modify the supplied ones). How many people can wear that many hats? Doesn't that create a choke point? Isn't that another block to agility ... you don't fix your code, you have to find and fix the code that generates your code, regenerate all, retest, hope it didn't break something outside your fiefdom.
MDA. Offshort outsourcing. Mission statements. ISO 9000. What's the next fad that's going to distract me from getting actual work done?