Wednesday 29 September 2010

Bye bye Plaxo, all the best.

I've had a Plaxo account for probably 6 years. Initially Plaxo was innovative and interesting but nothing ground-breaking or useful has come from Plaxo in a long time that isn't already well catered for by the likes of LinkedIn and others. It just fails to keep my attention and is one more stream that has become a boring chore to keep up to date with.
Account deleted.

Tuesday 21 September 2010

Get the md5 hash of an nvarchar in SQL Server 2005

create function [dbo].[GetMd5Hash] (@raw nvarchar(max)) returns uniqueidentifier as
begin
declare @hexstring char(32)
select @hexstring = master.dbo.fn_varbintohexsubstring(0, hashbytes('MD5', @raw), 1, 0)
return CAST(SUBSTRING(@hexstring, 1, 8)
+ '-' + SUBSTRING(@hexstring, 9, 4)
+ '-' + SUBSTRING(@hexstring, 13, 4)
+ '-' + SUBSTRING(@hexstring, 17, 4)
+ '-' + SUBSTRING(@hexstring, 21, 12) as uniqueidentifier)
end

Thursday 2 September 2010

Lets compare tools!

Continuous Integration Tool Comparisons

Version Control

Comparison of version control tools
TFS Subversion Mercurial SourceSafe
Pros Industry standard. Works very well. No learning curve from SS. Works very well, easy learning curve from SS. Faster than TFS. Integrates well with most issue trackers. Very fast. Designed for geographically dispersed teams. Superior branching merging and conflict resolution. None. It is capable of destroying a dev teams best efforts, eats babies and causes cancer.
Cons Bandwidth hungry on each developer commit and when getting latest versions. Can be slow if the connection isn’t great. Merging conflicts can be painful. Merging conflicts is less than optimal. Steeper learning curve for devs who’ve never used it. Some training required. This is bleeding edge. It’s a turd in every way. Microsoft never used it internally for dev work and are still embarassed by its existence.

Issue Tracking

Comparison of issue tracking tools
TFS Bugzilla Jira
Pros Industry standard. Works very well. Integrates by default with VS IDE. Industry standard. Works very well. Works very well. Easy web interface.
Cons The web interface (for testers, BA’s and other non-developers) takes a little while to get used to. The web interface (for everyone) takes a little while to get used to. Commercial product. There is a license cost.

Build, Test and Publish Automation

Comparison of build, test and publish automation tools
TFS CruiseControl.Net TeamCity
Pros Industry standard. Works very well. Industry standard. Works very well. Open Source and free. Easy to configure. Easy to maintain. Uses developer machines to produce builds and can be hosted on a shared server.
Cons Resource hungry. Needs 2 dedicated servers. One for TFS, one for its database. Commercial product. Costs a kings ransom. Configuration is done in XML files and is quite complex. Needs a dedicated (perhaps virtual) server as it does its own builds. Commercial product. Costs $2,000 (USD).

Tuesday 2 February 2010

When random is too consistent...

A while back I posted an extension method for shuffling Lists in C# using the Fisher Yates Shuffle. The algorithm is valid but my implementation relied on the default random number generator in .Net (System.Random) which is flawed since it generates a predictable sort of random.

Here's a correction that uses a more random sort of random from System.Security.Cryptography:
public static void Shuffle<T>(this IList<T> list)
{
var provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
var box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
var k = (box[0] % n);
n--;
var value = list[k];
list[k] = list[n];
list[n] = value;
}
}

Here's a simple test you can run to demonstrate the difference in the algorithms:

using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace AlphabetSoup
{
class Program
{
static void Main()
{
var alphabet = GetAlphabet();
foreach (var c in alphabet)
Console.Write(c);
Console.Write('\n');
Console.Write('\n');

Console.WriteLine("System.Random:");
for (int i = 0; i < 10; i++)
{
alphabet = GetAlphabet();
alphabet.QuickShuffle();
foreach (var c in alphabet)
Console.Write(c);
Console.Write('\n');
}
Console.Write('\n');
Console.Write('\n');

Console.WriteLine("System.Security.Cryptography:");
for (int i = 0; i < 10; i++)
{
alphabet = GetAlphabet();
alphabet.Shuffle();
foreach (var c in alphabet)
Console.Write(c);
Console.Write('\n');
}
Console.Write('\n');
Console.Write('\n');

Console.ReadKey();
}

static List<char> GetAlphabet()
{
var alphabet = new List<char>();
for (int c = 65; c < 91; c++)
alphabet.Add((char)c);
return alphabet;
}
}
static class Ext
{
public static void Shuffle<T>(this IList<T> list)
{
var provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
var box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
var k = (box[0] % n);
n--;
var value = list[k];
list[k] = list[n];
list[n] = value;
}
}
public static void QuickShuffle<T>(this IList<T> list)
{
var rng = new Random();
var n = list.Count;
while (n > 1)
{
n--;
var k = rng.Next(n + 1);
var value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}

Here's the output on my machine: