Coding Practices
Coding Practices
It's surprising to me that, so far, I haven't been able to find any blog entry or article anywhere about why the Visual Studio 2005 Code Coverage tool doesn't handle C#'s switch statement properly.
I use switch a lot, because it's so much easier to read than lots of if/else ifs, but the fact is any function in my code that contains switch gets marked, after complete and utter unit-testing, as not having been covered 100% -- there's always one block counted as being untested. Yet every line of code in that function is marked nicely in light blue, indicating that it was run. The unit test code makes sure that all cases are covered...
Then when I rewrite the code to use if/else if/... instead of switch, coverage is 100%.
Duh! I want to keep using switch!
Visual Studio 2005 really is a dream environment for any serious .NET Solution Architect or Developer. The built-in designers, the great new CLR and the language extensions, super new controls etc. make designing and developing complex applications less of a hassle. And as you may have derived from some of my previous posts, I also really dig automation of mundane tasks such as daily builds, build verification tests and of course coding and documentation of Data Access Layers, collections and the like. Enter Microsoft's Software Factories initiative.
A Software Factory, basically, is any automated process that generates software; be it code, a model, a spec, whatever. Software factories make the process of designing and building software less error-prone, faster and easier, freeing us up to focus on the interesting bits. And one of the absolutely coolest new things in this area is Microsoft's GAT.
The Guidance Automation Toolkit (GAT)
This toolkit is a freely-downloadable package from Microsoft's Patterns & Practices Group. Currently still in an early CTP version, GAT makes extending Visual Studio 2005 a lot easier than using the traditional means -- i.e., creating Enterprise Templates or writing plugins that talk to EnvDTE and the like. With GAT, architects and senior developers create guidance packages for their teams, for instance to auto-generate code and documentation, to quickly implement common domain-specific design patterns, etc., all according to company or team standards.
Without GAT, such guidance is hard to create. With the current version of GAT, it still isn't super-easy (some XML handcoding is still required) but it's already a big improvement and we can be sure that the RTM version is going to kick some serious butt.
GAT contains a set of tools which are really layers on top of Visual Studio's extensibility mechanisms -- actually, to be really purist, GAT builds on top of the Guidance Automation eXtensions (GAX), which form another layer of abstraction on top of Visual Studio's APIs.
For instance, using GAT it's easy to create wizards which connect to databases and auto-generate Data Access Layer (DAL) code, Business Layer code, database schema documentation, etc. In fact, one of the samples of GAT demonstrated at Tech-Ed this year did just that.
At the core of GAT are concepts such as "recipes", "templates" etc. A recipe is basically a template for a use case. Recipes consist of actions which create, modify or delete "artifacts" (such as code or XML) in Visual Studio. Recipes can be parameterized and the parameters' input can be fetched from the user (using wizards), XML configuration files, databases etc. You can group related recipes and templates in Guidance Packages and distribute them in your team or on the Internet.
Part of the GAT is T3, the templating engine with the cool name which will sadly be renamed T4 by RTM for reasons that are probably better left obscure. The T3 templating engine is similar to CodeSmith and uses a syntax similar to ASP's HTML/code mixing: embedding code between <# ... #> tags in output such as XML, HTML or code.
Resources:
This morning, Scott Hanselman presented his rather interesting talk on Code Generation (ARC305). I have mixed feelings on the subject -- I love the idea of generating chunks of code but I usually loathe the quality of the code. On top of that, often generated code can't be modified or built upon easily. For instance, I love the fact that you can generate typed DataSets using the xsd.exe utility, but the code it produces is really bad and you can't add stuff to it, such as raising an event when a certain property changes -- which is what I like to do. Anyway, back to Scott's presentation.
The basic idea of straight code generation is to build a specification, or call it a domain model if you will, for instance in XML files. You then have these XML files parsed, maybe along with some code templates (think CodeSmith or RapTier again), producing source code or compiled output (as in the case of xsd.exe). The key to making it successful is to shape it to fit your development processes and the domain you're working in. Obviously, if you're building small smartphone apps your code-generation procedure and the output is going to differ from your missile guidance system project. So you can make the input format (the XML schema for the domain models) as simple or as complex as needed, and provide very complex and flexible or very simple input templates.
Of course, you don't have to limit yourself to generating source code. You can generate documentation and unit tests as well, possibly even Word documents (using WordML) or, why not, Excel sheets with statistics?
Personally, I like to work with automated build systems that generate compiled Help files too, by tweaking Visual Studio.NET's project files before compilation (so that XML generation is turned on) and running NDoc on those XML files after compilation. In addition to code-generating tools such as CodeSmith, I also like to use ReSharper's template functions to automatically generate properties that raise xxChanging and xxChanged events, check for null input and the like. That's code generation too, but not the command-line variety that Scott was talking about. Digressing again...
Scott raised an interesting point when he talked about using WSDL as your specification language. Yes, WSDL was originally created for specifying the public APIs of web services -- it stands for Web Service Description Language, after all -- but that doesn't have to keep you back. Why not just use WSDL's syntax to specify entity classes, data access operations etc.? All you have to do is leave out the binding part and the Web Service discovery part of the WSDL, or replace it with something more meaningful to your code generator.
What's also nice about Visual Studio 2005 and .NET 2.0 is the partial classes feature, which fixes, in a sense, the “I can't edit this generated code” problem. To put in code that can't be generated off your model, you can tweak your code generator to output partial classes and then add code in other files that together make up the final class.
Later this week there's a session planned on NHibernate, the .NET version of Java's Hibernate which claims to be able to generate entity classes and business classes off databases and custom models. A couple of Java guys I'm working with use Hibernate and they're experiencing real pains with it. It'll be interesting to see how far NHibernate goes, and if it really is the holy grail that can generate half of any client/server app's code... Stay tuned, more to come on that subject!
<