Yep, I am probably going to piss a lot of people off with this post. But I have been privy to a conversation recently where some people were going back and forth on this topic, and since I have a giant megaphone (my blog) I felt like I should share my thoughts on this topic with everyone else. So let me first just start off by saying: I do not like code generation. In certain cases I think it can help greatly, but many people are far too eager to jump to this solution. I don’t think that there is anything particularly evil about the process of generating code, but I do feel like using code generation as a day to day tool is a very bad practice. Code generation should be the tool of last resort when there is no good way to cleanly implement a solution which doesn’t require code to be spread out everywhere. There are several reasons for this, which I will graciously inform you of…
1) Maintenance – Generated code can be a maintenance nightmare. If your solution to a problem is to just generate reams of code, then you have created that much more code that you now need to maintain. The alternative then is to simply make it so that you don’t touch your generated code at all, thus allowing it to be regenerated. This causes problems as well. Now you have to do things like create "buddy classes" that can hold metadata, creating partial classes which can hold custom code, maintaining templates so that you can generate all of your classes (including code for "one-offs"). Sadly, many of the problems that people use code generation for can be solved with a bit of reflection, a few abstract or virtual methods, and a sprinkling of interfaces. And don’t get me started on your arguments about the performance of reflection… I always prefer developer productivity to runtime productivity unless I can prove that I need the extra performance.
2) Flexibility – Generated code is often spit out by a custom piece of software or a template. This means that you either accept what is generated for you, or you have to customize the template. What happens when you need some piece of logic generated into a particular class? Well, you either edit your template to enable this case to be covered, or you create a new template for your class to enable this "one-off" solution. And all of this is assuming that you even have access to the templates which are driving your code generation and that you are able to swap out templates when you need to. These are two big assumptions, which quite often are not the case.
3) DRY – I put this one last in the list because I too am tired of people harping about the SOLID principles. They are extremely important, I just feel like I can’t open my feed reader without seeing SOLID about 15 times. So, this post is one more time! DRY is important though, and code generation can be the ultimate DRY violator if you aren’t using it for the right kind of code. Whenever I see someone use code generation for something that could be easily pushed into a base class or abstracted away into another chunk of functionality, I just want to scream! Code generation, when used, should be used for code which does not repeat. I’m sure there might be some exceptions to this, but I can’t think of any good ones right now. 🙂
So there you have it, Code Generation should be used sparingly, if at all. If Code Generation saves you typing for something that you would have had to manually write, then great! But if Code Generation is being used so that you don’t have to write some particular piece of code generically, then you will be bitten eventually! And I also realize that I am going to get 50 comments on this post saying "Dude, you are saying it is bad because people don’t use it right. If you have good developers, and they use it right, then code generation is a very useful tool!" Yes, I realize that, but not everyone is a good developer, and people don’t use code generation correctly. Done. Hope you enjoyed.