Showing posts with label Reminder. Show all posts
Showing posts with label Reminder. Show all posts

Monday, April 7, 2008

T4 and something to keep in mind...

A friend of mine recently did a post on the T4 framework (Text Template Transformation Toolkit) here. I had been following the technology for a little bit but I haven't had the opportunity to actually use it (just literature till now). After reading that post, I decided it was time to put on the water-wings and give it a whirl from within VS2008 (no additional downloads for VS2008). Needless to say, its pretty good. Honestly, its about time they built a template engine directly into the IDE. I think this will encourage a host of folk to rally around the banner of Code Generation goodness.

With all that said, there is a small thing to keep in mind. It's something that, when you think about it, is quite obvious, yet because of its nice "integration" with VS2008 its easy to overlook (well for me it was anyway).

What I wanted to do was, quite simply, using code inspection, create a set of interfaces and base implementation classes for a set of types. For example:

public interface INodeVisitor
{
bool Walk(BlockStatement node);
void Postwalk(BlockStatement node);

bool Walk(ScopeStatement node);
// .... continue on
}



I thought it would be a funky "first time" use of the template engine as if I added a new type, both my IVisitor and the various default implementations could be generated. I was quite proud of myself for finding such a nice "practical" use for T4 (I really didn't want to do the atypical "generate the business objects from the database" routine). The problem is, even though the template "looks" like it is part of your solution - it is important to realise that only the generated file is actually part of your solution, and not the template itself (ok, technically, that's wrong. The template is part of your solution, its just not within the same "code scope" - if I can call it that...). That is to say, you don't have access to types, from within the template (via template statements and/or features), that are defined within the same solution.



The reason for this is actually very simple and straightforward. The default T4 compiler kicks in via an "external" command line call with, compiles the template file, applies the transforms and generates your file. Therefore, like I have mentioned, its important to keep in mind that the template compilation and file generation happens outside of the scope of your own solution's compilation cycle. However, the generated file will still be compiled as part of your solution's normal compilation cycle.



Now before everyone pipes up at once, I do realise that using template directives, you can reference another assembly. The only issue is, that from what I saw, it required the full path to the assembly (i.e. "C:\development\someproject\bin\debug\somedll.dll"). I am not a huge fan of this, because of the potential for different build configurations (do you import the debug version of the assembly or the release version?). It just felt a little dirty to me. Also, we wont even step into issues like what happens on the first time build when the assembly doesn't yet exist. I guess you could use the hostspecific="true" and try and interact with the code model using the EnvDTE (from what I know the Visual Studio T4 host implements IServiceProvider) but I haven't gone that far just yet. Something to look into. Perhaps the topic of another post...



Anyway, like I said, nothing major, and not something that should stop anyone from using T4 - generally most (if not all) the other template engines should suffer the same limitation. It's just something to keep in mind when designing/creating your templates. It's way to easy to assume that because its within your solution explorer, that it has the built-in ability to access all types available within your assembly.



To sum up. T4 - I like it. I'll probably make more use of it where I can - especially in the area of boilerplate test cases - even if I have to "full path" the assembly reference (or use some DTE magic - is that even possible?) The simple fact that I don't have to bounce out to another application to compile the template and that there are no additional downloads, makes it a winner for me. It's really useful when you just want to quickly whip something up to "fill that gap" and not have to alt-tab for it and contend with project file changes and reloads...



My only gripe? No built-in intellisense! I guess that if you don't want to have download and install something like this T4 Editor, template edition is going to have to be done without all our new fan-dangled toys and back to the notepad roots! (for now, at least ;D).

Wednesday, March 5, 2008

Don't forget about string.IsNullOrEmpty() in .NET 2.0

I have noticed, in my travels though code written by others, that string.IsNullOrEmpty is simply being overlooked.

As most of you know by now, its much better practice, performance wise, to check if length of a string is less than or equal to zero, than comparing it to "" or string.Empty, when trying to determine if its an empty string or not. For those of you who didn't (yes you, in the back, I see you) here is a MSDN article that answers the question. Anyways, I digress and that's not the focus of this post.

The point is that in .NET 1.1 you did the classic:

if( someString == null || someString.Length <= 0 )
return;


Fantastic. However, typing that every time you want to do a "is the string empty check" gets old quite fast. Never fear - MS to the rescue of our ever precious keystrokes. It was decided that in .NET 2.0 that a static function, doing just the above, would become part of the public string interface and save us a little of the hassle.



Now the above code can be "simplified" as:

if( string.IsNullOrEmpty(someString) )
return;


It's a lot more expressive of intent, therefore more readable and as an added bonus, less of a pain to type (a massive 12 chars including white space ;P).



I have just noticed that a great deal of developers either don't now about it, simply don't use it or are still comparing strings to "", hence this post. Not exactly a "wow" or "this-going-to-change-my-life-forever-thank-you-so-much" post, but hopefully it will serve its purpose. It's just a little reminder to those who have made the move from 1.x to 2.0+ (or are just starting) that it's there... aching to be used.