Friday, April 29, 2011

Thoughts before Alt .NET Seattle: Part I: TDD

I am going to Alt.Net 2011 Seattle Conference next weekend. Since I am not on the bleeding edge of technology at work, I’m looking into modern methods and technologies.


On my last couple of gigs, when I bring up Test Driven Development, I get a lecture about how it is overly academic and would never work "here" (one place even banned NUnit altogether). Yes, it may take more time to code, but at these places, we spend a lot of time fixing things after the fact.

I agree that it can be taken too far. There are times that it doesn’t make sense to write test before writing trivial code. UI is infamously un-testable. Be pragmatic, it is just as extreme to reject automated testing altogether

I like the way TDD appears to make you think. You know, this function needs to do these 5 things, and what about this edge case, etc. And I have some tests that I can use later, for less effort than if wrote the test later.

I have snuck some tests into the projects that I have more control over. Most of the tests are too large (cover more one thing) and break other TDD rules. Since I can’t get approval to use an IOC container, they are not unit test. Even with these lower quality tests, I have found bugs and have been able to safely re-factor.

Thursday, April 14, 2011

Going to St. Louis

Nine years ago, my sister Susie was run over by a bus and killed. I am going to St. Louis to help my mother plant a tree in her honor.

I both look forward to and dread this trip. After all, it is the place of her death. It is a city that looms large in my mind even though I have never been there. I should have gone years ago and face the demons, now is as good a time as any.

Tuesday, April 12, 2011

Generate Linq To Sql .DBML Fragments

Another user for my post on getting the schema from a Stored Procedure. This time I am generating a Dbml fragment.

In the Column element, I am not providing a DbType. I don’t use Linq to Sql in such a way that it actually uses that value for anything important. I am also assuming that CanBeNull is true.

Yes, this is totally a message for work post. If you need detail as to what I’m doing, check this out.

<#@ assembly name="TsqlDesriptionUtil.dll" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="TsqlDesriptionUtil" #>
<#@ import namespace="System.Collections.Generic" #>
    public class DbmlFunctionFromTSqlCmd : TextTransformation
        public string FunctionName;
        public string FunctionMethod;
        public List<TableDescription> tables;

        public override string TransformText()
#>    <Function Name="<#= FunctionName
                #>" Method="<#= FunctionMethod #>">
<#+ foreach(TableDescription table in tables)
    { #>        <ElementType Name="<#= FunctionMethod #>Result_<#= table.TableName #>">
<#+ foreach(FieldDescription field in table.Fields)
   { #>             <Column Name="<#= field.FieldName #>" 
                      Type="<#= field.FieldType.FullName  #>" 
                      CanBeNull="true" />
<#+ } #>
<#+ } #>
        return this.GenerationEnvironment.ToString();
} #>

Again, for Demonstration purposes I wrote a simple T4 Template that includes the template above and uses the library I wrote in this post to get a description of the data.

<#@ template language="C#v3.5" debug="true" 
#><#@ output extension="txt" 
#><#@ include file="" 
#><#@ assembly name="TsqlDesriptionUtil.dll" 
#><#@ import namespace="TsqlDesriptionUtil" 
    // Since I'm generating XML, I will go to extreme measures to avoid new 
    // line characters like the strange formatting of declarations above ^
    // Get the table descriptions for given T-SQL
    string conString = @"Data Source=localhost;" +
      @"Initial Catalog=Northwind;Integrated Security=True";
    string commandString = "EXEC  CustOrderHist @CustomerID='ALFKI'";
    List<TableDescription> tables = 
      TsqlCommandSchema.GetFieldDescription(conString, commandString);
    // Generate DBML Fragment:
    var gen = new DbmlFunctionFromTSqlCmd();
    gen.FunctionName = "dbo.GetBigTableDataUseTempTab";
    gen.FunctionMethod = "MyNew";
    gen.tables = tables;

(If I were more of a studman programmer dude, I'd write a Visual Studio Add-in that would insert this fragment directly into my .dbml file.)