Archive for the ‘Computers’ Category

Side Effect Free Retrieval Pattern

Comments

A colleague of mine and I were discussing good verb replacements for “GetOrCreate” data retrieval patterns, where the “Create” part is responsible for the instantiation of a new instance of something.  While the pattern I present here did not solve his particular problem, its at least worth sharing.  Its obvious, and probably in use commonly already, but I figure its worth noting.

Essentially the goal is to get away from a “GetOrCreate” master method call and just have two methods: Get(args) and Get(args, Foo default) and then leave the responsibility of default generation up to Foo.  This way there’s no unintended side effects and you don’t have to explicitly coalesce (though with this pattern you could as easily coalesce; strictly speaking it isn’t as “discoverable”)…

var foo = FooService.Get(23) ?? new Foo { ... };

So here’s the pattern defined in code:

public class Foo : ICloneable
{
    private readonly static Foo __default =
        new Foo { Bar = "...", Baz = Int32.MinValue };

    public string Bar { get; set; }
    public int Baz { get; set; }

    public static Foo Default()
    {
        return (Foo)__default.Clone();
    }

    public object Clone()
    {
        return new Foo { Bar = this.Bar, Baz = this.Baz };
    }
}

public class FooService
{
    public Foo Get(int baz)
    {
        // retrieve from data store...
        return null;
    }

    public Foo Get(int baz, Func<Foo> @default)
    {
        return Get(baz) ?? @default.Invoke();
    }
}

You’ll see that any associated overhead with Clone only occurs if Get(baz) returns null.  I have specifically stepped around the common naming standard of “GetDefault()” for the function – its named like a property - because its intended usage is as follows:

var foo = new FooService().Get(12, Foo.Default);


An ICloneable reference type is pretty much required, though any immutable reference type could get by without cloning because any changes gives you a new copy of that type.


Trying out SyntaxHighligher and PreCode

Comments

Just making sure this is correct.  By this I mean PreCode (requires Windows Live Writer 2009) with SyntaxHighligher setup.  PreCode is also a stand alone program.

 

public bool Validate(IValidationDictionary modelState, string prefix)
{
    // xVal example code
    var dataAnnotationErrors = from prop in TypeDescriptor.GetProperties(_entity).Cast<PropertyDescriptor>()
           from attribute in prop.Attributes.OfType<ValidationAttribute>()
           where !attribute.IsValid(prop.GetValue(_entity))
           select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), _entity);

    var brokenRules = GetBrokenRules();

    if (!String.IsNullOrEmpty(prefix))
        prefix += ".";

    if (dataAnnotationErrors.Any())
        dataAnnotationErrors.ForEach(ei => modelState.AddError(prefix + ei.PropertyName, ei.ErrorMessage));
    if (brokenRules.Any())
        brokenRules.ForEach(rule => modelState.AddError(prefix + rule.Property, rule.Message));

    return modelState.IsValid;
}

 

There is a “Fix Indentation” button in PreCode.  I am in love.

Now just to setup the clipboard SWF thing.

I should seriously consider a theme with a wider content area.


Automatic Windows Update Fail and Fix for WHS (Server 2003)

Comments

So I went to stream a movie (DVD) off my Windows Home Server (Windows Server 2003 based) to my Windows Media Center 2005 (XP 32-bit) and encountered CONSTANT stuttering.  The night before I had watched a movie with no problems.  I spent about 5 hours trying to figure out what had happened - both machines had a "Your computer was recently updated!" message from automatic updates.  I knew I was in serious trouble.

I spent a long time trying to troubleshoot codecs (both audio and video) and going through all manner of issues.  I mucked around with the registry on both machines as I narrowed down the problem to horrible, horrible gigabit network performance.  I watched the networking performance through Task Manager on the server and saw my network usage NEVER go above 1%.

Then finally I came across the hotfix from Microsoft to unfuck the hotfix automatic updates kindly installed for me:

http://support.microsoft.com/kb/948496/

Now network utilization hangs out at 25% while copying a 7 GB file across my gigabit network.

And I've learned the lesson I seem to learn every 6 months or so - pretty much every time a new install of Windows or a new PC comes online in my house - disable Automatic Update.  If you don't - you will regret it.

Update: I also had to install a hotfix rollup for Windows Media Center 2005 available from Windows Update and reboot the machine to put my network bandwidth consumption at something over 0.5% which is apparently what I need to play DVDs without stutters... though /sigh there is *still* some stuttering but not nearly as bad as before.

Update[2]: FINALLY.  I ran across this:

http://www.winaims.com/network_patch.html

So on my Windows Media Center machine I fired up regedit again and did:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanworkstation\parameters
Key: ReadAheadGranularity
Type: DWORD
Value: 0

rebooted, and now network utilization seems to stay at a constant 20% when copying a 6 GB file over my network.

Finally I can sleep with a minor feeling of accomplishment.


Web Application csproj => Mvc csproj

Comments

