30 September 2009

My recent transformation from hating code generators to loving them

For a long time now I believed that code generators were evil. When I discussed this topic I mainly gave these reasons:
  • a strong believe that you could pack every code into a class and just use it from there
  • a chapter from The Pragmatic Programmer I wrongly remembered as "Beware of evil code wizards"
  • bad experience with MFC Wizards(VS 4.2) for database based data entry / viewing dialogs
It didn't came to my mind until now that I was already using code generators everyday:
  • Automatically add using references when typing still unreferenced types
  • Using Resharper's Complete Code to insert delegates or create method stubs
  • using Resharper's Live Templates to insert unit testing stubs
Perhaps they were so small and convenient that I didn't recognize them as code generators. Lateley I had to do a lot of WCF programming. First I totally rejected the recommended way of using Web References because they generated tons of code I didn't understand. I wanted to do it like Juval Löwy, that means
  • refactor all contracts into a ServiceContract dll
  • reference this dll from the server and the client
  • let the client use a ChannelFactory to create a proxy on the fly from the service interface
This was an elegant and easy to understand solution. Additionaly I would got compiler errors if I changed an interface and forgot to change the client. This is absolutely necessary if you use Continous Integration. Then I needed to think more and more about cross cutting concerns with WCF proxies like
  • retrying failed service calls
  • authentication
  • central exception handling

Some of these things cannot be simply refactored into another class and just used. Basically, often you need to wrap every method into a try-catch block or do some common initialization. You have to do the same thing over and over again, and if every member in your team has to do it also it becomes a nightmare to ensure that everyone is doing it in the same way. In parallel I needed to do some Silverlight clients for the same WCF services. This should be easy, but with Silverlight you can't reference the ServiceContract dll generated by normal .net (because it uses a different runtime version) and even worse you need to use the asnychronous communication modell, which means you need another interface with other methods. Combined with the additional needed cross cutting concerns and soon you have a very unmaintainable code base.

In this situation I started to think of a code generator that could generate proxies for silverlight and .net with allthe special cross cutting stuff from one single source. I started to develop it, and a day later I had a protypegenerating working proxies. I spent another day with integrating it into Visual Studio and the automatic build and then it was obvious to me that this was the right solution to my problems. Integrating cross cutting concerns is really simple, all the special knowledge is encapsulated inseid the proxy generator, proxies get regenerated on every automatic build with the newest proxy generator, team members just add a custom service generation step and start using the proxies. No more code reviews and no more search and replace through the whole code base if a cross cutting concern changes.

After this experience I have now reread the chapter about evil wizards and learned that my understanding mutated over the years. Actually the pragamatic programmer encourages you to build code generators to automate repetive tasks. The evil is not the code generation itself. The evil is, that you get code that you don't understandand that you must modify it, because it is like a framework. After a modification you cannot regenerateit without loosing your modifications.

Having this remembered and extended my understanding I can now happily say that generating code from file A to file B in a repeatable way is always safe. Its just like a compiler for a DSL stored in file A. Just don't modify B. Creating method stubs or unit test hull is also safe, even if you need to modify them, because they are small and understandable. But keep aware of run-once-wizards which generate complex application frameworks that you don't understand.

No comments:

Post a Comment