views:

1089

answers:

9

I have heard people state that Code Generators and T4 templates should not be used. The logic behind that is that if you are generating code with a generator then there is a better more efficient way to build the code through generics and templating.

While I slightly agree with this statement above, I have not really found effective ways to build templates that can say for instance instantiate themselves. In otherwords I can never do :

return new T();

Additionally, if I want to generate code based on database values I have found that using Microsoft.SqlServer.Management.SMO in conjunction with T4 templates have been wonderful at generating mass amounts of code without having to copy / paste or use resharper.

Many of the problems I have found with Generics too is that to my shock there are a lot of developers who do not understand them. When I do examine generics for a solution, there are times where it gets complicated because C# states that you cannot do something that may seem logical in my mind.

What are your thoughts? Do you prefer to build a generator, or do you prefer to use generics? Also, how far can generics go? I know a decent amount about generics, but there are traps and pitfalls that I always run into that cause me to resort to a T4 template.

What is the more proper way to handle scenarios where you need a large amount of flexibility? Oh and as a bonus to this question, what are good resources on C# and Generics?

+8  A: 

You can do new T(); if you do this

public class Meh<T>
  where T : new()
{
  public static T CreateOne()
  {
    return new T();
  }
}

As for code-generators. I use one every day without any problems. I'm using one right now in fact :-)

Generics solve one problem, code-generators solve another. For example, creating a business model using a UML editor and then generating your classes with persistence code as I do all of the time using this tool couldn't be achieved with generics, because each persistent class is completely different.

As for a good source on generics. The best has got to be Jon Skeet's book of course! :-)

Peter Morris
I will have to check out Jon Skeet's book then. Yeah objects that persist cannot be generalized and tend to be large blocks of tedius code.
jwendl
+2  A: 

More code means more complexity. More complexity means more places for bugs to hide, which means longer fix cycles, which in turn means higher costs throughout the project.

Whenever possible, I prefer to minimize the amount of code to provide equivalent functionality; ideally using dynamic (programmatic) approaches rather than code generation. Reflection, attributes, aspects and generics provide lots of options for a DRY strategy, leaving generation as a last resort.

Morendil
Depends on the level of abstraction you are working/thinking at. Your compiler is also a code generator, but I suspect you are not kept up at night worrying about how much IL is being generated and how to keep the amount of IL minimized. High level code generation is the future for static languages.. every single product MS puts out now is using it
Schneider
+2  A: 

Maybe it is a bit harsh, but for me code generation smells.

That code generation is used means that there are numerous underlying common principles which may be expressed in a "Don't repeat yourself" fashion. It may take a bit longer, but it is satisfying when you end up with classes that only contain the bits that really change, based on an infrastructure that contains the mechanics.

As to Generics...no I don't have too many issues with it. The only thing that currently doesn't work is saying that

List<Animal> a = new List<Animal>();
List<object> o = a;

But even that will be possible in the next version of C#.

flq
DRY is important, I think that's why the question was on my mind. Although are you really repeating yourself if a generator is doing the repeating?
jwendl
No, that won't be possible in the next version of C#. Type parameter variance only will apply to interfaces and delegates.
Rafa Castaneda
A: 

Why does being able to copy/paste really, really fast, make it any more acceptable?

That's the only justification for code generation that I can see.

Even if the generator provides all the flexibility you need, you still have to learn how to use that flexibility - which is yet another layer of learning and testing required.

And even if it runs in zero time, it still bloats the code.

I rolled my own data access class. It knows everything about connections, transactions, stored procedure parms, etc, etc, and I only had to write all the ADO.NET stuff once.

It's now been so long since I had to write (or even look at) anything with a connection object in it, that I'd be hard pressed to remember the syntax offhand.

ChrisA
Maybe you've only ever seen really stupid code generators? I can't imagine anyone describing what lex and yacc do as being able to copy/paste really fast...
Sol
David Schmitt
@Sol: Fair enough - I was over-generalising. I'm referring mostly to the kind of code that gets generated by ORMs
ChrisA
@David: Sure, I understand that. I still prefer fixing a bug in one place, and _not_ having to replicate it in lots of places, even if the generator is quick and automatic.
ChrisA
A: 

Generics and code generation are two different things. In some cases you could use generics instead of code generation and for those I believe you should. For the other cases code generation is a powerful tool.

For all the cases where you simply need to generate code based on some data input, code generation is the way to go. The most obvious, but by no means the only example is the forms editor in Visual Studio. Here the input is the designer data and the output is the code. In this case generics is really no help at all, but it is very nice that VS simply generates the code based on the GUI layout.

Brian Rasmussen
A: 

Code generation, like generics, templates, and other such shortcuts, is a powerful tool. And as with most powerful tools, it amplifies the capaility of its user for good and for evil - they can't be separated.

So if you understand your code generator thoroughly, anticipate everything it will produce, and why, and intend it to do so for valid reasons, then have at it. But don't use it (or any of the other technique) to get you past a place where you're not to sure where you're headed, or how to get there.

Some people think that, if you get your current problem solved and some behavior implemented, you're golden. It's not always obvious how much cruft and opaqueness you leave in your trail for the next developer (which might be yourself.)

le dorfier
+3  A: 

Generating code isn't evil and it doesn't smell! The key is to generate the right code at the right time. I think T4 is great--I only use it occasionally, but when I do it is very helpful. To say, unconditionally, that generating code is bad is unconditionally crazy!

rp
+3  A: 

It seems to me code generators are fine as long as the code generation is part of your normal build process, rather than something you run once and then keep its output. I add this caveat because if just use the code generator once and discard the data that created it, you're just automatically creating a massive DRY violation and maintenance headache; whereas generating the code every time effectively means that whatever you are using to do the generating is the real source code, and the generated files are just intermediate compile stages that you should mostly ignore.

Lex and yacc are classic examples of tools of allow you to specify functionality in an efficient manner and generate efficient code from it. Trying to do their jobs by hand will lengthen your development time and probably produce less efficient and less readable code. And while you could certainly incorporate something like lex and yacc directly into your code and do their jobs at run time instead of at compile time, that would certainly add considerable complexity to your code and slow it down. If you actually need to change your specification at run time it might be worth it, but in most normal cases using lex/yacc to generate code for you at compile time is a big win.

Sol
I'd upvote you twice, if I could.
David Schmitt
Good answer and good point, yet philosophically if you could generate the code and enforce it to always be current then would it make a difference.
jwendl
A: 

Code generators could be considered a code smell that indicate a flaw or lack of functionality in the target langauge.

For example, while it has been said here that "Objects that persist can not be generalized", it would be better to think of it as "Objects in C# that automatically persist their data can not be generalized in C#", because I surely can in Python through the use of various methods.

The Python approach could, however, be emulated in static languages through the use of operator[ ](method_name as string), which either returns a functor or a string, depending on requirements. Unfortunately that solution is not always applicable, and returning a functor can be inconvenient.

The point I am making is that code generators indicate a flaw in a chosen language that are addressed by providing a more convenient specialised syntax for the specific problem at hand.

Arafangion