Since you can run classic web forms along side MVC its useful to know how to update your *.csproj project file so Visual Studio shows you the MVC items you can add to your project when you add a new item.  To do this, after installing MVC (and .NET 3.5 SP1 if you haven't yet):

  1. Unload your project through Solution Explorer (right-click, unload)
  2. Edit your *.csproj (yes you can do this in Visual Studio, right click the unloaded project node in Solution Explorer, Edit *.proj)
  3. In the <ProjectTypeGuids /> node add the GUID {603c0e0b-db56-11dc-be95-000d561079b0}; (the semi-colon is important if you prepend it to the exiting list, which is what I did)
  4. Add <MvcBuildViews>false</MvcBuildViews> as a sibling of the <ProjectTypeGuids /> node
  5. Reload the project

Hudson Continuous Integration

Comments

So Java is good for something other than an abstract white coffee cup on an orange background in my system tray after all!

I am working with a friend on an attempt at best practices MVC development using the whole nine yards (DI, TDD, CI, git, SVN).  I had sort of dreaded the part where I had to setup CruiseControl.NET because, well, I hate editing XML files and I hate configuring CC.NET.  Then I stumbled across Chris Allport's blog post on Hudson for .NET Projects.  Hudson is a continuous integration server written in Java and its trivially easy to install, setup, and get running.  On my workstation it took less than 15 minutes to have a working build.  My Windows Home Server (Windows Server 2003) it was a bit more taxing as I had no build environment so I'll detail the steps shortly.

Some of the advantages I see from Hudson, other than very easy to setup and configure:

  • not a lot of hand editing XML files (you could I suppose)
  • plugins - loads and loads - install from the web UI, no manual steps necessary
  • has built in "install as Windows service" option
    • if you do this, do it first for optimal user experience - if you set your hudson directory to something like "c:\hudson" and install as a Windows Service your previous settings will appear to be lost (but they aren't, they are just under the ~\.hudson folder Hudson uses by default)
  • easy to manage security or for the masochistic LDAP integrated security
  • very clean, responsive UI
  • build reports, trends, status
  • RSS feeds for build statuses per project plus email notification
  • integrated textual help on just about everything

Its rare to find a software package that just feels enjoyable to use.  Hudson is one of those software packages.  It absolutely has displaced CC.NET for CI for me.

 

image 

So on my bare Windows Server 2003 I had to install the following things (download links may not work due to session identifiers but you should be able to find everything after a cursory search):

  • Java Runtime Environment 1.6 (1.5+ is required) [download]
  • .NET Framework 3.5 with SP1 [download] (required a reboot)
  • Hudson (latest stable) [download - can go out of date, look for the latest on the Hudson releases page]
    • I placed the hudson.war file in c:\hudson and gave the local system (Network Service) account privileges to this folder
  • Ruby (for Rake, optional if you use NAnt or something else) [download - this link can easily go out of date, you'll want the latest version of Ruby as always]
    • after installation, Command Prompt and cd c:\ruby then gem install rake
  • Windows SDK for Windows Server 2008 and .NET Framework 3.5 [download]
    • Supported platforms: Windows Server 2003, amongst many others - don't let the name fool you!
    • There is an ISO version and web installer - I went for the web installer and paired down the installed components to just the .NET SDK stuff
  • (Optional) ASP.NET MVC if you are compiling an MVC application [download]
  • (Optional) Visual Studio for C# Express [home page]

I also had to copy my workstation's MS Build targets (found, on Vista 64 by default at: C:\Program Files (x86)\MSBuild\Microsoft and ended up on my Windows 2003 Server 32-bit at Program Files\MSBuild\Microsoft [download]

After you're all setup, you can start Hudson by running:

java -jar c:\hudson\hudson.war*

then you can browse to http://localhost:8080 and begin your configuration - but if you're going to install Hudson as a Windows Service make sure to turn that on first so you don't waste time double configuring!  Installing as a service was very easy but I did have to go to Computer Management > Services and manually restart Hudson due to a Java NullPointerException caused when the web UI tried to launch the service manually.  No big deal.

I installed the Rake plugin and the NUnit plugin.  Once doing this I restarted the service (there is a button after plugin installation to do this, and restarting the service from the service hosted HTTP server works fine).

After fiddling around with some settings (specifically email - I created a gmail account and used smtp.gmail.com over SSL for my build server) I moved onto configuring a job.  Some settings I made for my build were:

  • Advanced Project Options > Use custom workspace - I created c:\hudson\workspaces\specialorder and choose that as my custom workspace.  Be foreward: this ended up causing my repository to be placed under c:\hudson\workspaces\specialorder\specialorder since I also set the Source Code Management > Local module directory (optional) value to "specialorder"
  • For building I used rake because, well, its ridiculously easy.  I used the example Rakefile.rb found on Chris Allport's blog "Getting Started with Rake on .NET Projects" as my basis, the resulting Rakefile.rb was placed in my source control repository's trunk\ directory and checked in.
task :default => :build

task :build => [:clean, :compile, :test]

task :clean do
  FileUtils.rm_rf("build") 
  # this doesn't do anything for me yet - have to conf. projects to ".."
end

task :compile do
params = '/t:Rebuild /nologo /v:m /p:Configuration="Debug" src\SiameseHead.SpecialOrder.sln'
msbuid = 'C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe'
sh "#{msbuid} #{params}"
end

task :test do
  # FileUtils.cd 'build\\Debug'
  # exec "..\\..\\tools\\nunit\\nunit-console.exe TestStuffInDotNet.dll"
end

You can see I haven't tried setting up automatic unit testing yet, but I will shortly.

  • For Build > Advanced I specified the full path to the Rakefile.rb (C:\hudson\workspaces\specialorder\specialorder\trunk\Rakefile.rb) and the full path for the Rake working directory (C:\hudson\workspaces\specialorder\specialorder\trunk\); I was getting "invalid path" errors from Rake otherwise

Once you've saved your job you should be able to build it using the "Build Now" link and work your way through any errors (just click on failed builds then look for the "Console Output" link on the left side of the page).