Archive for the 'Programming' Category

LINQ bites back

Today I found some odd behavior when working with LINQ. It is hard to describe, so here is the code.

public void Foo(IEnumerable<string> strings)
{
	IEnumberable<string> stringsInDb = strings.Where(s => this.QueryTheDbAndTakeALongTime(s));
 
	foreach(string str in stringsInDb)
	{
		//Where clause in LINQ is actually executed 
	}
 
	foreach(string str in stringsInDb)
	{
		//Where clause in LINQ is actually executed  AGAIN
	}
}

Luckily, some unit tests detected this behavior. It actually isn’t surprising when you think about it though. The proper thing to do for this case is actually call ToList() after the Where().

IEnumberable<string> stringsInDb = strings.Where(s => this.QueryTheDbAndTakeALongTime(s)).ToList();

Don’t let this behavior bite you.

Code your Documents

Every developer has heard the phrase document your code. The reason this is important is the functionality is now coupled with a description of how it works. Now a future developer can load up a single source of information and understand the functionality. But, more importantly, the odds of the documentation staying updated are higher because of this coupling. The same can’t be said for a standalone document.

Well, shouldn’t the same be true for documents, specifically those that describe some sort of process? For example, a document describing the steps to setup an IIS web server for a particular application is perfect to convert to an automated script. So, today, I started on a simple script to setup IIS compression using MSBuild.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
  <!-- Types -->
  <PropertyGroup>
    <adsutilPath>C:\inetpub\AdminScripts\adsutil.vbs</adsutilPath>
    <cscriptPath>cscript</cscriptPath>
    <StaticFilesToCompress>html htm js txt</StaticFilesToCompress>
    <DynamicFilesToCompress>aspx asp dll exe axd</DynamicFilesToCompress>
  </PropertyGroup>
 
  <Target Name="IisCompression">
 
    <Message Text="Turn on static and dynamic compression for all of IIS." Importance="high" />
    <!-- http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true -->
    <Exec Command="$(cscriptPath) $(adsutilPath) set w3svc/filters/compression/parameters/HcDoStaticCompression true" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set w3svc/filters/compression/parameters/HcDoDynamicCompression true " />
 
    <Message Text="Select files to compress for static and dyanamic compression." Importance="high" />
    <!-- http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d52ff289-94d3-4085-bc4e-24eb4f312e0e.mspx?mfr=true -->
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/Deflate/HcFileExtensions $(StaticFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/gzip/HcFileExtensions $(StaticFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/Deflate/HcScriptFileExtensions $(DynamicFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/gzip/HcScriptFileExtensions $(DynamicFilesToCompress)"/>
 
  </Target>
</Project>

Not only does this script automate the process, but it serves as a living document for the process. By doing this, the documented process is now coupled to the task itself.

The next step to coding processes is coding tasks that can’t be automated. For example, during a deployment, if some sort of fatal error occurs, the next task might be to call your boss and clean up your resume. Why not code a message in the deploy script to give you the list of people and phone numbers to call in case of an emergency, then load up your resume in Word? Again, the documented process is now coupled with the task itself.

Obviously, this article grows out of my dislike of documentation. I dislike it, not because it isn’t useful, but because it takes a lot of time and, in my personal experience, isn’t used very often. By integrating the documentation with the task itself, I think we gain more value from it.

Book Review: Continuous Integration

Continuous Integration
Continuous Integration is an easy read that anyone directly involved in the software development process could gain a lot from. Even though it doesn’t really introduce anything new, it ties everything most developers have learned over time into a single process, called continuous integration. Here are a few of the things that I really liked about the book.

Automation

Automate everything. Automation limits the ability for bugs to creep into a process and it also makes processes easier to follow. After reading this book, I was really motivated to automate everything and so far it has been a great decision. Some good examples of things that should be automated are:

  • Tests
  • Environment setup and teardown, especially databases
  • Code inspection
  • Deployment

Databases

Very often, databases are not part of a build process or version control. This allows differences between different environments to potentially cause bugs. Putting database schemas and test data in version control can help prevent this. But, what I like the most, is it documents the setup of the database so potentially any developer could setup a new one.

For example, when a new developer starts, I can show him the NAnt or MSBuild task to execute in order to generate a new developer DB. This is much easier than having to guide someone through MySQL, MSSQL, or any other database for the first time.

Transparency

Lastly, the biggest thing I learned from this book is how easily continuous integration can provide project transparency. In my experience, all to often the developers and the rest of an organization get out of touch regarding a project’s status. Continuous integration, combined with more agile development practices, allows a project to be completely transparent throughout an organization, from developers, to QA, to designers, and even senior leadership. No longer does a looming release date bring surprises for those outside the development team.

LINQ’d up

I just used LINQ for the first time ever in code. Pretty exciting. For me, it doesn’t get much better than transforming some mundane 6 liner into an elegant one liner.

This…

int count = 0;
foreach (string email in this.emails)
{
    if (email.EndsWith("@mydomain.com")) count++;
}
return count;

becomes this…

return this.emails.Count(email => email.EndsWith("@mydomain.com"));

In some weird kind of way, I feel like an emo Ruby developer. Maybe I’ll start wearing some tighter clothes.

NUnit and RowTest

I have been researching different unit testing tools for .NET lately. Obviously, NUnit was the first I came across, but MbUnit had the RowTest attribute, which allows parameters to be added to tests. This saves a lot of code and is really a must have feature. Luckily, I found an NUnit addin for RowTest here. The latest version here is linked to NUnit 2.4.6, so I rebuilt it from source to use NUnit 2.4.7.

To install for TestDriven.NET, just create an addins folder in the %install root%\TestDriven.NET 2.0\NUnit\2.4\ and copy NUnitExtension.RowTest.AddIn.dll to the newly created folder. Then in your test project, just reference NUnitExtensino.RowTest and you are set to go.

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace TestExample
{
     [TestFixture]
     public class Tests
     {
          [RowTest]
          [Row(-4,4)]
          [Row(-5,5)]
          [Row(-6,6)]
          public void TestAddEqualsZero(int x, int y)
          {
               Assert.IsTrue((x + y) == 0);
          }
}