<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>Alan Dean</title><description></description><managingEditor>noreply@blogger.com (Alan Dean)</managingEditor><pubDate>Mon, 24 Mar 2025 19:45:03 -0700</pubDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">71</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage><link>http://alandean.blogspot.com/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><copyright>Creative Commons Attribution 2.5 License</copyright><itunes:image href="http://farm4.static.flickr.com/3271/2958710613_dfdd4a4878_o.jpg"/><itunes:summary>I am a UK-based professional software developer. I am also active in the development user community.</itunes:summary><itunes:subtitle>Audio and Video blogging from Alan Dean</itunes:subtitle><itunes:category text="Technology"/><itunes:author>Alan Dean</itunes:author><itunes:owner><itunes:email>alan.dean@gmail.com</itunes:email><itunes:name>Alan Dean</itunes:name></itunes:owner><item><title>A Definition of Done is ...</title><link>http://alandean.blogspot.com/2011/11/definition-of-done-is.html</link><category>Agile</category><pubDate>Thu, 17 Nov 2011 00:14:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-7776991656687834167</guid><description>&lt;p&gt;Those who work with me know that the Definition of Done is something which I consider to be vital to effective software development. For me the subtitle of any Definition of Done should be along the lines of:&lt;/p&gt;
&lt;blockquote&gt;As a professional, when I say that my work is &lt;strong&gt;Done&lt;/strong&gt;, it means that I genuinely believe that I have no further work to do and that I have myself verified that the work is of necessary quality and completeness as well as having the work appropriately checked by others. I will honestly be surprised if my work is defective in some manner when I say it is done. Please take a look at the list below of the characteristics that I consider to be important to my work:&lt;/blockquote&gt;
&lt;p&gt;After this subtitle, there is the list that most &lt;a href="http://www.google.co.uk/search?q=definition+of+done&amp;prmd=imvns&amp;tbm=isch"&gt;Agile practitioners are familiar with&lt;/a&gt;.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Unit test naming convention</title><link>http://alandean.blogspot.com/2011/11/unit-test-naming-convention.html</link><category>TDD</category><pubDate>Sat, 12 Nov 2011 22:47:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-5178442525605672015</guid><description>&lt;p&gt;I have been using &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development" rel="nofollow"&gt;TDD&lt;/a&gt; since before it was even called that. The practice was called &lt;em&gt;test-first&lt;/em&gt; at the time and I learnt to do it with &lt;a href="http://comunit.sourceforge.net/" rel="nofollow"&gt;ComUnit&lt;/a&gt; against VB6 code. I suspect that there aren't many people who can put down more than a decade of of TDD on their CV. Probably due to this, I employ somewhat idiosyncratic practices, such as a distinct interface focus (both the default interface and those additionally implemented). Accordingly, I have a fairly well elaborated naming convention for my unit tests in order to make test scenario coverage more rigorous and visible.&lt;/p&gt;
&lt;p&gt;The overall convention is &lt;code&gt;public void memberKind_parameterType_parameterType_whenScenarioInfo()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Member Kinds (when default or implicit interface implementation)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Constructors: &lt;code&gt;ctor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Properties: &lt;code&gt;prop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Indexers: &lt;code&gt;index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Methods: &lt;code&gt;op&lt;/code&gt;, &lt;code&gt;opImplicit&lt;/code&gt;, &lt;code&gt;opExplicit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Generic Methods: &lt;code&gt;op_MethodNameOfT&lt;/code&gt;, &lt;code&gt;op_MethodNameOfClass&lt;/code&gt;, &lt;code&gt;op_MethodNameOfNew&lt;/code&gt;, &lt;code&gt;op_MethodNameOfIInterfaceName&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Member Kinds (when explicit interface implementation)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Properties: &lt;code&gt;IInterfaceName_prop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Indexers: &lt;code&gt;IInterfaceName_index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Methods: &lt;code&gt;IInterfaceName_op&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Names&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Type definition assertions: &lt;code&gt;a_definition&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Assert deserialization: &lt;code&gt;xmlDeserialize&lt;/code&gt;, &lt;code&gt;jsonDeserialize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Assert serialization: &lt;code&gt;xmlSerialize&lt;/code&gt;, &lt;code&gt;jsonSerialize&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameter Types&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Keywords: &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Null types: &lt;code&gt;stringNull&lt;/code&gt;, &lt;code&gt;TypeNameNull&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Empty string: &lt;code&gt;stringEmpty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Invalid string: &lt;code&gt;stringInvalid&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Specific values: &lt;code&gt;longZero&lt;/code&gt;, &lt;code&gt;intOne&lt;/code&gt;, &lt;code&gt;decimalNegative&lt;/code&gt;, &lt;code&gt;floatEpsilon&lt;/code&gt;, &lt;code&gt;shortMin&lt;/code&gt;, &lt;code&gt;DateTimeNow&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When&lt;/strong&gt;&lt;br/&gt;
Used to disambiguate two or more tests which otherwise have the same name, e.g. &lt;code&gt;op_ToString_whenDefault()&lt;/code&gt;, &lt;code&gt;op_ToString_whenDescriptionIsNull()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br/&gt;
Cavity has almost complete test coverage so there are plenty of examples. Here are some:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/cavity/source/browse/trunk/src/Cavity%20Core/Class%20Libraries/Core.Facts/AlphaDecimal.Facts.cs"&gt;AlphaDecimal.Facts.cs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/cavity/source/browse/trunk/src/Cavity%20Core/Class%20Libraries/Core.Facts/CommentAttribute.Facts.cs"&gt;CommentAttribute.Facts.cs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/cavity/source/browse/trunk/src/Cavity%20Core/Class%20Libraries/Core.Facts/DateTime.ExtensionMethods.Facts.cs"&gt;DateTime.ExtensionMethods.Facts.cs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;h4&gt;Update&lt;/h4&gt;
&lt;p&gt;So obvious that I forgot to mention it, but worth putting on the record: each class should have exactly one test class, i.e. &lt;code&gt;Example.cs&lt;/code&gt; has &lt;code&gt;Example.Facts.cs&lt;/code&gt; (if xUnit) or &lt;code&gt;Example.Tests.cs&lt;/code&gt; (if NUnit, MSTest, etc.). The period in Example.Facts or Example.Tests is to force the same sort order of units and tests in the Visual Studio solution explorer tree view. I use a pair of templates to assist me (installer available in &lt;a href="http://code.google.com/p/cavity/downloads/list"&gt;downloads&lt;/a&gt;).&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Not-so-simple NuGet Packaging</title><link>http://alandean.blogspot.com/2011/10/not-so-simple-nuget-packaging.html</link><category>nuget</category><pubDate>Wed, 12 Oct 2011 07:02:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-4573538237021199566</guid><description>&lt;p&gt;Moving beyond the &lt;a href="http://alandean.blogspot.com/2011/10/simple-nuget-packaging.html"&gt;simple case&lt;/a&gt;, here is what I did to &lt;a href="http://nuget.org/List/Packages/Cavity.Diagnostics.Log4Net"&gt;package the Cavity log4net trace listener&lt;/a&gt; which I'm sharing because I encountered some frustration points.&lt;/p&gt;
&lt;p&gt;First, the &lt;code&gt;.nuspec&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;package xmlns=&amp;quot;http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd&amp;quot;&amp;gt;
  &amp;lt;metadata&amp;gt;
    &amp;lt;id&amp;gt;Cavity.Diagnostics.Log4Net&amp;lt;/id&amp;gt;
    &amp;lt;version&amp;gt;1.1.0.444&amp;lt;/version&amp;gt;
    &amp;lt;title&amp;gt;Cavity log4net trace listener&amp;lt;/title&amp;gt;
    &amp;lt;authors&amp;gt;Alan Dean&amp;lt;/authors&amp;gt;
    &amp;lt;owners /&amp;gt;
    &amp;lt;licenseUrl&amp;gt;http://www.opensource.org/licenses/mit-license.php&amp;lt;/licenseUrl&amp;gt;
    &amp;lt;projectUrl&amp;gt;http://code.google.com/p/cavity/&amp;lt;/projectUrl&amp;gt;
    &amp;lt;iconUrl&amp;gt;http://www.alan-dean.com/nuget.png&amp;lt;/iconUrl&amp;gt;
    &amp;lt;requireLicenseAcceptance&amp;gt;false&amp;lt;/requireLicenseAcceptance&amp;gt;
    &amp;lt;description&amp;gt;A trace listener for log4net, allowing provider-agnostic tracing.&amp;lt;/description&amp;gt;
    &amp;lt;summary /&amp;gt;
    &amp;lt;copyright&amp;gt;Copyright © 2010 - 2011 Alan Dean&amp;lt;/copyright&amp;gt;
    &amp;lt;language /&amp;gt;
    &amp;lt;tags&amp;gt;Diagnostics&amp;lt;/tags&amp;gt;
    &amp;lt;releaseNotes&amp;gt;Switched off license acceptance dialog.&amp;lt;/releaseNotes&amp;gt;
    &amp;lt;dependencies&amp;gt;
      &amp;lt;dependency id=&amp;quot;log4net&amp;quot; version=&amp;quot;1.2.10&amp;quot; /&amp;gt;
    &amp;lt;/dependencies&amp;gt;
  &amp;lt;/metadata&amp;gt;
  &amp;lt;files&amp;gt;
    &amp;lt;file src=&amp;quot;content\app.config.transform&amp;quot; target=&amp;quot;content\app.config.transform&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;content\log4net.config.transform&amp;quot; target=&amp;quot;content\log4net.config.transform&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;content\web.config.transform&amp;quot; target=&amp;quot;content\web.config.transform&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;content\Properties\log4net.cs&amp;quot; target=&amp;quot;content\Properties\log4net.cs&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;lib\net35\Cavity.Diagnostics.Log4Net.dll&amp;quot; target=&amp;quot;lib\net35\Cavity.Diagnostics.Log4Net.dll&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;lib\net40\Cavity.Diagnostics.Log4Net.dll&amp;quot; target=&amp;quot;lib\net40\Cavity.Diagnostics.Log4Net.dll&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;tools\Install.ps1&amp;quot; target=&amp;quot;tools\Install.ps1&amp;quot; /&amp;gt;
  &amp;lt;/files&amp;gt;
&amp;lt;/package&amp;gt;&lt;/pre&gt;
&lt;p&gt;Right off the bat. you can see that more is going on here. The trace listener is dependent on &lt;a href="http://nuget.org/List/Packages/log4net"&gt;log4net&lt;/a&gt; and I also have a bunch of content in additional to my two assemblies.&lt;/p&gt;
&lt;p&gt;The target project will need to have either its' &lt;code&gt;app.config&lt;/code&gt; or &lt;code&gt;web.config&lt;/code&gt; extended so there is a &lt;a href="http://docs.nuget.org/docs/creating-packages/configuration-file-and-source-code-transformations"&gt;transform&lt;/a&gt; for each. The target will need an assembly attribute applied, so I took the simple expedient of dropping &lt;code&gt;log4net.cs&lt;/code&gt; into Properties alongside &lt;code&gt;AssemblyInfo.cs&lt;/code&gt;. However, log4net also requires XmlConfigurator.Configure() to be called. This call needs to be in either &lt;code&gt;Main()&lt;/code&gt; or &lt;code&gt;Application_Start()&lt;/code&gt; and therefore existing code needs to be edited (rather than a new code file dropped in). To accomplish this, we have to use &lt;a href="http://msdn.microsoft.com/library/envdte" rel="nofollow"&gt;EnvDTE&lt;/a&gt;, as exposed in the &lt;code&gt;Install.ps1&lt;/code&gt; PowerShell script (I also mark the &lt;code&gt;log4net.config&lt;/code&gt; file to copy to output during build):&lt;/p&gt;
&lt;pre class="brush: powershell"&gt;param($installPath, $toolsPath, $package, $project)

$project.ProjectItems.Item("log4net.config").Properties.Item("CopyToOutputDirectory").Value = 1

try
{
  $item = $project.ProjectItems.Item("Program.cs")
}
catch [System.Management.Automation.MethodInvocationException]
{
}

if (!$item)
{
  $item = $project.ProjectItems.Item("global.asax").ProjectItems.Item("global.asax.cs")
}

$terminator = ""
if ($item.FileCodeModel.Language -eq "{B5E9BD34-6D3E-4B5D-925E-8A43B79820B4}")
{
  $terminator = ";"
}

$win = $item.Open("{7651A701-06E5-11D1-8EBD-00A0C90F26EA}")
$text = $win.Document.Object("TextDocument");
$namespace = $item.FileCodeModel.CodeElements | where-object {$_.Kind -eq 5}
$class = $namespace.Children | where-object {$_.Kind -eq 1}

$methods = $class.Children | where-object {$_.Name -eq "Main"}
if (!$methods)
{
  $methods = $class.Children | where-object {$_.Name -eq "Application_Start"}
  if (!$methods)
  {
    [system.windows.forms.messagebox]::show("methods is null")
  }
}

$edit = $methods.StartPoint.CreateEditPoint();
$edit.LineDown()
$edit.CharRight(1)
$edit.Insert([Environment]::NewLine)
$edit.Insert(" log4net.Config.XmlConfigurator.Configure()")
$edit.Insert($terminator)&lt;/pre&gt;
&lt;p&gt;I have to say that the PowerShell + EnvDTE experience was rather less than enjoyable but I got the basics of what I needed to work.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Simple NuGet Packaging</title><link>http://alandean.blogspot.com/2011/10/simple-nuget-packaging.html</link><category>nuget</category><pubDate>Wed, 12 Oct 2011 05:59:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-4427579366849333269</guid><description>&lt;p&gt;Over the last week I have started publishing my &lt;a href="http://code.google.com/p/cavity/"&gt;Cavity&lt;/a&gt; libraries on to &lt;a href="http://nuget.org/"&gt;NuGet&lt;/a&gt;, starting with my &lt;a href="http://code.google.com/p/cavity/wiki/CavityTestingUnit"&gt;Unit Testing Fluent API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The API is implemented in a single assembly with no non-BCL dependencies, which makes it the simplest case to &lt;a href="http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package"&gt;pack for NuGet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is the &lt;code&gt;.nuspec&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;package xmlns=&amp;quot;http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd&amp;quot;&amp;gt;
  &amp;lt;metadata&amp;gt;
    &amp;lt;id&amp;gt;Cavity.Testing.Unit&amp;lt;/id&amp;gt;
    &amp;lt;version&amp;gt;1.1.0.444&amp;lt;/version&amp;gt;
    &amp;lt;title&amp;gt;Cavity Unit Testing&amp;lt;/title&amp;gt;
    &amp;lt;authors&amp;gt;Alan Dean&amp;lt;/authors&amp;gt;
    &amp;lt;owners /&amp;gt;
    &amp;lt;licenseUrl&amp;gt;http://www.opensource.org/licenses/mit-license.php&amp;lt;/licenseUrl&amp;gt;
    &amp;lt;projectUrl&amp;gt;http://code.google.com/p/cavity/&amp;lt;/projectUrl&amp;gt;
    &amp;lt;iconUrl&amp;gt;http://www.alan-dean.com/nuget.png&amp;lt;/iconUrl&amp;gt;
    &amp;lt;requireLicenseAcceptance&amp;gt;false&amp;lt;/requireLicenseAcceptance&amp;gt;
    &amp;lt;description&amp;gt;Fluent API for asserting types and properties.&amp;lt;/description&amp;gt;
    &amp;lt;summary /&amp;gt;
    &amp;lt;copyright&amp;gt;Copyright © 2010 - 2011 Alan Dean&amp;lt;/copyright&amp;gt;
    &amp;lt;language /&amp;gt;
    &amp;lt;tags&amp;gt;TDD&amp;lt;/tags&amp;gt;
    &amp;lt;releaseNotes&amp;gt;Switched off license acceptance dialog.&amp;lt;/releaseNotes&amp;gt;
  &amp;lt;/metadata&amp;gt;
  &amp;lt;files&amp;gt;
    &amp;lt;file src=&amp;quot;lib\net35\Cavity.Testing.Unit.dll&amp;quot; target=&amp;quot;lib\net35\Cavity.Testing.Unit.dll&amp;quot; /&amp;gt;
    &amp;lt;file src=&amp;quot;lib\net40\Cavity.Testing.Unit.dll&amp;quot; target=&amp;quot;lib\net40\Cavity.Testing.Unit.dll&amp;quot; /&amp;gt;
  &amp;lt;/files&amp;gt;
&amp;lt;/package&amp;gt;&lt;/pre&gt;
&lt;p&gt;I have implemented framework targeting in my build process, so in this case I have two assemblies (.NET 3.5 and .NET 4.0) which I have copied into the lib subdirectory.&lt;/p&gt;
&lt;p&gt;For a simple package like this, that is all you need to configure; just &lt;a href="http://nuget.org/List/Packages/Cavity.Testing.Unit"&gt;pack and push&lt;/a&gt;.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>How to conditionally skip compilation</title><link>http://alandean.blogspot.com/2011/02/how-to-conditionally-skip-compilation.html</link><category>Build</category><pubDate>Sun, 20 Feb 2011 12:20:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-1682181826894397967</guid><description>&lt;p&gt;As I mentioned in my last post, I was having problems getting an MVC web application to play nice with my framework targeting builds. Specifically, my CI server would fall over if I tried to build using Framework 3.5 when the web application was using 4.0 (due to 4.0-specific web.config settings that 3.5 does not recognise). I managed to spend a large portion of the afternoon searching for an answer until I had one of those “eureka” moments. My objective was to simply not build the web application unless the framework was 4.0 (the same would apply to any project that is framework version-specific). I tried putting a conditional on the project element. No Joy. I tried a whole bunch of other things and it was starting to look like I would have to manually configure each project to be built – very nasty, not at all what I want.&lt;/p&gt;&lt;p&gt;My “eureka” moment happened as I was gazing forlornly at a project file. My eye alighted upon an attribute of &lt;code&gt;DefaultTargets=&amp;quot;Build&amp;quot;&lt;/code&gt; on the project element. Build? I thought… I’ve not seen a target called that. A quick check confirmed my suspicion. The “Build” target is effectively inherited. In a flash I thought I wonder if I can intercept this? I changed the attribute to &lt;code&gt;DefaultTargets=&amp;quot;Conditional&amp;quot;&lt;/code&gt; and then added the following target and all is well again in Narnia:&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;Target Name=&amp;quot;Conditional&amp;quot;&amp;gt;
&amp;lt;CallTarget Targets=&amp;quot;Build&amp;quot; Condition=&amp;quot; '$(TargetFrameworkVersion)' == 'v4.0' &amp;quot; /&amp;gt;
&amp;lt;/Target&amp;gt;&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Framework version targeting with MSBUILD</title><link>http://alandean.blogspot.com/2011/02/framework-version-targeting-with.html</link><category>Build</category><pubDate>Sun, 20 Feb 2011 07:17:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-3662791983780300600</guid><description>&lt;p&gt;I faced a question this weekend: how best should I support conditional compilation by framework? The proximate reason for asking this was a need to use &lt;a title="BigInteger Structure" href="http://msdn.microsoft.com/library/system.numerics.biginteger" rel="nofollow"&gt;BigInteger&lt;/a&gt; in the &lt;a title="Cavity Project" href="http://code.google.com/p/cavity/"&gt;Cavity&lt;/a&gt; project in order to be able to support 128-bit base-36 notation with a minimum of fuss. This is a new value type in Framework 4.0 and up until now Framework 3.5 have been the target for Cavity assemblies. As 3.5 is going to be around for a good while yet (heck, there is still plenty of 2.0 in production today) I didn’t want to orphan support for that version. I also didn’t want to add complexity to my build or maintenance activities. This ruled out brute force options such as creating a branch for 3.5 or creating a new solution and project files for one or other of the framework versions.&lt;/p&gt;&lt;p&gt;A search yielded a varied collection of advice. Some was plainly potty but a couple of StackOverflow answers &lt;sup&gt;[&lt;a title="C# Conditional Compilation and framework targets" href="http://stackoverflow.com/questions/2923210/c-conditional-compilation-and-framework-targets" rel="nofollow"&gt;1&lt;/a&gt;] [&lt;a title="Target specific version of .NET framework at Visual Studio 2010 Solution level" href="http://stackoverflow.com/questions/4426524/target-specific-version-of-net-framework-at-visual-studio-2010-solution-level" rel="nofollow"&gt;2&lt;/a&gt;]&lt;/sup&gt; looked promising. Taking the answers and combining a bit of common sense, I put together a &lt;a title="Build Targeting" href="http://code.google.com/p/alan-dean/source/browse/#svn%2Ftrunk%2Fsrc%2FBuild%20Targeting"&gt;quick spike&lt;/a&gt; to verify that I had the gist of it. Here is what I learnt:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The best way to control targeting is to use property parameters with a build file. Here is a .bat file to build release versions targeting each major framework version:      &lt;br /&gt;
&lt;pre class="brush: text"&gt;MSBUILD build.xml /p:Configuration=Release /p:TargetFrameworkVersion=v2.0
MSBUILD build.xml /p:Configuration=Release /p:TargetFrameworkVersion=v3.5
MSBUILD build.xml /p:Configuration=Release /p:TargetFrameworkVersion=v4.0&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;You don’t need to do anything in the build.xml or the .sln file for this to work. You do, however, need to do a little work in the .csproj files: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;First, you need to decide which framework version you want to work with in Visual Studio (typically, this will be the latest version) and configure &lt;em&gt;TargetFrameworkVersion&lt;/em&gt; accordingly: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;TargetFrameworkVersion Condition=&amp;quot; '$(TargetFrameworkVersion)' == '' &amp;quot;&amp;gt;v4.0&amp;lt;/TargetFrameworkVersion&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;To make the build output obvious, set the &lt;em&gt;OutputPath&lt;/em&gt; to use properties: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;OutputPath&amp;gt;bin\$(Configuration) $(TargetFrameworkVersion)\&amp;lt;/OutputPath&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Next, you should set up some conditional property groups: &lt;br /&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;PropertyGroup Condition=&amp;quot; '$(TargetFrameworkVersion)' == 'v2.0' &amp;quot;&amp;gt;
    &amp;lt;DefineConstants&amp;gt;NET20&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;TargetFrameworkVersionNumber&amp;gt;2.0&amp;lt;/TargetFrameworkVersionNumber&amp;gt;
&amp;lt;/PropertyGroup&amp;gt;
&amp;lt;PropertyGroup Condition=&amp;quot; '$(TargetFrameworkVersion)' == 'v3.5' &amp;quot;&amp;gt;
    &amp;lt;DefineConstants&amp;gt;NET35&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;TargetFrameworkVersionNumber&amp;gt;3.5&amp;lt;/TargetFrameworkVersionNumber&amp;gt;
&amp;lt;/PropertyGroup&amp;gt;
&amp;lt;PropertyGroup Condition=&amp;quot; '$(TargetFrameworkVersion)' == 'v4.0' &amp;quot;&amp;gt;
    &amp;lt;DefineConstants&amp;gt;NET40&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;TargetFrameworkVersionNumber&amp;gt;4.0&amp;lt;/TargetFrameworkVersionNumber&amp;gt;
&amp;lt;/PropertyGroup&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;This allows you to configure framework-specific assembly references, such as &lt;em&gt;System.Core&lt;/em&gt; and &lt;em&gt;Microsoft.CSharp&lt;/em&gt;: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;Reference Include=&amp;quot;System.Core&amp;quot; Condition=&amp;quot; '$(TargetFrameworkVersionNumber)' &amp;gt;= '3.5' &amp;quot; /&amp;gt;
&amp;lt;Reference Include=&amp;quot;Microsoft.CSharp&amp;quot; Condition=&amp;quot; '$(TargetFrameworkVersionNumber)' &amp;gt;= '4.0' &amp;quot; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;You should now be able to target framework versions in a straightforward manner by running the batch file above. &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;If you want to conditionally include classes, simply apply a framework condition: &lt;br /&gt;
&lt;pre class="brush: xml"&gt;&amp;lt;Compile Include=&amp;quot;Class20.cs&amp;quot; Condition=&amp;quot; '$(TargetFrameworkVersion)' == 'v2.0' &amp;quot; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;I also defined constants above to allow conditional compilation at code level: &lt;br /&gt;
&lt;pre class="brush: csharp"&gt;namespace Example
{
    public sealed class Class1
    {
#if NET20
        public void Net20()
        {
        }
#endif

#if NET35
        public void Net35()
        {
        }
#endif

#if NET40
        public void Net40()
        {
        }
#endif
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;The only pain I have really encountered so far is getting MVC web applications to play nicely.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Object Pool Pattern</title><link>http://alandean.blogspot.com/2010/06/object-pool-pattern.html</link><category>Pattern</category><pubDate>Tue, 29 Jun 2010 09:41:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-3960066326324273774</guid><description>&lt;p&gt;In the last post I discussed the &lt;a title="Multiton Pattern" href="http://alandean.blogspot.com/2010/06/multiton-pattern.html" rel="bookmark"&gt;Multiton&lt;/a&gt; pattern and this post continues the theme of non-&lt;acronym title="Gang of Four"&gt;GoF&lt;/acronym&gt; patterns by looking at &lt;a title="Object pool pattern" href="http://wikipedia.org/wiki/Object_pool_pattern" rel="nofollow"&gt;Object Pool&lt;/a&gt;, another specialised &lt;a title="Singleton pattern" href="http://wikipedia.org/wiki/Singleton_pattern" rel="nofollow"&gt;Singleton&lt;/a&gt;. The purpose of this pattern is to re-use object instances to avoid creation / destruction. My mnemonic this time is a &lt;a title="Carpool" href="http://wikipedia.org/wiki/Carpool" rel="nofollow"&gt;Car Pool&lt;/a&gt; which is just a collection of cars for my purposes:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public sealed class Car
{
    public Car(string registration)
    {
        this.Registration = registration;
    }

    public string Registration
    {
        get;
        set;
    }

    public override string ToString()
    {
        return this.Registration;
    }
}&lt;/pre&gt;&lt;p&gt;The pool implementation also uses &lt;a title="WeakReference Class (.NET Framework Class Library)" href="http://msdn.microsoft.com/library/system.weakreference" rel="nofollow"&gt;weak references&lt;/a&gt; to handle garbage collected cars which have not been explicitly returned to the pool:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;
using System.Collections.Generic;
using System.Linq;

public sealed class CarPool
{
    private static CarPool _pool = new CarPool();

    private CarPool()
    {
        this.Cars = new Dictionary&amp;lt;Car, WeakReference&amp;gt;();
    }

    public static int Availability
    {
        get
        {
            int value = 0;

            lock (_pool)
            {
                value = _pool.Cars.Where(x =&amp;gt; null == x.Value || !x.Value.IsAlive).Count();
            }

            return value;
        }
    }

    private Dictionary&amp;lt;Car, WeakReference&amp;gt; Cars
    {
        get;
        set;
    }

    public static void Add(params Car[] cars)
    {
        foreach (var car in cars)
        {
            lock (_pool)
            {
                _pool.Add(car);
            }
        }
    }

    public static Car Get()
    {
        Car result = null;

        if (0 &amp;lt; CarPool.Availability)
        {
            lock (_pool)
            {
                var item = _pool.Cars.Where(x =&amp;gt; null == x.Value || !x.Value.IsAlive).FirstOrDefault();

                var value = new WeakReference(item.Key);
                _pool.Cars[item.Key] = value;

                result = (Car)value.Target;
            }
        }

        return result;
    }

    public static void Return(Car car)
    {
        if (null == car)
        {
            throw new ArgumentNullException(&amp;quot;car&amp;quot;);
        }

        lock (_pool)
        {
            _pool.Cars[car] = null;
        }
    }

    private void Add(Car car)
    {
        this.Cars.Add(car, new WeakReference(null));
    }
}&lt;/pre&gt;&lt;p&gt;Here is a test which verifies the expected behaviour:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using Xunit;

public sealed class ObjectPoolFacts
{
    [Fact]
    public void car_pooling()
    {
        Car one = new Car(&amp;quot;ABC 111&amp;quot;);
        Car two = new Car(&amp;quot;ABC 222&amp;quot;);
        CarPool.Add(one, two);

        Car first = CarPool.Get();
        Assert.Same(one, first);

        Car second = CarPool.Get();
        Assert.Same(two, second);

        Assert.Null(CarPool.Get());

        CarPool.Return(first);
        CarPool.Return(second);

        second = CarPool.Get();
        Assert.Same(one, second);
    }
}&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Multiton Pattern</title><link>http://alandean.blogspot.com/2010/06/multiton-pattern.html</link><category>Pattern</category><category>TDD</category><pubDate>Tue, 29 Jun 2010 07:18:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-6158497139027523216</guid><description>&lt;p&gt;I’m doing a little ‘brushing up on the basics’ at the moment and as part of that effort I am working up some pattern examples, starting with &lt;a title="Creational pattern" href="http://wikipedia.org/wiki/Creational_pattern" rel="nofollow"&gt;creational patterns&lt;/a&gt;. These include staples such as &lt;a title="Factory method pattern" href="http://wikipedia.org/wiki/Factory_method_pattern" rel="nofollow"&gt;Factory Method&lt;/a&gt;, &lt;a title="Abstract factory pattern" href="http://wikipedia.org/wiki/Abstract_factory_pattern" rel="nofollow"&gt;Abstract Factory&lt;/a&gt;, &lt;a title="Prototype pattern" href="http://wikipedia.org/wiki/Prototype_pattern" rel="nofollow"&gt;Prototype&lt;/a&gt;, &lt;a title="Singleton pattern" href="http://wikipedia.org/wiki/Singleton_pattern" rel="nofollow"&gt;Singleton&lt;/a&gt; and so on but there are other creational patterns which weren’t in the Gang of Four (&lt;acronym title="Gang of Four"&gt;GoF&lt;/acronym&gt;) &lt;a title="Design Patterns" href="http://wikipedia.org/wiki/Design_Patterns_(book)" rel="nofollow"&gt;Design Patterns&lt;/a&gt; book. One of these is the &lt;a title="Multiton pattern" href="http://wikipedia.org/wiki/Multiton_pattern" rel="nofollow"&gt;Multiton&lt;/a&gt;. I don’t know what it’s provenance is, but it is an extension to the Singleton pattern which provides centralised access to a single collection making keys unique within scope. In my example, the singleton is declared as a &lt;code&gt;static&lt;/code&gt; member so it has &lt;a title="Application Domains (.NET Framework Developer&amp;#39;s Guide)" href="http://msdn.microsoft.com/library/cxk374d9" rel="nofollow"&gt;application domain&lt;/a&gt; scope.&lt;/p&gt;&lt;p&gt;I like to work up examples that feel (at least somewhat) real-world as I find that these are easier to remember later on. For the Multiton pattern I decided to use the &lt;a title="Rolodex" href="http://wikipedia.org/wiki/Rolodex" rel="nofollow"&gt;Rolodex&lt;/a&gt; which is simply a collection of cards for my purposes:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public sealed class Card
{
    internal Card(string key)
    {
        this.Key = key;
    }

    public string Information
    {
        get;
        set;
    }

    public string Key
    {
        get;
        set;
    }
}&lt;/pre&gt;&lt;p&gt;The pattern defines that item creation is handled by a static factory if the key does not exist in the collection:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;
using System.Collections.ObjectModel;
using System.Linq;

public sealed class Rolodex
{
    private static Rolodex _rolodex = new Rolodex();

    private Rolodex()
    {
        this.Cards = new Collection&amp;lt;Card&amp;gt;();
    }

    private Collection&amp;lt;Card&amp;gt; Cards
    {
        get;
        set;
    }

    public static Card Open(string key)
    {
        Card result = null;

        lock (_rolodex)
        {
            result = _rolodex.Cards
                .Where(x =&amp;gt; string.Equals(x.Key, key, StringComparison.Ordinal))
                .FirstOrDefault();

            if (null == result)
            {
                result = new Card(key);
                _rolodex.Cards.Add(result);
            }
        }

        return result;
    }
}&lt;/pre&gt;&lt;p&gt;Here is a test which verifies the expected behaviour:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;Xunit;

public sealed class MultitonFacts
{
    [Fact]
    public void rolodex_card()
    {
        string key = &amp;quot;John Doe&amp;quot;;

        Card expected = Rolodex.Open(key);
        expected.Information = &amp;quot;john.doe@example.com&amp;quot;;

        Card actual = Rolodex.Open(key);

        Assert.Same(expected, actual);
    }
}&lt;/pre&gt;&lt;p&gt;It’s worth pointing out that, as with all Singleton patterns, the plain vanilla pattern doesn’t lend itself to unit testing as-is. The answer is to provide a wrapper for mocking purposes. Here is an example of doing so for &lt;a title="DateTime.UtcNow Property" href="http://msdn.microsoft.com/library/system.datetime.utcnow" rel="nofollow"&gt;DateTime.UtcNow&lt;/a&gt;:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;

public static class DateTimeFactory
{
    [ThreadStatic]
    private static DateTime? _mock;

    public static DateTime Today
    {
        get
        {
            DateTime value = DateTime.Today;

            if (null != _mock)
            {
                value = _mock.Value.Date;
            }

            return value;
        }
    }

    public static DateTime UtcNow
    {
        get
        {
            DateTime value = DateTime.UtcNow;

            if (null != _mock)
            {
                value = _mock.Value;
            }

            return value;
        }
    }

    public static DateTime? Mock
    {
        get
        {
            return _mock;
        }

        set
        {
            _mock = value;
        }
    }

    public static void Reset()
    {
        DateTimeFactory.Mock = null;
    }
}&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Routing TcpClient HTTP requests through the default proxy</title><link>http://alandean.blogspot.com/2010/06/routing-tcpclient-http-requests-through.html</link><category>HTTP</category><pubDate>Sun, 27 Jun 2010 11:56:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-5008500887428324468</guid><description>&lt;p&gt;I’m coding an &lt;code&gt;HttpClient&lt;/code&gt; at the moment: mostly for self-education but something useful might arise as well. Here is a trivial example of making an HTTP request using the &lt;code&gt;&lt;a title="TcpClient Class (System.Net.Sockets)" href="http://msdn.microsoft.com/library/system.net.sockets.tcpclient" rel="nofollow"&gt;TcpClient&lt;/a&gt;&lt;/code&gt; class:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;string response = null;
System.Net.Sockets.TcpClient tcp = null;
try
{
    tcp = new System.Net.Sockets.TcpClient(&amp;quot;www.example.com&amp;quot;, 80);

    using (var stream = tcp.GetStream())
    {
        using (var writer = new System.IO.StreamWriter(stream))
        {
            writer.WriteLine(&amp;quot;GET / HTTP/1.1&amp;quot;);
            writer.WriteLine(&amp;quot;Host: www.example.com&amp;quot;);
            writer.WriteLine(&amp;quot;Connection: close&amp;quot;);
            writer.WriteLine(string.Empty);
            writer.Flush();
            using (var reader = new System.IO.StreamReader(stream))
            {
                response = reader.ReadToEnd();
            }
        }
    }
}
finally
{
    if (null != tcp)
    {
        tcp.Close();
    }
}&lt;/pre&gt;&lt;p&gt;&lt;a title="Hypertext Transfer Protocol -- HTTP/1.1" href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" rel="nofollow"&gt;HTTP&lt;/a&gt; is simply an application-level protocol layered on top of &lt;a title="Transmission Control Protocol" href="http://wikipedia.org/wiki/Transmission_Control_Protocol" rel="nofollow"&gt;TCP&lt;/a&gt;, so this works fine. However, as soon as the &lt;code&gt;HttpClient&lt;/code&gt; becomes non-trivial then debugging becomes an issue. Thankfully we have tools in place to see at what’s happening on the wire. &lt;a title="Wireshark · Go deep." href="http://www.wireshark.org/" rel="nofollow"&gt;Wireshark&lt;/a&gt; is an excellent tool which watches all TCP traffic on a network adapter but it is somewhat overkill for watching just HTTP traffic. &lt;a title="Fiddler Web Debugger - A free web debugging tool" href="http://www.fiddler2.com/fiddler2/" rel="nofollow"&gt;Fiddler&lt;/a&gt;, on the other hand, is my own tool of choice for monitoring HTTP traffic. Unfortunately the code shown above won’t appear in Fiddler as-is. Fiddler acts as a &lt;a title="Proxy server" href="http://wikipedia.org/wiki/Proxy_server" rel="nofollow"&gt;proxy&lt;/a&gt; and the code doesn’t cater for that. The &lt;code&gt;TcpClient&lt;/code&gt; class doesn’t either because a web proxy works at the HTTP layer rather than TCP.&lt;/p&gt;&lt;p&gt;In over to overcome this limitation, we can use the &lt;code&gt;&lt;a title="WebClient Class (System.Net)" href="http://msdn.microsoft.com/library/system.net.webclient" rel="nofollow"&gt;WebClient&lt;/a&gt;&lt;/code&gt; class to resolve the default proxy.&lt;/p&gt;&lt;pre class="brush: csharp"&gt;var requestUri = new System.Uri(&amp;quot;http://www.example.com/&amp;quot;);
Uri proxy = null;
using (var web = new System.Net.WebClient())
{
    proxy = web.Proxy.GetProxy(requestUri);
}

tcp = new System.Net.Sockets.TcpClient(proxy.DnsSafeHost, proxy.Port);&lt;/pre&gt;&lt;p&gt;Now Fiddler will now happily monitor the traffic. My thanks to &lt;a title="Steve Strong" href="http://twitter.com/srstrong" rel="bookmark"&gt;@srstrong&lt;/a&gt;, &lt;a title="Seb Lambla" href="http://twitter.com/serialseb" rel="bookmark"&gt;@serialseb&lt;/a&gt;, &lt;a title="Barry Dorrans" href="http://twitter.com/blowdart" rel="bookmark"&gt;@blowdart&lt;/a&gt;, &lt;a title="Ben Lovell" href="http://twitter.com/benlovell" rel="bookmark"&gt;@benlovell&lt;/a&gt; for helping me figure this out.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Run StyleCop on every build</title><link>http://alandean.blogspot.com/2010/06/run-stylecop-on-every-build.html</link><category>Build</category><pubDate>Sat, 26 Jun 2010 16:31:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-7547921851948588254</guid><description>&lt;p&gt;I first started using &lt;a title="StyleCop - Home" href="http://code.msdn.microsoft.com/sourceanalysis" rel="nofollow"&gt;StyleCop&lt;/a&gt; during a couple of projects with &lt;a title="Microsoft Services Home" href="http://www.microsoft.com/microsoftservices/en/uk/home.aspx" rel="nofollow"&gt;Microsoft Services&lt;/a&gt; when it was called Source Analysis and I’m a big fan because it helps makes code consistently formatted across a codebase. In order to have StyleCop run on every build, simply open the project file in the text editor of your choice (or you can unload the project from within the solution and then right-click to edit within Visual Studio) and add the &lt;code&gt;Microsoft.StyleCop.targets&lt;/code&gt; import (I normally add it immediately after the &lt;code&gt;Microsoft.CSharp.targets&lt;/code&gt; import):&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;Project ToolsVersion=&amp;quot;4.0&amp;quot; DefaultTargets=&amp;quot;Build&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&amp;gt;
    ...
    &amp;lt;Import Project=&amp;quot;$(MSBuildToolsPath)\Microsoft.CSharp.targets&amp;quot; /&amp;gt;
    &amp;lt;Import Project=&amp;quot;$(MSBuildExtensionsPath)\Microsoft\StyleCop\v4.3\Microsoft.StyleCop.targets&amp;quot; /&amp;gt;
    ...
&amp;lt;/Project&amp;gt;&lt;/pre&gt;&lt;p&gt;P.S. A plea to Microsoft: &lt;em&gt;can we have the standard project and class templates pass StyleCop by default please?&lt;/em&gt;&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Deploying to IIS7 from MSBuild</title><link>http://alandean.blogspot.com/2010/06/deploying-to-iis7-from-msbuild.html</link><category>Build</category><category>Deploy</category><pubDate>Sat, 26 Jun 2010 05:42:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-2756142571661832906</guid><description>&lt;p&gt;Here is an example of how to configure deployment of a web application on a development machine using &lt;a title="MSBuild Reference" href="http://msdn.microsoft.com/library/0k6kkbsd" rel="nofollow"&gt;MSBuild&lt;/a&gt; with the &lt;a title="MSBuild Extension Pack" href="http://msbuildextensionpack.codeplex.com/" rel="nofollow"&gt;Extension Pack&lt;/a&gt;:&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;Project DefaultTargets=&amp;quot;Run&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot; ToolsVersion=&amp;quot;3.5&amp;quot;&amp;gt;

    &amp;lt;Import Project=&amp;quot;$(MSBuildProjectDirectory)\lib\trove\Framework\v2.0\MSBuild.Community.Tasks.Targets&amp;quot; /&amp;gt;
    &amp;lt;Import Project=&amp;quot;$(MSBuildProjectDirectory)\lib\trove\Framework\v3.5\MSBuild.ExtensionPack.tasks&amp;quot; /&amp;gt;

    &amp;lt;Target Name=&amp;quot;Run&amp;quot;&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Clean&amp;quot; /&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Build&amp;quot; /&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Deploy&amp;quot; Condition=&amp;quot;'$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp@MajorVersion)'=='7'&amp;quot; /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Clean&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Example.sln&amp;quot;
            Targets=&amp;quot;Clean&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;
            /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Build&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Example.sln&amp;quot;
            Targets=&amp;quot;Rebuild&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;&amp;gt;
            &amp;lt;Output
                TaskParameter=&amp;quot;TargetOutputs&amp;quot;
                ItemName=&amp;quot;CodeAssemblies&amp;quot;
                /&amp;gt;
        &amp;lt;/MSBuild&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;PropertyGroup&amp;gt;
        &amp;lt;WebApplicationName&amp;gt;www.example.net&amp;lt;/WebApplicationName&amp;gt;
        &amp;lt;WebApplicationPath&amp;gt;$(MSBuildProjectDirectory)\src\Web Applications\Example&amp;lt;/WebApplicationPath&amp;gt;
    &amp;lt;/PropertyGroup&amp;gt;

    &amp;lt;Target Name=&amp;quot;Deploy&amp;quot;&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Website
            TaskAction=&amp;quot;CheckExists&amp;quot; 
            Name=&amp;quot;$(WebApplicationName)&amp;quot;&amp;gt;
            &amp;lt;Output
                TaskParameter=&amp;quot;Exists&amp;quot;
                PropertyName=&amp;quot;WebApplicationExists&amp;quot;
                /&amp;gt;
        &amp;lt;/MSBuild.ExtensionPack.Web.Iis7Website&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Website
            TaskAction=&amp;quot;Create&amp;quot;
            Name=&amp;quot;$(WebApplicationName)&amp;quot;
            Path=&amp;quot;$(WebApplicationPath)&amp;quot;
            Port=&amp;quot;80&amp;quot;
            AppPool=&amp;quot;ASP.NET v4.0&amp;quot;
            Condition=&amp;quot;'$(WebApplicationExists)'=='False'&amp;quot;
            /&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Binding
            TaskAction=&amp;quot;Remove&amp;quot;
            Name=&amp;quot;$(WebApplicationName)&amp;quot;
            BindingInformation=&amp;quot;*:80:&amp;quot;
            BindingProtocol=&amp;quot;http&amp;quot;
            /&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Binding
            TaskAction=&amp;quot;Add&amp;quot;
            Name=&amp;quot;$(WebApplicationName)&amp;quot;
            BindingInformation=&amp;quot;127.0.0.127:80:$(WebApplicationName)&amp;quot;
            BindingProtocol=&amp;quot;http&amp;quot;
            Condition=&amp;quot;'$(WebApplicationExists)'=='False'&amp;quot;
            /&amp;gt;
        &amp;lt;MSBuild.Community.Tasks.Sleep Milliseconds=&amp;quot;3000&amp;quot; /&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Website
            TaskAction=&amp;quot;Stop&amp;quot;
            Name=&amp;quot;$(WebApplicationName)&amp;quot;
            /&amp;gt;
        &amp;lt;MSBuild.Community.Tasks.Sleep Milliseconds=&amp;quot;3000&amp;quot; /&amp;gt;
        &amp;lt;MSBuild.ExtensionPack.Web.Iis7Website
            TaskAction=&amp;quot;Start&amp;quot;
            Name=&amp;quot;$(WebApplicationName)&amp;quot;
            /&amp;gt;
    &amp;lt;/Target&amp;gt;

&amp;lt;/Project&amp;gt;&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Consistent Assembly Versioning</title><link>http://alandean.blogspot.com/2010/06/consistent-assembly-versioning.html</link><category>Build</category><pubDate>Fri, 25 Jun 2010 04:37:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-2633696703080831145</guid><description>&lt;p&gt;Personally, I like to have consistent versioning applied to all assemblies from the same build. Doing this manually is a PITA so I version from my build file and I have a pattern which I apply to achieve this. I typically use subversion for my source control and I will use the &lt;a title="Cavity - Tools and utilities for .NET" href="http://code.google.com/p/cavity/" rel="bookmark"&gt;Cavity&lt;/a&gt; project as an example:&lt;/p&gt;&lt;p&gt;&lt;img alt="Subversion project structure" src="http://farm2.static.flickr.com/1404/4732191985_2a0efefce6_o.png" width="99" height="127" /&gt;&lt;/p&gt;&lt;p&gt;I build from the trunk folder:&lt;/p&gt;&lt;p&gt;&lt;img alt="Subversion trunk folder" src="http://farm2.static.flickr.com/1145/4732192015_ea822a0347_o.png" width="207" height="332" /&gt;&lt;/p&gt;&lt;p&gt;I have a batch file for each ‘potted’ configuration I want and, of course, the &lt;a title="MSBuild Reference" href="http://msdn.microsoft.com/library/0k6kkbsd" rel="nofollow"&gt;MSBuild&lt;/a&gt; file. Here is the release batch file:&lt;/p&gt;&lt;pre class="brush: text"&gt;MSBUILD build.xml /p:Configuration=Release
PAUSE&lt;/pre&gt;&lt;p&gt;In order to apply consistent versioning, I want to emit a &lt;code&gt;Build.cs&lt;/code&gt; file and then link that to each project. If I want this to be a static number, I can simply configure the version directly and use &lt;code&gt;AssemblyInfo&lt;/code&gt; task from the &lt;a title="MSBuild Community Tasks Project" href="http://msbuildtasks.tigris.org/" rel="nofollow"&gt;MSBuild Community Tasks Project&lt;/a&gt;:&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;Project DefaultTargets=&amp;quot;Run&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot; ToolsVersion=&amp;quot;3.5&amp;quot;&amp;gt;
    &amp;lt;Import Project=&amp;quot;$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets&amp;quot; /&amp;gt;

    &amp;lt;PropertyGroup&amp;gt;
        &amp;lt;Configuration Condition=&amp;quot;'$(Configuration)'==''&amp;quot;&amp;gt;Release&amp;lt;/Configuration&amp;gt;
        &amp;lt;Version Condition=&amp;quot;'$(Version)'==''&amp;quot;&amp;gt;1.2.3.4&amp;lt;/Version&amp;gt;
    &amp;lt;/PropertyGroup&amp;gt;

    &amp;lt;Target Name=&amp;quot;Run&amp;quot;&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Clean&amp;quot; /&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Build&amp;quot; /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Clean&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Cavity.sln&amp;quot;
            Targets=&amp;quot;Clean&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;
        /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Versioning&amp;quot;&amp;gt;
        &amp;lt;AssemblyInfo
            CodeLanguage=&amp;quot;CS&amp;quot;
            OutputFile=&amp;quot;$(MSBuildProjectDirectory)\src\Build.cs&amp;quot;
            AssemblyVersion=&amp;quot;$(Version)&amp;quot;
            AssemblyFileVersion=&amp;quot;$(Version)&amp;quot;
            AssemblyInformationalVersion=&amp;quot;$(Version)&amp;quot;
            /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Build&amp;quot; DependsOnTargets=&amp;quot;Versioning&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Cavity.sln&amp;quot;
            Targets=&amp;quot;Rebuild&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;&amp;gt;
            &amp;lt;Output
                TaskParameter=&amp;quot;TargetOutputs&amp;quot;
                ItemName=&amp;quot;CodeAssemblies&amp;quot;
                /&amp;gt;
        &amp;lt;/MSBuild&amp;gt;
    &amp;lt;/Target&amp;gt;

&amp;lt;/Project&amp;gt;&lt;/pre&gt;&lt;p&gt;This will emit the following &lt;code&gt;Build.cs&lt;/code&gt;:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;//------------------------------------------------------------------------------
// &amp;lt;auto-generated&amp;gt;
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.1
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// &amp;lt;/auto-generated&amp;gt;
//------------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion(&amp;quot;1.2.3.4&amp;quot;)]
[assembly: AssemblyFileVersion(&amp;quot;1.2.3.4&amp;quot;)]
[assembly: AssemblyInformationalVersion(&amp;quot;1.2.3.4&amp;quot;)]&lt;/pre&gt;&lt;p&gt;However, I normally use the subversion Revision number as the build number to be able to identify what was built. To do this you will need to install the &lt;a title="CollabNet Subversion Downloads" href="http://www.open.collab.net/downloads/subversion/" rel="nofollow"&gt;CollabNet Subversion client&lt;/a&gt; in order to be able to query the subversion repository. Once installed, you can then use the following build file to emit a dynamic version number by utilising the &lt;code&gt;SvnVersion&lt;/code&gt; task:&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;Project DefaultTargets=&amp;quot;Run&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot; ToolsVersion=&amp;quot;3.5&amp;quot;&amp;gt;
    &amp;lt;Import Project=&amp;quot;$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets&amp;quot; /&amp;gt;

    &amp;lt;PropertyGroup&amp;gt;
        &amp;lt;Configuration Condition=&amp;quot;'$(Configuration)'==''&amp;quot;&amp;gt;Release&amp;lt;/Configuration&amp;gt;
        &amp;lt;Version Condition=&amp;quot;'$(Version)'==''&amp;quot;&amp;gt;1.2.3&amp;lt;/Version&amp;gt;
        &amp;lt;Revision&amp;gt;0&amp;lt;/Revision&amp;gt;
    &amp;lt;/PropertyGroup&amp;gt;

    &amp;lt;Target Name=&amp;quot;Run&amp;quot;&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Clean&amp;quot; /&amp;gt;
        &amp;lt;CallTarget Targets=&amp;quot;Build&amp;quot; /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Clean&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Cavity.sln&amp;quot;
            Targets=&amp;quot;Clean&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;
            /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Versioning&amp;quot;&amp;gt;
        &amp;lt;SvnVersion LocalPath=&amp;quot;.&amp;quot;&amp;gt;
            &amp;lt;Output TaskParameter=&amp;quot;Revision&amp;quot; PropertyName=&amp;quot;Revision&amp;quot; /&amp;gt;
        &amp;lt;/SvnVersion&amp;gt;
        &amp;lt;AssemblyInfo
            CodeLanguage=&amp;quot;CS&amp;quot;
            OutputFile=&amp;quot;$(MSBuildProjectDirectory)\src\Build.cs&amp;quot;
            AssemblyVersion=&amp;quot;$(Version).$(Revision)&amp;quot;
            AssemblyFileVersion=&amp;quot;$(Version).$(Revision)&amp;quot;
            AssemblyInformationalVersion=&amp;quot;$(Version).$(Revision)&amp;quot;
            /&amp;gt;
    &amp;lt;/Target&amp;gt;

    &amp;lt;Target Name=&amp;quot;Build&amp;quot; DependsOnTargets=&amp;quot;Versioning&amp;quot;&amp;gt;
        &amp;lt;MSBuild
            Projects=&amp;quot;$(MSBuildProjectDirectory)\src\Cavity.sln&amp;quot;
            Targets=&amp;quot;Rebuild&amp;quot;
            Properties=&amp;quot;Configuration=$(Configuration)&amp;quot;&amp;gt;
            &amp;lt;Output
                TaskParameter=&amp;quot;TargetOutputs&amp;quot;
                ItemName=&amp;quot;CodeAssemblies&amp;quot;
                /&amp;gt;
        &amp;lt;/MSBuild&amp;gt;
    &amp;lt;/Target&amp;gt;

&amp;lt;/Project&amp;gt;&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Abstracting Service Location</title><link>http://alandean.blogspot.com/2010/06/abstracting-service-location.html</link><category>Cavity</category><pubDate>Sat, 19 Jun 2010 07:24:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-6486963950777417784</guid><description>&lt;p&gt;A couple of days ago I blogged about the &lt;a title="Common Service Locator library" href="http://commonservicelocator.codeplex.com/" rel="nofollow"&gt;Common Service Locator&lt;/a&gt;, how to use the ServiceLocator and &lt;a title="Mocking IServiceLocator" href="http://alandean.blogspot.com/2010/06/mocking-iservicelocator.html" rel="nofollow"&gt;how to mock the IServiceLocator interface for unit testing purposes&lt;/a&gt;. However, I personally feel that the Common Service Locator library didn’t complete the job. Ideally, I should not need to choose specific &lt;a title="Inversion of control" href="http://wikipedia.org/wiki/Inversion_of_control" rel="nofollow"&gt;&lt;acronym title="Inversion of Control"&gt;IoC&lt;/acronym&gt;&lt;/a&gt; provider whilst writing my code (or at least should not be forced to recompile my application in order to change provider) and the library doesn’t enable this.&lt;/p&gt;&lt;p&gt;In order to enable this use case, I’ve published a set of lightweight libraries in the &lt;a title="Cavity - Tools and utilities for .NET" href="http://code.google.com/p/cavity/" rel="bookmark"&gt;Cavity&lt;/a&gt; project. The key library is &lt;code&gt;Cavity.ServiceLocation.dll&lt;/code&gt; which contains one interface and one concrete class. The interface is, frankly, trivial:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Cavity.Configuration
{
    public interface ISetLocatorProvider
    {
        void Configure();
    }
}&lt;/pre&gt;&lt;p&gt;The interface is trivial simply because it’s a hook to load the provider-specific configuration data. I have provided a plain vanilla implementation for &lt;a title="autofac - An addictive .NET IoC container" href="http://code.google.com/p/autofac/" rel="nofollow"&gt;Autofac&lt;/a&gt;, &lt;a title="MicroKernel/Windsor :: Castle Project" href="http://www.castleproject.org/container/" rel="nofollow"&gt;Castle Windsor&lt;/a&gt;, &lt;a title="StructureMap Home Page" href="http://structuremap.github.com/structuremap/" rel="nofollow"&gt;StructureMap&lt;/a&gt; and &lt;a title="patterns &amp;amp; practices - Unity" href="http://unity.codeplex.com/" rel="nofollow"&gt;Unity&lt;/a&gt; because each of these supports XML configuration. Here is the implementation of the Castle Windsor &lt;code&gt;ISetLocatorProvider&lt;/code&gt;:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Cavity.Configuration
{
    using Castle.Windsor;
    using Castle.Windsor.Configuration.Interpreters;
    using CommonServiceLocator.WindsorAdapter;
    using Microsoft.Practices.ServiceLocation;

    public sealed class XmlServiceLocatorProvider : ISetLocatorProvider
    {
        public void Configure()
        {
            var container = new WindsorContainer(new XmlInterpreter());
            ServiceLocator.SetLocatorProvider(() =&amp;gt; new WindsorServiceLocator(container));
        }
    }
}&lt;/pre&gt;&lt;p&gt;As you can see, the code is lightweight: create a container, load it with configuration data and apply the configured container to the generic &lt;code&gt;ServiceLocator&lt;/code&gt; and you’re done. To set up Castle Windsor as your provider, you must edit your &lt;code&gt;app.config&lt;/code&gt; or &lt;code&gt;web.config&lt;/code&gt;, as appropriate, as follows (having a separate &lt;code&gt;castle.config&lt;/code&gt; is optional but generally considered preferable):&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section
            name=&amp;quot;castle&amp;quot;
            type=&amp;quot;Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor&amp;quot;/&amp;gt;
        &amp;lt;section
            name=&amp;quot;serviceLocation&amp;quot;
            type=&amp;quot;Cavity.Configuration.ServiceLocation, Cavity.ServiceLocation&amp;quot;/&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;castle configSource=&amp;quot;castle.config&amp;quot; /&amp;gt;
    &amp;lt;serviceLocation type=&amp;quot;Cavity.Configuration.XmlServiceLocatorProvider, Cavity.ServiceLocation.CastleWindsor&amp;quot; /&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;&amp;lt;serviceLocation&amp;gt;&lt;/code&gt; element &lt;code&gt;type&lt;/code&gt; attribute points to the &lt;code&gt;ISetLocatorProvider&lt;/code&gt; implementation you wish to use. To learn more about &lt;code&gt;castle.config&lt;/code&gt;, see &lt;em&gt;&lt;a title="Initializing with an external configuration :: Castle Project" href="http://www.castleproject.org/container/documentation/v21/usersguide/externalconfig.html" rel="nofollow"&gt;Initializing with an external configuration&lt;/a&gt;&lt;/em&gt;. To see examples of each provider, you can browse the &lt;a title="Cavity - example console applications" href="http://code.google.com/p/cavity/source/browse/#svn/trunk/src/ConsoleApplications" rel="bookmark"&gt;Cavity source code&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you prefer to specific your container via a &lt;a title="Fluent interface" href="http://wikipedia.org/wiki/Fluent_interface" rel="nofollow"&gt;fluent interface&lt;/a&gt;, then you can still employ the &lt;code&gt;ISetLocatorProvider&lt;/code&gt; abstraction by writing a custom implementation.&lt;/p&gt;&lt;p&gt;More detail about using the &lt;code&gt;Cavity.ServiceLocation.dll&lt;/code&gt; library can be seen on the &lt;a title="Cavity Service Location" href="http://code.google.com/p/cavity/wiki/ServiceLocation" rel="bookmark"&gt;Cavity Wiki&lt;/a&gt;. Packages for each of the four plain vanilla implementations can be &lt;a title="Cavity Download List" href="http://code.google.com/p/cavity/downloads/list" rel="bookmark"&gt;downloaded as zips&lt;/a&gt; and the binaries are also &lt;a title="Trove" href="http://alandean.blogspot.com/2010/06/trove.html" rel="bookmark"&gt;available via trove&lt;/a&gt;.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Mocking IServiceLocator</title><link>http://alandean.blogspot.com/2010/06/mocking-iservicelocator.html</link><category>TDD</category><pubDate>Thu, 17 Jun 2010 12:28:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-7392450402075469976</guid><description>&lt;p&gt;Using &lt;a title="Inversion of control" href="http://wikipedia.org/wiki/Inversion_of_control" rel="nofollow"&gt;&lt;acronym title="Inversion of Control"&gt;IoC&lt;/acronym&gt;&lt;/a&gt; has become far more popular in recent years but it is very easy to end up &lt;a title="Decoupling - Software Development" href="http://en.wikipedia.org/wiki/Decoupling#Software_Development" rel="nofollow"&gt;decoupling&lt;/a&gt; your components but at the same time end up tightly coupled to a specific provider, such as &lt;a title="MicroKernel/Windsor :: Castle Project" href="http://www.castleproject.org/container/" rel="nofollow"&gt;Castle Windsor&lt;/a&gt;. The first step to decouple the IoC provider is to utilize the &lt;a title="Common Service Locator library" href="http://commonservicelocator.codeplex.com/" rel="nofollow"&gt;Common Service Locator&lt;/a&gt; published by the &lt;a title="patterns &amp;amp; practices: Developer Center Home" href="http://msdn.microsoft.com/practices/" rel="nofollow"&gt;Microsoft patterns &amp;amp; practices&lt;/a&gt; team. Here is a trivial example of decoupling using the ServiceLocator:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Example
{
    using Microsoft.Practices.ServiceLocation;

    public interface IFoo
    {
        void Foo();
    }

    public sealed class FooImplementation : IFoo
    {
        public void Foo()
        {
        }
    }

    public sealed class Class1
    {
        public Class1()
        {
            this.Foo = ServiceLocator.Current.GetInstance&amp;lt;IFoo&amp;gt;();
        }

        public IFoo Foo
        {
            get;
            private set;
        }
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;However, if you run the following test, a &lt;c&gt;System.ArgumentNullException&lt;/c&gt; will be thrown as the ServiceLocator does not have a provider set:&lt;/p&gt;&lt;br /&gt;
&lt;pre class="brush: csharp"&gt;namespace Example
{
    using Xunit;

    public sealed class Class1Facts
    {
        [Fact]
        public void ctor()
        {
            Assert.NotNull(new Class1());
        }
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Rather than configure a specific provider, it’s much cleaner to &lt;a title="Mocks Aren&amp;#39;t Stubs" href="http://martinfowler.com/articles/mocksArentStubs.html" rel="nofollow"&gt;mock&lt;/a&gt; out the ServiceLocator. The following example uses &lt;a title="moq - The simplest mocking library for .NET 3.5 and Silverlight with deep C# 3.0 integration" href="http://code.google.com/p/moq/" rel="nofollow"&gt;Moq&lt;/a&gt; but the principle applies regardless of your preferred mocking framework:&lt;/p&gt;&lt;br /&gt;
&lt;pre class="brush: csharp"&gt;namespace Example
{
    using Microsoft.Practices.ServiceLocation;
    using Moq;
    using Xunit;

    public sealed class Class1Facts
    {
        [Fact]
        public void ctor()
        {
            try
            {
                var mock = new Mock&amp;lt;IServiceLocator&amp;gt;();
                mock.Setup(x =&amp;gt; x.GetInstance&amp;lt;IFoo&amp;gt;()).Returns(new FooImplementation()).Verifiable();
                ServiceLocator.SetLocatorProvider(new ServiceLocatorProvider(() =&amp;gt; mock.Object));

                Assert.NotNull(new Class1());

                mock.VerifyAll();
            }
            finally
            {
                ServiceLocator.SetLocatorProvider(null);
            }
        }
    }
}&lt;/pre&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Trove</title><link>http://alandean.blogspot.com/2010/06/trove.html</link><category>Trove</category><pubDate>Thu, 17 Jun 2010 03:52:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-8085128135352664510</guid><description>&lt;p&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" alt="Treasure Chest" align="right" src="http://farm5.static.flickr.com/4040/4691623398_656f812d27_o.jpg" width="342" height="351" /&gt;Over the last couple of months I have been thinking about &lt;a title="Package management system" href="http://wikipedia.org/wiki/Package_management_system" rel="nofollow"&gt;package management&lt;/a&gt; in the .net ecosystem. If you only develop using assemblies from Microsoft then you will not have had to think much about this but if you utilize open source assemblies then it can rapidly become a real bugbear. Some open source packages are standalone and thus don’t suffer reference problems; the &lt;a title="Html Agility Pack" href="http://htmlagilitypack.codeplex.com/" rel="nofollow"&gt;HtmlAgilityPack&lt;/a&gt; is a good example of this as it only references the &lt;a title="System Namespace" href="http://msdn.microsoft.com/library/system" rel="nofollow"&gt;System&lt;/a&gt; assemblies. If you start utilizing the &lt;a title="Home :: Castle Project" href="http://www.castleproject.org/" rel="nofollow"&gt;Castle Project&lt;/a&gt; (the &lt;a title="Inversion of control" href="http://wikipedia.org/wiki/Inversion_of_control" rel="nofollow"&gt;&lt;acronym title="Inversion of Control"&gt;IoC&lt;/acronym&gt;&lt;/a&gt; functionality in &lt;a title="MicroKernal/Windsor :: Castle Project" href="http://www.castleproject.org/container/" rel="nofollow"&gt;Windsor&lt;/a&gt; or the &lt;a title="Home - NHibernate Forge" href="http://nhforge.org/" rel="nofollow"&gt;NHibernate&lt;/a&gt; functionality in &lt;a title="ActiveRecord :: Castle Project" href="http://www.castleproject.org/activerecord/" rel="nofollow"&gt;ActiveRecord&lt;/a&gt; are commonly employed) then you will rapidly encounter reference problems, especially if you also use other libraries that also depend on Castle.&lt;/p&gt;&lt;p&gt;Now I’m not the first to consider this problem. &lt;a title="HornGet" href="http://www.hornget.net/" rel="nofollow"&gt;HornGet&lt;/a&gt; takes the direct approach of building the source and publishing the binaries. I don’t know how much, if any, verification work is done but I have noticed that the builds seem to break rather frequently which doesn’t inspire confidence. As an experiment, I decided to carry out a poor man’s replication of that approach by simply writing a batch build file of a sequence of projects. One of the first issues I discovered was that the trunk often doesn’t build successfully on open source project. I suppose that I should not have been surprised, of course. I then carried out a second experiment, building from branches where available. This typically built successfully but the dependencies were incompatible, leaving you choose this &lt;em&gt;or&lt;/em&gt; that rather than this &lt;em&gt;and&lt;/em&gt; that. So my conclusion was that direct build doesn’t meet the need.&lt;/p&gt;&lt;p&gt;After direct build, there is &lt;a title="RubyGems.org | your community gem host" href="http://rubygems.org/" rel="nofollow"&gt;Ruby Gems&lt;/a&gt; envy. I’m convinced that there was an NGem project at one time but I can’t find it and it certainly didn’t get any adoption by the community. At present I’m aware of at least three projects that want to create a solution to the problem: &lt;a title="OpenWrap - Google Search" href="http://www.google.com/search?q=openwrap" rel="nofollow"&gt;OpenWrap&lt;/a&gt;, &lt;a title="Bricks – A preview of a .NET package manager" href="http://jonorossi.com/blog/archive/2010/04/11/bricks-a-preview-of-a-.net-package-manager.aspx" rel="nofollow"&gt;Bricks&lt;/a&gt;, and &lt;a title="The Common Opensource Application Publishing Platform" href="http://coapp.org/" rel="nofollow"&gt;CoApp&lt;/a&gt;. The problem is that all of these are either vapourware or alpha code and I want something useful right now.&lt;/p&gt;&lt;p&gt;After musing for a little while, it was clear to me that simply starting yet-another-package-management-project would be wasteful duplication. Maybe one of the currently active projects will come to something, who knows. I then got to thinking about what would be &lt;a title="Do The Simplest Thing That Could Possibly Work" href="http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html" rel="nofollow"&gt;&lt;q cite="http://en.wikiquote.org/wiki/Ward_Cunningham#The_Simplest_Thing_that_Could_Possibly_Work"&gt;the simplest thing that could possibly work?&lt;/q&gt;&lt;/a&gt; &lt;sup&gt;&lt;a title="Ward Cunningham" href="http://en.wikiquote.org/wiki/Ward_Cunningham" rel="nofollow"&gt;(Ward Cunningham)&lt;/a&gt;&lt;/sup&gt;. Well, maybe the simplest thing would be just to work on a single package of mutually consistent assemblies. Not so hard to do either, so long as you put together some verification tests to check that the package as a whole is stable and mutually dependent. How to distribute? An easy way would be just zip up the assemblies to share that but then it occurred to me that I could simply create a Subversion repo and consumers could simply link to it using &lt;a title="Version Control with Subversion" href="http://svnbook.red-bean.com/en/1.1/svn-book.html#svn-ch-7-sect-2.3.6" rel="nofollow"&gt;svn:externals&lt;/a&gt; which is really simple to &lt;a title="Setting Up Subversion Externals With TortoiseSVN" href="http://justaddwater.dk/2007/10/23/setting-up-subversion-externals-with-tortoisesvn/" rel="nofollow"&gt;configure with TortoiseSVN&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Thus was born &lt;a title="trove - a .NET Library Repo" href="http://code.google.com/p/trove/" rel="bookmark"&gt;http://code.google.com/p/trove/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;There is a &lt;a title="trove manifest" href="http://code.google.com/p/trove/wiki/manifest" rel="bookmark"&gt;manifest&lt;/a&gt; of the contained assemblies. All you need to do is add an &lt;code&gt;svn:externals&lt;/code&gt; property on your &lt;code&gt;lib&lt;/code&gt; folder of “&lt;code&gt;trove &lt;a href="http://trove.googlecode.com/svn/trunk/lib"&gt;http://trove.googlecode.com/svn/trunk/lib&lt;/a&gt;&lt;/code&gt;” and update :-)&lt;/p&gt;&lt;p&gt;If you pull down the whole project, you will also get the verification tests.&lt;/p&gt;&lt;p&gt;At the moment, the trove contains:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a title="ANTLR v3 C# Code generator and Runtime library" href="http://www.antlr.org/wiki/display/ANTLR3/Antlr+3+CSharp+Target" rel="nofollow"&gt;Antlr3&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="autofac - An addictive .NET IoC container" href="http://code.google.com/p/autofac/" rel="nofollow"&gt;Autofac&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="The C5 Generic Collection Library" href="http://www.itu.dk/research/c5/" rel="nofollow"&gt;C5&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Home :: Castle Project" href="http://www.castleproject.org/" rel="nofollow"&gt;Castle&lt;/a&gt; (ActiveRecord, Logging, Transaction, Validator, Windsor and some Facilities) &lt;/li&gt;
&lt;li&gt;&lt;a title="Cavity - Tools and utilities for .NET" href="http://code.google.com/p/cavity/" rel="bookmark"&gt;Cavity&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Command Line Parser Library" href="http://commandline.codeplex.com/" rel="nofollow"&gt;CommandLine&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Common Service Locator library" href="http://commonservicelocator.codeplex.com/" rel="nofollow"&gt;CommonServiceLocator&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Fitnesse.Net" href="http://www.syterra.com/FitnesseDotNet.html" rel="nofollow"&gt;Fitnesse&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Fast Lightweight Expression Evaluator" href="http://flee.codeplex.com/" rel="nofollow"&gt;Flee&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Fluent NHibernate" href="http://fluentnhibernate.org/" rel="nofollow"&gt;FluentNHibernate&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Fluent Validation" href="http://fluentvalidation.codeplex.com/" rel="nofollow"&gt;FluentValidation&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Html Agility Pack" href="http://htmlagilitypack.codeplex.com/" rel="nofollow"&gt;HtmlAgilityPack&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Add Support for &amp;quot;Set&amp;quot; Collections to .NET" href="http://www.codeproject.com/KB/recipes/sets.aspx" rel="nofollow"&gt;IesiCollections&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Json.NET" href="http://json.codeplex.com/" rel="nofollow"&gt;Json&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="linfu - A framework that adds mixins, inversion of control, DbC, and other language features to the Common Language Runtime" href="http://code.google.com/p/linfu/" rel="nofollow"&gt;LinFu&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Apache log4net" href="http://logging.apache.org/log4net/" rel="nofollow"&gt;log4net&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Lucene.Net" href="http://lucene.apache.org/lucene.net/" rel="nofollow"&gt;Lucene&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Math.NET Project" href="http://www.mathdotnet.com/" rel="nofollow"&gt;MathNet&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Managed Extensibility Framework" href="http://mef.codeplex.com/" rel="nofollow"&gt;MEF&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="moq - The simplest mocking library for .NET 3.5 and Silverlight with deep C# 3.0 integration" href="http://code.google.com/p/moq/" rel="nofollow"&gt;Moq&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Home - NHibernate Forge" href="http://nhforge.org/" rel="nofollow"&gt;NHibernate&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Nini: An uncommonly powerful .NET configuration library" href="http://nini.sourceforge.net/" rel="nofollow"&gt;Nini&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Open source dependency injector for .NET - Ninject" href="http://ninject.org/" rel="nofollow"&gt;Ninject&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="NLog – Advanced .NET Logging" href="http://nlog-project.org/" rel="nofollow"&gt;NLog&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="NMock: A Dynamic Mock Object Library for .NET" href="http://www.nmock.org/" rel="nofollow"&gt;NMock&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="noda-time - A port of Joda Time to .NET" href="http://code.google.com/p/noda-time/" rel="nofollow"&gt;NodaTime&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="NUnit - Home" href="http://www.nunit.org/" rel="nofollow"&gt;NUnit&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Wintellect&amp;#39;s Power Collections for .NET" href="http://powercollections.codeplex.com/" rel="nofollow"&gt;PowerCollections&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="Rhino.Mocks" href="http://www.ayende.com/projects/rhino-mocks.aspx" rel="nofollow"&gt;RhinoMocks&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="SQLite Home Page" href="http://www.sqlite.org/" rel="nofollow"&gt;SQLite&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="StructureMap Home Page" href="http://structuremap.github.com/structuremap/" rel="nofollow"&gt;StructureMap&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="SubSonic: All Your Database Are Belong To Us" href="http://www.subsonicproject.com/" rel="nofollow"&gt;SubSonic&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="patterns &amp;amp; practices - Unity" href="http://unity.codeplex.com/" rel="nofollow"&gt;Unity&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="WCF REST Starter Kit" href="http://aspnet.codeplex.com/wikipage?title=WCF%20REST" rel="nofollow"&gt;WCF REST Starter Kit&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a title="xUnit.net - Unit Testing for .NET" href="http://xunit.codeplex.com/" rel="nofollow"&gt;xUnit&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If there are other libraries you think I should have in the trove, please let me know.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>NDepend Review</title><link>http://alandean.blogspot.com/2010/06/ndepend-review.html</link><category>Cavity</category><pubDate>Wed, 16 Jun 2010 08:02:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-5359113259566078607</guid><description>&lt;p&gt;&lt;em&gt;[Disclaimer: I have been given a free copy of &lt;/em&gt;&lt;a title="NDepend" href="http://ndepend.com/" rel="nofollow"&gt;&lt;em&gt;NDepend&lt;/em&gt;&lt;/a&gt;&lt;em&gt; in order to be able to write this review]&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;As I have released my unit testing DSL on &lt;a title="Cavity Project" href="http://code.google.com/p/cavity/" rel="bookmark"&gt;Cavity&lt;/a&gt;, I thought that this would be a good opportunity to take a look at NDepend (a tool which I already knew about but hadn’t taken out for a ride, in no small part because I was not sure that I would get enough benefit to justify the license price which &lt;a title="NDepend Purchase" href="http://ndepend.com/purchase.aspx" rel="nofollow"&gt;starts from €299&lt;/a&gt;). It is worth pointing out that before I ran NDepend, the assembly passed both &lt;a title="Guidelines for Using Code Analysis Tools" href="http://msdn.microsoft.com/library/ms182023" rel="nofollow"&gt;Code Analysis&lt;/a&gt; and &lt;a title="StyleCop" href="http://code.msdn.microsoft.com/sourceanalysis" rel="nofollow"&gt;Source Analysis&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Installation is simple: unzip the &lt;a title="Download NDepend Trial / Open Source / Academic Edition" href="http://ndepend.com/ndependdownload.aspx" rel="nofollow"&gt;download&lt;/a&gt; to your preferred location and run the application. Also included is support for &lt;a title="MSBuild Reference" href="http://msdn.microsoft.com/library/0k6kkbsd" rel="nofollow"&gt;MSBuild&lt;/a&gt;, &lt;a title="CruiseControl Home" href="http://cruisecontrol.sourceforge.net/" rel="nofollow"&gt;CruiseControl&lt;/a&gt; and &lt;a title="NAnt - A .NET Build Tool" href="http://nant.sourceforge.net/" rel="nofollow"&gt;NAnt&lt;/a&gt;. Although installation is simple, I do think that also providing an &lt;a title="About Windows Installer" href="http://msdn.microsoft.com/library/aa367449" rel="nofollow"&gt;&lt;abbr title="Microsoft Installet"&gt;MSI&lt;/abbr&gt;&lt;/a&gt; installer would be useful but that’s not a deal-breaker for me.&lt;/p&gt;  &lt;p&gt;The application provides a start screen:&lt;/p&gt;  &lt;p&gt;&lt;a title="NDepend Start Screen" href="http://www.flickr.com/photos/alan-dean/4705400553/"&gt;&lt;img alt="NDepend Start Screen" src="http://farm5.static.flickr.com/4031/4705400553_b5641b0e57_m.jpg" width="240" height="148" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I didn’t bother with creating a project, I just went straight ahead and selected the &lt;c&gt;Cavity.Testing.Unit.dll&lt;/c&gt; to analyze. When this is done, an html report is emitted and the application shifts into Quick Project mode so that you can browse the assembly. The html report provides a great deal of information and here are some sections:&lt;/p&gt;  &lt;h4&gt;Application Metrics&lt;/h4&gt;  &lt;p&gt;&lt;img alt="Application Metrics Section" src="http://farm2.static.flickr.com/1284/4706014998_dbf6fe3bc9_b.jpg" width="929" height="660" /&gt;&lt;/p&gt;  &lt;p&gt;This section provides an overview of the gross topology of the assembly, the contained types (classes, interfaces and so on) and the maximum statistical result such as the highest &lt;a title="Cyclomatic complexity" href="http://wikipedia.org/wiki/Cyclomatic_complexity" rel="nofollow"&gt;cyclomatic complexity&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Assemblies Metrics&lt;/h4&gt;  &lt;p&gt;&lt;img alt="Assemblies Metrics Section" src="http://farm5.static.flickr.com/4045/4706015040_6de0624bb0_o.png" width="1341" height="112" /&gt;&lt;/p&gt;  &lt;p&gt;This section provides &lt;a title="Metrics on assemblies" href="http://www.ndepend.com/Metrics.aspx#MetricsOnAssemblies" rel="nofollow"&gt;headline metrics&lt;/a&gt; which indicate how maintainable the assembly is. At first glance, this is all rather obtuse so the report next provides an easy-to-understand graph.&lt;/p&gt;  &lt;h4&gt;Assemblies Abstractness vs. Instability&lt;/h4&gt;  &lt;p&gt;&lt;a title="Abstractness vs. Instability Graph" href="http://www.flickr.com/photos/alan-dean/4705372221/"&gt;&lt;img alt="Abstractness vs. Instability Graph" src="http://farm2.static.flickr.com/1288/4705372221_0c0d1b05a1.jpg" width="453" height="500" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;My assembly is sitting inside the green zone, so I’m going to infer that it is broadly maintainable.&lt;/p&gt;  &lt;h4&gt;Assemblies Dependencies Diagram&lt;/h4&gt;  &lt;p&gt;&lt;a title="Assemblies Dependencies Diagram" href="http://www.flickr.com/photos/alan-dean/4706015106/"&gt;&lt;img alt="Assemblies Dependencies Diagram" src="http://farm5.static.flickr.com/4036/4706015106_ec20707f76_m.jpg" width="226" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’m only looking at one assembly (and a rather trivial one at that) so this diagram isn’t very informative but I imagine that for multi-assembly situations in more complex situations it would be more useful.&lt;/p&gt;  &lt;h4&gt;CQL Queries and Constraints&lt;/h4&gt;  &lt;p&gt;&lt;img alt="CQL Queries and Constraints Section" src="http://farm2.static.flickr.com/1280/4706015150_b1754b8612_b.jpg" width="702" height="372" /&gt;&lt;/p&gt;  &lt;p&gt;At the top of this section, a colour-coded list is provided. For my assembly, eight constraints are green (pass) and nine are yellow (warning). I assume that items also can be coloured red (fail) but that my assembly doesn’t warrant it.&lt;/p&gt;  &lt;h5&gt;{Code Quality \ Type Metrics}&lt;/h5&gt;  &lt;p&gt;&lt;img alt="CQL Constraint {Code Quality - Type Metrics}" src="http://farm2.static.flickr.com/1302/4705490713_aae16e53d4_o.png" width="877" height="517" /&gt;&lt;/p&gt;  &lt;p&gt;Three classes have warnings: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;c&gt;Resources&lt;/c&gt;: this warning is due to the tool not ignoring classes marked as &lt;c&gt;&lt;a title="GeneratedCodeAttribute Class" href="http://msdn.microsoft.com/library/system.codedom.compiler.generatedcodeattribute" rel="nofollow"&gt;[GeneratedCode]&lt;/a&gt;&lt;/c&gt;. &lt;/li&gt;    &lt;li&gt;&lt;c&gt;PropertyExpectations&amp;lt;T&amp;gt;&lt;/c&gt; and &lt;c&gt;TypeExpectations&amp;lt;T&amp;gt;&lt;/c&gt;: these are my two &lt;a title="Implementing an Internal DSL" href="http://martinfowler.com/dslwip/InternalOverview.html" rel="nofollow"&gt;internal &lt;acronym title="Domain Specific Language"&gt;DSL&lt;/acronym&gt;&lt;/a&gt;s, so it's not a surprise that they have a large number of methods as I have employed &lt;a title="Method Chaining" href="http://martinfowler.com/dslwip/MethodChaining.html" rel="nofollow"&gt;method chaining&lt;/a&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;{Design}&lt;/h5&gt;  &lt;p&gt;&lt;img alt="CQL Constraint {Design}" src="http://farm5.static.flickr.com/4008/4705541507_831d5926e9_o.png" width="759" height="418" /&gt;&lt;/p&gt;  &lt;p&gt;This isn’t especially informative so I swapped over to the application and looked at the Dependency Matrix:&lt;/p&gt;  &lt;p&gt;&lt;a title="Dependency Matrix - # namespaces" href="http://www.flickr.com/photos/alan-dean/4706202622/"&gt;&lt;img alt="Dependency Matrix - # namespaces" src="http://farm2.static.flickr.com/1301/4706202622_3490918c17_m.jpg" width="240" height="205" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Browsing through this matrix indicates that the constraint failed due to the method chaining implementation of the internal DSL. As an observation, I should say that method chaining does indeed lead to less maintainable code as changing the decision flow is non-trivial but here is an example of deliberately accepting a burden in order to achieve an objective.&lt;/p&gt;  &lt;p&gt;There are a bunch of other constraints reported on but I think that you get the picture. Time to have a look at the application in a little more detail.&lt;/p&gt;  &lt;h4&gt;CQL Query Explorer&lt;/h4&gt;  &lt;p&gt;I’m going to take a trivial example to illustrate usage. At the bottom of the application screen there is an explorer-style listing of the CQL report information, colour-coded as in the report. I have selected &lt;em&gt;Abstract base classes should be suffixed with ‘Base’&lt;/em&gt; from the &lt;em&gt;Naming Conventions&lt;/em&gt; node. When I do so, the relevant classes are highlighted in blue in the map above. When I hover my mouse over a highlighted class it changes to a pink highlight and the tooltip window on the right displays CQL information about that class. It all feel very slick and responsive. In this particular case, I have no objection to renaming the two classes with a suffix of ‘Base’ so I have gone ahead and made that change.&lt;/p&gt;  &lt;p&gt;&lt;a title="CQL Query Explorer" href="http://www.flickr.com/photos/alan-dean/4706260392/"&gt;&lt;img alt="CQL Query Explorer" src="http://farm5.static.flickr.com/4005/4706260392_498401f187.jpg" width="500" height="305" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Conclusion&lt;/h4&gt;  &lt;p&gt;NDepend is clearly a powerful tool and I can see myself finding it useful in future projects but it is clearly an expert tool, best employed by those already comfortable with static analysis or as a means for self-education. It isn’t a ‘must-have’ tool. What would make it so, for me, would be to have the same type of Visual Studio integration as Code Analysis and Source Analysis do. I like being able to configure the static analysis at project inception, having warnings and errors emitted during build. This feels very natural to me and having to leave the IDE simply means that I’m far less likely to utilise the tool.&lt;/p&gt;  &lt;p&gt;&lt;ins darerime="2010-06-16T21:44"&gt;[Update] I should make clear that NDepend &lt;a title="NDepend Feature Tour" href="http://www.ndepend.com/Features.aspx#Tour" rel="nofollow"&gt;does integrate with Visual Studio&lt;/a&gt;. In the text above I am specifically referring to the build warning / error integration that both Code Analysis and Source Analysis provide. This means that as soon as you write the code, you will discover if you have caused an analysis issue. I am a firm believer that raising issues as soon as you write the code makes writing clean code a cheaper proposition.&lt;/ins&gt;&lt;/p&gt;  </description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="http://farm5.static.flickr.com/4031/4705400553_b5641b0e57_t.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Cavity Unit Testing</title><link>http://alandean.blogspot.com/2010/06/cavity-unit-testing.html</link><category>Cavity</category><category>TDD</category><pubDate>Tue, 15 Jun 2010 13:34:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-7177283052937982253</guid><description>&lt;p&gt;I have started a new open source project on google code which I've named &lt;i&gt;Cavity&lt;/i&gt; for no particular reason other than it's somewhat memorable: &lt;a href="http://code.google.com/p/cavity/" rel="bookmark" title="Cavity"&gt;http://code.google.com/p/cavity/&lt;/a&gt; and I plan on pushing up some of the code I use to accelerate and assist development, starting with an &lt;a href="http://martinfowler.com/dslwip/InternalOverview.html" rel="nofollow" title="Implementing an Internal DSL"&gt;internal DSL&lt;/a&gt; for unit testing type and property definitions.&lt;/p&gt;&lt;p&gt;I’ve been doing &lt;a href="http://www.c2.com/cgi/wiki?TestDrivenDevelopment" rel="nofollow" title="Test Driven Development"&gt;&lt;acronym title="Test Driven Development"&gt;TDD&lt;/acronym&gt;&lt;/a&gt; for about 9 years now and have, I admit, derived a somewhat idiosyncratic style which involves asserting all of the external characteristics of a type. I don’t agree with those who argue in favour of not testing properties (I disagree because properties have behaviour and thus ought to be verifiable). I also believe that interface implementations and attribute decorations should be verifiable (which also speaks to my belief in what I call &lt;i&gt;intentional development&lt;/i&gt;). However there is a downside to this, which is that asserting type and property definitions is slower than not doing so (obviously) and so I use my unit test DSL to accelerate the process and thus mitigate the impedance. This has been living inside the &lt;a href="http://code.google.com/p/simplewebservices/" rel="nofollow" title="Simple Web Services"&gt;SimpleWebServices&lt;/a&gt; project for a while now but I thought it was time to promote it to a more formal offering and so it is the first library available from Cavity.&lt;/p&gt;&lt;p&gt;To give you a flavour, here are a couple of examples of testing a class and a property:&lt;/p&gt;&lt;p&gt;&lt;pre class="brush: csharp"&gt;[Fact]
public void type_definition()
{
    Assert.True(new TypeExpectations&amp;lt;Class1&amp;gt;()
        .DerivesFrom&amp;lt;object&amp;gt;()
        .IsConcreteClass()
        .IsUnsealed()
        .HasDefaultConstructor()
        .Implements&amp;lt;IFoo&amp;gt;()
        .IsDecoratedWith&amp;lt;CustomAttribute&amp;gt;()
        .Result);
}

[Fact]
public void value_definition()
{
    Assert.True(new PropertyExpectations&amp;lt;Class1&amp;gt;("Value")
        .TypeIs&amp;lt;string&amp;gt;()
        .DefaultValueIs("default")
        .Set("example")
        .ArgumentNullException()
        .ArgumentOutOfRangeException(string.Empty)
        .FormatException("invalid")
        .IsNotDecorated()
        .Result);
}
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;The binaries and source are &lt;a href="http://code.google.com/p/cavity/downloads/list" rel="nofollow" title="Cavity Downloads"&gt;zipped for download&lt;/a&gt; and to see more examples, please visit the wiki:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/cavity/wiki/TypeExpectations" rel="bookmark" title="TypeExpectations&amp;lt;T&amp;gt;"&gt;TypeExpectations&amp;lt;T&amp;gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/cavity/wiki/PropertyExpectations" rel="bookmark" title="PropertyExpectations"&gt;PropertyExpectations&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>What would a rational constitutional settlement look like?</title><link>http://alandean.blogspot.com/2010/04/would-would-rational-constitutional.html</link><category>Politics</category><pubDate>Sun, 18 Apr 2010 08:45:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-2956019575466418550</guid><description>&lt;p&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="Rational Constitutional Settlement" border="0" alt="A diagram of a rational constitutional settlemt" align="right" src="http://farm5.static.flickr.com/4061/4531473872_78fa6d98a6_o.png" width="573" height="646" /&gt;With the &lt;a title="UK General Election 2010" href="http://news.bbc.co.uk/1/hi/uk_politics/election_2010/default.stm" rel="nofollow"&gt;General Election&lt;/a&gt; campaign in full flood, I’ve been thinking about what a rational constitutional settlement for the &lt;acronym title="United Kingdom"&gt;UK&lt;/acronym&gt; might look like. The current settlement, whereby Scotland, Wales and Northern Ireland have &lt;a title="Devolved government in the UK" href="http://www.direct.gov.uk/en/Governmentcitizensandrights/UKgovernment/Devolvedgovernment/DG_073306" rel="nofollow"&gt;devolved government&lt;/a&gt; but England does not is causing a certain amount of constitutional stress and this is likely to increase in the coming years. English voters are becoming alienated by &lt;acronym title="Member of Parliament"&gt;MP&lt;/acronym&gt;s who represent areas with devolved powers still being able to vote for policies that do not affect their own constituents. If we get a &lt;a title="hung parliament" href="http://wikipedia.org/wiki/Hung_parliament" rel="nofollow"&gt;hung parliament&lt;/a&gt; from this election, but there is a majority party in England then I expect to hear a great deal of commentary about a caretaker government being sustained in power without legitimacy.&lt;/p&gt;&lt;p&gt;Rolling back devolution at this point is not a realistic proposition; that horse has left the stable. Given that political reality, how might we organise our &lt;a title="representative democracy" href="http://wikipedia.org/wiki/Representative_democracy" rel="nofollow"&gt;representative democracy&lt;/a&gt;? I am deliberately excluding &lt;a title="Republicanism in the United Kingdom" href="http://wikipedia.org/wiki/Republicanism_in_the_United_Kingdom" rel="nofollow"&gt;republicanism&lt;/a&gt; from this discussion. If you are in favour of keeping a &lt;a title="Monarchy of the United Kingdom" href="http://wikipedia.org/wiki/Monarchy_of_the_United_Kingdom" rel="nofollow"&gt;monarch&lt;/a&gt;, simply imagine a world where our arrangements for &lt;a title="Head of State" href="http://wikipedia.org/wiki/Head_of_State" rel="nofollow"&gt;Head of State&lt;/a&gt; are unchanged. If you are not, then imagine a world where an elected Head of State exercises broadly the &lt;a title="Constitutional monarchy" href="http://wikipedia.org/wiki/Constitutional_monarchy" rel="nofollow"&gt;same set of functions as the monarch currently does&lt;/a&gt;. Similarly, I am ignoring the question of the voting system(s) to be employed. Clearly, the voting system and seat distribution would have a profound &lt;em&gt;political&lt;/em&gt; impact but my proposition stands as a constitutional model regardless of voting system, be it &lt;a title="Proportional representation" href="http://wikipedia.org/wiki/Proportional_representation" rel="nofollow"&gt;proportional&lt;/a&gt; or not.&lt;/p&gt;&lt;p&gt;The primary consideration I have employed to build this model is fairness as accountability is a much more difficult metric to measure. I simply ask &lt;q&gt;would voters consider this model to be fair to all the other voters in the UK?&lt;/q&gt;. The secondary consideration is simplicity. I have tried to come up with a model that a voter can comprehend easily and that they know who to blame or acclaim when deciding how to vote.&lt;/p&gt;&lt;h4&gt;Local Councils&lt;/h4&gt;&lt;p&gt;My proposal does not change the constitutional role of &lt;a title="Local government in the UK" href="http://wikipedia.org/wiki/Local_government#United_Kingdom" rel="nofollow"&gt;local government&lt;/a&gt;, nor does it alter the current organisation of local government. However, my model devolves such decisions and local government funding entirely to the &lt;em&gt;Regional Assemblies&lt;/em&gt; (see below).&lt;/p&gt;&lt;h4&gt;Regional Assemblies&lt;/h4&gt;&lt;p&gt;In this constitutional model, each constituent country in the UK (England, Scotland, Wales and Northern Ireland) would have an assembly (I use the term generically, it does not imply that the &lt;a title="Scottish Parliament" href="http://wikipedia.org/wiki/Scottish_parliament" rel="nofollow"&gt;Scottish Parliament&lt;/a&gt; needs to be renamed).&amp;#160; The current model applied to Scotland would be applied equally to all of the other assemblies; that is to say that certain powers would be reserved to the UK Parliament (see below) and all powers not explicitly reserved become the responsibility of the regional assemblies within their geographic limits. At this point I am not going to enumerate the reserved powers: it is sufficient to say that there will be some and I envisage that they will likely be broadly in line with current Scottish arrangements. As is the case at present, each region would have an executive which is comprised of assembly members. Regional assemblies would be &lt;a title="Unicameralism" href="http://wikipedia.org/wiki/Unicameral" rel="nofollow"&gt;unicameral&lt;/a&gt; (i.e. they would have only one chamber). As to the question of where a new English Parliament might be based: I leave that up to you to discuss in the comments! I envisage that an English Parliament might comprise as many as 300 members, with a similar or greater reduction in the number of UK Parliamentarians (see below).&lt;/p&gt;&lt;h4&gt;UK Parliament&lt;/h4&gt;&lt;p&gt;The most significant changes in my model arise at the national level. With a devolved English Parliament, the structure of national government would need to change dramatically. I propose to keep the current &lt;a title="Bicameralism" href="http://wikipedia.org/wiki/Bicameral" rel="nofollow"&gt;bicameral&lt;/a&gt; model at &lt;a title="Parliament of the United Kingdom" href="http://wikipedia.org/wiki/Parliament_of_the_United_Kingdom" rel="nofollow"&gt;Westminster&lt;/a&gt;, with an elected lower house and a revising upper house.&lt;/p&gt;&lt;h5&gt;Federal Chamber (Upper House)&lt;/h5&gt;&lt;p&gt;I propose that the current membership of the &lt;a title="House of Lords" href="http://wikipedia.org/wiki/House_of_lords" rel="nofollow"&gt;House of Lords&lt;/a&gt; should be replaced with a federal membership. The new Federal Chamber would have 100 seats, like the &lt;a title="United States Senate" href="http://wikipedia.org/wiki/Us_senate" rel="nofollow"&gt;US Senate&lt;/a&gt;, with seats apportioned to each region by population recorded at the &lt;a title="Census in the United Kingdom" href="http://wikipedia.org/wiki/UK_census" rel="nofollow"&gt;dicennial census&lt;/a&gt;. The seat proportions would approximately be: England 81, Scotland 10, Wales 6, Northern Ireland 3. The primary role of the Federal Chamber would be to revise legislation as the current House of Lords does. The restrictions that currently apply to the House of Lords would be maintained to ensure that the elected chamber would retains primacy (the &lt;a title="House of Lords - Legislative functions" href="http://wikipedia.org/wiki/House_of_Lords#Legislative_functions" rel="nofollow"&gt;Parliament Acts&lt;/a&gt; and the &lt;a title="Salisbury Convention" href="http://wikipedia.org/wiki/Salisbury_Convention" rel="nofollow"&gt;Salisbury Convention&lt;/a&gt;). Members from each region would be selected from the elected Regional Assembly members. Members of the Federal Chamber would not be permitted to take a position in the UK Government, unlike the current House of Lords.&lt;/p&gt;&lt;h5&gt;Elected Chamber (Lower House)&lt;/h5&gt;&lt;p&gt;The elected chamber would be the primary &lt;a title="Legislature" href="http://wikipedia.org/wiki/Legislature" rel="nofollow"&gt;legislature&lt;/a&gt; of the UK, just as the current &lt;a title="House of Commons" href="http://wikipedia.org/wiki/House_of_commons" rel="nofollow"&gt;House of Commons&lt;/a&gt; is. Given the introduction of an English Parliament, the elected chamber would not need to be anything like as large as the current House of Commons due to the devolution of powers. I suspect that perhaps as few as 200 members would be sufficient. The arrangement of constituencies would depend upon the voting system employed. All Ministers of the UK Government would be required to have seats in the elected chamber.&lt;/p&gt;&lt;h4&gt;European Union&lt;/h4&gt;&lt;p&gt;I have long thought that one of the weaknesses in our current constitutional settlement is the poor integration of our institutions with those of the &lt;acronym title="European Union"&gt;EU&lt;/acronym&gt;. Here is my perspective on how that might be improved.&lt;/p&gt;&lt;h5&gt;European Commission, Consilium and Council&lt;/h5&gt;&lt;p&gt;These bodies are defined by the &lt;a title="Treaty of Lisbon" href="http://wikipedia.org/wiki/Lisbon_treaty" rel="nofollow"&gt;Lisbon Treaty&lt;/a&gt; and are somewhat integrated with the UK Government already (although the actual interplay between them is rather murky) but I don’t propose significant changes as Ministers would remain accountable to Parliament.&lt;/p&gt;&lt;h5&gt;European Parliament&lt;/h5&gt;&lt;p&gt;I would make a very real change regarding the &lt;a title="European Parliament" href="http://wikipedia.org/wiki/European_Parliament" rel="nofollow"&gt;European Parliament&lt;/a&gt;. Currently, despite the Parliament gaining rather more power from the Lisbon Treaty, voting for it tends to be regarded as a protest opportunity (both in the UK and elsewhere in Europe). I would change this by having all British &lt;acronym title="Member of the European Parliament"&gt;MEP&lt;/acronym&gt;s be elected via the UK Parliament. The exact mechanics of this election process would be subject to the electoral system decided up for the UK Parliament but the key point is that our MEPs would sit in our national Parliament and be accountable through it, rather than being divorced from normal national politics as they mostly are right now.&lt;/p&gt;&lt;h4&gt;Fiscal Policy&lt;/h4&gt;&lt;p&gt;These changes to our constitutional settlement would necessitate a clearer separation of responsibilities between the layers of government than currently exists (a good thing, in my opinion). One area in particular, fiscal policy, deserves special consideration as it is the lifeblood of all government. I propose that UK taxation would be explicitly split between the UK Parliament and the Regional Assemblies. The UK Parliament would set a base level of taxation (income, &lt;acronym title="Value Added Tax"&gt;VAT&lt;/acronym&gt;, Duties and Excise) to pay for the reserved powers such as defence. On top of that, each Regional Assembly would levy regional taxation. This would mean that on your pay slip you would see two sets of income tax amounts. The base level of VAT would continue to include the proportion that flows to the EU. This way, voters in each region can elect representatives with high or low tax and spend manifestos without the effects being hidden as is currently the case. However, the &lt;a title="Barnett Formula" href="http://wikipedia.org/wiki/Barnett_Formula" rel="nofollow"&gt;Barnett Formula&lt;/a&gt; exists for a reason. Although there are many arguments about what the correct amount of fiscal transfer should be, these are properly a matter for budgetary votes in the UK Parliament. Any amounts of fiscal transfer voted for would form part of the base taxation level at a national level as it would be iniquitous, for example, to force an English Parliament to levy a direct transfer. Borrowing and the National Debt would remain a sovereign, reserved, power of the UK Parliament as it is now with interest and capital repayments forming part of the base national taxation level. &lt;ins&gt;Update: I envisage local and corporate taxation being devolved to the regions.&lt;/ins&gt;&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;I appreciate that much of what I have set out above will be considered radical, possibly even unworkable, but I ask that you consider if we are at a point where we ought to embrace radicalism in order to lay down strong democratic foundations for a form of politics that is fit for our future and I accordingly commend this proposal to you.&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Spoofing my TabletPC as an iPad</title><link>http://alandean.blogspot.com/2010/04/spoofing-my-tabletpc-as-ipad.html</link><category>Win7</category><pubDate>Sat, 10 Apr 2010 08:07:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-327639470077396418</guid><description>&lt;p&gt;&lt;a title="TabletPC Desktop" href="http://www.flickr.com/photos/alan-dean/4507893688/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TabletPC Desktop" border="0" alt="TabletPC Desktop" align="right" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUGZ3BJLI/AAAAAAAAApI/rILghYqMueM/4507893688_741b4aaf21_m%5B1%5D%5B5%5D.jpg?imgmax=800" width="244" height="154" /&gt;&lt;/a&gt;Hot on the heels of the release of the &lt;a title="Apple iPad" href="http://apple.com/ipad/" rel="nofollow"&gt;iPad&lt;/a&gt;, I decided to repave my &lt;a title="TabletPC - Wikipedia" href="http://wikipedia.org/wiki/Tablet_PC" rel="nofollow"&gt;TabletPC&lt;/a&gt; (an &lt;a title="HP TX2520EA Reviews: Windows Vista Home Premium 12.1&amp;quot; Screen Laptop computer" href="http://www.reevoo.com/p/hp-tx2520ea" rel="nofollow"&gt;HP TX2520ea&lt;/a&gt;) with a fresh install of &lt;a title="Windows 7: Your PC, simplified" href="http://microsoft.com/windows/windows-7/" rel="nofollow"&gt;Windows 7&lt;/a&gt;. I haven’t been making real use of the tablet for about a year now as I have been highly development focussed and less managerial but it was time to upgrade from Vista.&lt;/p&gt;  &lt;p&gt;I did have a quick look at some &lt;em&gt;&lt;a title="Search for iPad Ready" href="http://google.com/search?q=ipad+ready" rel="nofollow"&gt;iPad-ready&lt;/a&gt;&lt;/em&gt; websites using Safari and &lt;a title="How to Change and Spoof Safari User-Agent String" href="http://www.mydigitallife.info/2010/01/27/how-to-change-and-spoof-safari-user-agent-string/" rel="bookmark"&gt;spoofing the browser User Agent as an iPad&lt;/a&gt; but the configuration steps are clunky and need to be carried out each time you create a new Safari instance.&lt;/p&gt;  &lt;p&gt;&lt;a title="RocketDock Icon Settings" href="http://www.flickr.com/photos/alan-dean/4507342253/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="RocketDock Icon Settings" border="0" alt="RocketDock Icon Settings" align="left" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUGn98SJI/AAAAAAAAApM/2dLWDrKY7ko/4507342253_8b308c4d49_t%5B1%5D%5B4%5D.jpg?imgmax=800" width="104" height="97" /&gt;&lt;/a&gt; Then yesterday I read “&lt;a title="Use Gmail for iPad in Google Chrome" href="http://googlesystem.blogspot.com/2010/04/use-gmail-for-ipad-in-google-chrome.html" rel="bookmark"&gt;Use Gmail for iPad in Google Chrome&lt;/a&gt;” which shows how to easily open &lt;a title="Google Chrome" href="http://google.com/chrome" rel="nofollow"&gt;Chrome&lt;/a&gt; with spoofing enabled and a brainwave came to me. I use &lt;a title="RocketDock" href="http://rocketdock.com" rel="bookmark"&gt;RocketDock&lt;/a&gt; (an excellent application launcher for Windows which emulates the &lt;a title="Mac 101: The Dock" href="http://support.apple.com/kb/HT2474" rel="nofollow"&gt;Apple Dock&lt;/a&gt;) and I realised that it would be easy to configure docked shortcuts for spoofing.&lt;/p&gt;  &lt;p&gt;You simply create a new docked shortcut to &lt;em&gt;chrome.exe&lt;/em&gt; and configure the arguments, setting the desired app URI:&lt;/p&gt;  &lt;pre&gt;&lt;small&gt;--app=&amp;quot;http://www.example.com&amp;quot; --user-agent=&amp;quot;Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10&amp;quot;&lt;/small&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So far there aren’t a large number of sites which are iPad-ready but there are enough to make a difference to my TabletPC experience, especially as I am a heavy Google Apps user and significant work has been done by Goole on their properties to better support the iPad (it would have been nicer if they had already done this work for Windows 7 Touch devices, but there we are). Here is a selection of screenshots of Google Apps spoofed as an iPad:&lt;/p&gt;&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;Mail&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Mail" href="http://www.flickr.com/photos/alan-dean/4507892550/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Mail" border="0" alt="Google Mail" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUHO4i9rI/AAAAAAAAApQ/7h417rQfjFI/4507892550_f42169564f_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="104" height="86" /&gt;&lt;/a&gt;&amp;#160;&lt;a title="Google Mail" href="http://www.flickr.com/photos/alan-dean/4507255177/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Mail" border="0" alt="Google Mail" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUHv4bWzI/AAAAAAAAApU/2nyfuq7iAkM/4507255177_dbb9424563_m%5B1%5D%5B3%5D.jpg?imgmax=800" width="244" height="167" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Docs&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Docs (Folders)" href="http://www.flickr.com/photos/alan-dean/4507254483/sizes/o/" rel="bookmark"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Google Docs (Folders)" border="0" alt="Google Docs (Folders)" src="http://lh4.ggpht.com/_K3SGqsLdA04/S8CUIFcHFEI/AAAAAAAAAqY/0J_Wm5LhuAY/4507254483_58a6d44554_t%5B1%5D%5B4%5D.jpg?imgmax=800" width="102" height="104" /&gt;&lt;/a&gt; &lt;a title="Google Docs" href="http://www.flickr.com/photos/alan-dean/4507892888/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Docs" border="0" alt="Google Docs" src="http://lh4.ggpht.com/_K3SGqsLdA04/S8CUIVASFVI/AAAAAAAAApc/ez-Z0JbpWkI/4507892888_91bccca04e_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="84" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Calendar&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Calendar" href="http://www.flickr.com/photos/alan-dean/4507892760/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Calendar" border="0" alt="Google Calendar" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUI_XiXJI/AAAAAAAAApg/9F4T_q91mSk/4507892760_4172a1a151_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="69" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Tasks&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Tasks" href="http://www.flickr.com/photos/alan-dean/4507255431/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Tasks" border="0" alt="Google Tasks" src="http://lh5.ggpht.com/_K3SGqsLdA04/S8CUJOZcJ9I/AAAAAAAAApk/VcQFXGkcHfo/4507255431_df4d30d6da_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="79" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here are some other Google sites:&lt;/p&gt;&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;Mobile &lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Mobile" href="http://www.flickr.com/photos/alan-dean/4507892940/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Mobile" border="0" alt="Google Mobile" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUJvj3mgI/AAAAAAAAApo/ycpp2Ei5tGg/4507892940_415ca194ff_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="75" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Search &lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Search" href="http://www.flickr.com/photos/alan-dean/4507892414/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Search" border="0" alt="Google Search" src="http://lh4.ggpht.com/_K3SGqsLdA04/S8CUJ3qMZcI/AAAAAAAAAps/DVdf8inklhE/4507892414_35cc1ab388_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="63" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Reader&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Reader" href="http://www.flickr.com/photos/alan-dean/4507892484/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Reader" border="0" alt="Google Reader" src="http://lh5.ggpht.com/_K3SGqsLdA04/S8CUKQC7fQI/AAAAAAAAApw/h16oWCyV-AE/4507892484_7c6b0a2c4e_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="70" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;News&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google News" href="http://www.flickr.com/photos/alan-dean/4507892614/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google News" border="0" alt="Google News" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUKmdDciI/AAAAAAAAAp0/HdEPdHK2kOU/4507892614_cfdcb71ce0_t%5B1%5D%5B4%5D.jpg?imgmax=800" width="98" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Buzz&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Buzz" href="http://www.flickr.com/photos/alan-dean/4507893196/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Buzz" border="0" alt="Google Buzz" src="http://lh4.ggpht.com/_K3SGqsLdA04/S8CULgCt11I/AAAAAAAAAp4/txaKQuRFRwE/4507893196_c2f4c4261b_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="93" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Talk&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Talk" href="http://www.flickr.com/photos/alan-dean/4507255379/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Talk" border="0" alt="Google Talk" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUL9v7ajI/AAAAAAAAAp8/l8Wad4pjdVg/4507255379_7153ba6c1d_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="104" height="100" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Maps&lt;/dt&gt;&lt;dd&gt;&lt;a title="Google Maps" href="http://www.flickr.com/photos/alan-dean/4507254775/sizes/o/" rel="bookmarks"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Google Maps" border="0" alt="Google Maps" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUMByCKdI/AAAAAAAAAqA/_AwLxff8KUA/4507254775_0f9cd0b7bc_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="75" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;YouTube&lt;/dt&gt;&lt;dd&gt;&lt;a title="YouTube" href="http://www.flickr.com/photos/alan-dean/4507892694/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="YouTube" border="0" alt="YouTube" src="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUMrAwCwI/AAAAAAAAAqE/Ue_S82tTsk0/4507892694_ff0e49bd9e_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="74" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Finally, here are some other iPad-Ready sites:&lt;/p&gt;&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;Twitter&lt;/dt&gt;&lt;dd&gt;&lt;a title="Twitter" href="http://www.flickr.com/photos/alan-dean/4507254893/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Twitter" border="0" alt="Twitter" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUM6yKH7I/AAAAAAAAAqI/hLd3wfcP2hk/4507254893_84518873f8_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="102" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Facebook&lt;/dt&gt;&lt;dd&gt;&lt;a title="Facebook" href="http://www.flickr.com/photos/alan-dean/4507893350/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Facebook" border="0" alt="Facebook" src="http://lh5.ggpht.com/_K3SGqsLdA04/S8CUNthKaeI/AAAAAAAAAqM/b7S7JaYdERo/4507893350_3c61a13919_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="97" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;Delicious&lt;/dt&gt;&lt;dd&gt;&lt;a title="Delicious" href="http://www.flickr.com/photos/alan-dean/4507893484/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Delicious" border="0" alt="Delicious" src="http://lh6.ggpht.com/_K3SGqsLdA04/S8CUOAG96RI/AAAAAAAAAqQ/OlTB2VxGjHk/4507893484_50cf2fe636_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="54" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;BBC iPlayer&lt;/dt&gt;&lt;dd&gt;&lt;a title="BBC iPlayer" href="http://www.flickr.com/photos/alan-dean/4507893412/sizes/o/" rel="bookmark"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="BBC iPlayer" border="0" alt="BBC iPlayer" src="http://lh4.ggpht.com/_K3SGqsLdA04/S8CUOnKx-jI/AAAAAAAAAqU/DZ-OljidMaU/4507893412_6fe7be6d6c_t%5B1%5D%5B3%5D.jpg?imgmax=800" width="82" height="104" /&gt;&lt;/a&gt; &lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Of course, you can’t run &lt;a title="Apps for iPad" href="http://www.apple.com/ipad/apps-for-ipad/" rel="nofollow"&gt;iPad Apps&lt;/a&gt; on Windows 7 but the rush to roll-out tablet-style websites that look good on the iPad will coincidentally benefit TabletPC owners like me and that makes me happy.&lt;/p&gt;  </description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="http://lh3.ggpht.com/_K3SGqsLdA04/S8CUGZ3BJLI/AAAAAAAAApI/rILghYqMueM/s72-c/4507893688_741b4aaf21_m%5B1%5D%5B5%5D.jpg?imgmax=800" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Agility is not Viral</title><link>http://alandean.blogspot.com/2010/04/agility-is-not-viral.html</link><category>Agile</category><pubDate>Thu, 8 Apr 2010 04:28:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-8218004026628062365</guid><description>&lt;p&gt;&lt;em&gt;Please note: This post was originally published on my Charteris blog in 2008 but is no longer accessible so I’m republishing it here as I feel it remains important.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.slideshare.net/alan.dean/future-direction-for-agile-presentation/"&gt;&lt;img style="margin: 0px 5px 0px 0px" alt="" align="left" src="http://farm4.static.flickr.com/3148/2930557467_3848729f6e_o.png" /&gt;&lt;/a&gt;At Charteris Day this week, we had a series of presentations discussing Agility. The various speakers covered both Business Consultancy (with a focus on our '&lt;a href="http://www.charteris.com/what_we_do/customer_centricity/"&gt;Customer Centricity&lt;/a&gt;' capability) and from the Technology Consultancy (with a focus on &lt;a href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;Agile software development&lt;/a&gt;). My contribution was to give a 20 minute talk explaining why I felt that the presentation (&amp;quot;&lt;a href="http://www.infoq.com/presentations/Agile-Directions-David-Anderson"&gt;Future Directions for Agile&lt;/a&gt;&amp;quot;) by &lt;a href="http://www.agilemanagement.net/"&gt;David Anderson&lt;/a&gt; at &lt;a href="http://www.agile2008.org/"&gt;Agile 2008&lt;/a&gt; in August was so important.&lt;/p&gt;&lt;p&gt;At the head of my presentation I discussed something that I have been articulating for some time now (&lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/10/10/on-project-learning.aspx"&gt;including during the Park Bench session at the Alt.Net Conference&lt;/a&gt;) and I thought it would be worth repeating here to see if others agree with me or not.&lt;/p&gt;&lt;p&gt;First, a little background. During the late 90's I was developing shrinkwrap software using &lt;a href="http://en.wikipedia.org/wiki/Rapid_application_development"&gt;RAD&lt;/a&gt;. Whilst I was working for the &lt;a href="http://www.ivisgroup.com/"&gt;IVIS Group&lt;/a&gt; on &lt;a href="http://www.tesco.com/"&gt;Tesco.com&lt;/a&gt; in 2002, I was introduced to &lt;a href="http://en.wikipedia.org/wiki/Extreme_programming"&gt;eXtreme Programming&lt;/a&gt;. Since that time I have considered myself an extreme programmer, rather than an Agilist (for various reasons that I won't bore you with right now) and have acted as an agent of change at a number of organisations.&lt;/p&gt;&lt;p&gt;In hindsight, I think that at the beginning of the Millennium we genuinely believed that our principles and practices would prove to be &lt;a href="http://en.wikipedia.org/wiki/Viral_phenomenon"&gt;viral&lt;/a&gt; and that the &lt;a href="http://en.wikipedia.org/wiki/Meme"&gt;meme&lt;/a&gt; would spread. After all, we could demonstrate how effective the practices were. We could measure productivity and velocity in a far more transparent manner than&amp;#160; hitherto. The team members felt more empowered and gained more satisfaction from their work. Sponsors felt that, often for the first time, that they actually knew what their development staff were doing and how well. Sponsors especially appreciated the visibility of functional gain and the ability to direct the functional implementation. These characteristics were (and still are) real. It is not an illusion.&lt;/p&gt;&lt;p&gt;&lt;img alt="" align="right" src="http://www.agilealliance.org/system/public_resource/file/89/Agile-logo-4c-sm.jpg" /&gt;Given the reality of these powerful advantages, how could it not be viral? Why would the meme not spread? Yet it has not. At least, it has not in the way that we envisaged.&lt;/p&gt;&lt;p&gt;It is true that the term Agile Development has gained wide currency now, although perhaps not wide understanding. Many, possibly a majority, of development teams aspire to be Agile. It is also true that there are more agile teams now than there were. My observation about a lack of &lt;a href="http://www.google.co.uk/search?q=define:virality"&gt;virality&lt;/a&gt; is separate to this.&lt;/p&gt;&lt;p&gt;So what do I mean? Over the years, I have engaged with a number of teams to, amongst other objectives, bring in Agile development practices; to act as an agent of change. To a greater or lesser extent, these engagements have proven successful and the teams grew demonstrably more Agile and effective. But then, the time comes to move on to the next engagement. After the departure of the agent of change, the team reverts to the &lt;a href="http://en.wikipedia.org/wiki/Status_quo_ante"&gt;status quo ante&lt;/a&gt;. Not immediately, but visibly and certainly. It isn't a deliberate, conscious decision to do so - it just happens, gradually. Six months or a year later, it is as if you had never been there.&lt;/p&gt;&lt;p&gt;Remember, this is a scenario where everyone was actually happier, more contented and fulfilled when they were Agile. Astonishing.&lt;/p&gt;&lt;p&gt;&lt;img style="margin: 0px 5px 0px 0px" alt="" align="left" src="http://farm4.static.flickr.com/3188/2931450594_345dcbef87_o.jpg" /&gt;There have been times when I have questioned my own ability to effect change because of this phenomenon. It was very refreshing to hear David Anderson articulate that he has encountered the same problems.&lt;/p&gt;&lt;p&gt;If we accept that Agility is not viral then we are bound to start asking the question: why?&lt;/p&gt;&lt;p&gt;I will start by saying that I have no potted answer to this question, I am still in the process of seeking to gain understanding, but my first candidate explanation is this: &lt;em&gt;&amp;quot;people are intrinsically lazy&amp;quot;&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Ouch. That sounds contentious! Well, it shouldn't be. After all, there is a reason why we prefer to buy labour-saving devices. There is a reason why people walk across the grass along the &lt;a href="http://en.wikipedia.org/wiki/Hypotenuse"&gt;hypotenuse of the triangle&lt;/a&gt;when the path follows the other two sides.&lt;/p&gt;&lt;p&gt;So why might laziness be an issue? I suspect it is because Agility is hard work. The practices we espouse are difficult and require us to work at a more challenging pace. Even if we feel better for doing it, it is easier not to do it. It is much the same as exercise. Why do gyms offer 'new joiner deals' in January? It is because they know full well that only a fraction of people will actually use their facilities all year and after the Christmas break people feel guilty about all that excess consumption.&lt;/p&gt;&lt;p&gt;Sponsors love the transparency of agile functional gain but it takes effort from them to achieve it. Sponsors are busy and in the absence of that agent of change hounding them to set aside time to contribute to the development process they start to miss meetings, they stop engaging fully with the development team and so agility is lost. The development team is just as guilty though. They too are busy people and it takes effort to ensure that the quality control practices are maintained. Knowing that the agent of change isn't around anymore to catch them out, they start cutting corners on their &lt;a href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;TDD&lt;/a&gt;. Before long, the team reverts to being less agile; possibly even entirely ceasing TDD for example.&lt;/p&gt;&lt;p&gt;The direction that David is taking in his talk is to look again at the &lt;a href="http://en.wikipedia.org/wiki/Capability_Maturity_Model"&gt;CMM&lt;/a&gt; and he certainly marshals some strong arguments. He also challenges some of our practices by asking if &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development"&gt;Lean&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Kanban"&gt;Kanban&lt;/a&gt; are Agile. I am not yet wholly sure that these are the right answers but he is certainly asking the right questions.&lt;/p&gt;&lt;p&gt;I have a feeling that perhaps we have historically had a very mechanistic view of people and process. Perhaps this is why we assumed that agility would be viral, because we assumed utility was inherently compelling. When I use the term 'we' here, I suppose that I am really talking about alpha geeks. The same people who naturally gravitated to extreme programming, agile and now to &lt;a href="http://altdotnet.org/"&gt;alt.net&lt;/a&gt;. This is why there are so many discussions about &amp;quot;is alt.net elite.net?&amp;quot; and so on. If so, we need to recognise that most people are not like us. Even most software developers, I suspect. We therefore face the very real challenge of &lt;em&gt;&lt;strong&gt;how to make agility sticky&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;My suspicion is that we need to become sociologists and learn how to &lt;a href="http://www.google.co.uk/search?q=define:enculture"&gt;enculture&lt;/a&gt; organisations with agility.&lt;img alt="" align="right" src="http://farm4.static.flickr.com/3172/2931478894_3a3d78f96c_o.jpg" /&gt;&lt;/p&gt;&lt;p&gt;I am very happy to say that I think that the agility presentations at Charteris Day look like they have succeeded in sparking the debate I believe is needed to grow our capability further as a consultancy; to better leverage the depth of knowledge in the company and to harness this for our clients. I'm sure that I will have more to say on this subject in the future.&lt;/p&gt;&lt;p&gt;&lt;img src="http://blogs.charteris.com/aggbug.aspx?PostID=633" width="1" height="1" /&gt;&lt;/p&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>2009 Alt.Net UK Conference Announced</title><link>http://alandean.blogspot.com/2009/05/2009-altnet-uk-conference-announced.html</link><pubDate>Mon, 11 May 2009 10:01:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-7035540869004942490</guid><description>&lt;p&gt;We are pleased to announce the &lt;a title="Alt.Net UK Conference 2009" href="http://www.altnetuk.com/" rel="bookmark"&gt;2009 Alt.Net Conference&lt;/a&gt;. &lt;a title="AltNetConf UK London August 2009" href="http://codebetter.com/blogs/ian_cooper/archive/2009/05/11/altnetconf-uk-london-august-2009.aspx" rel="bookmark"&gt;As Ian says&lt;/a&gt;, we tend to organise the Conference when the community feels ready for one and the time seems right again.&lt;/p&gt;  &lt;p&gt;This time, we are settings our sights a little higher and making a weekend of it by bringing together the Alt.Net Beers which &lt;a title="SerialSeb" href="http://serialseb.blogspot.com/" rel="bookmark"&gt;Seb&lt;/a&gt; runs, the &lt;a title="Open Space Coding Days in London" href="http://openspacecode.com/uk/london" rel="bookmark"&gt;Open Space Coding Day&lt;/a&gt; which I run and the Conference itself. Attendees will be able to register for one, two or all three events depending on availability. Registration will be open from 13:00 on Tuesday 12 May (tomorrow if you are reading this at the time of posting).&lt;/p&gt;  &lt;p&gt;Our thanks go to EMC Conchango for agreeing to host both the Saturday and Sunday events and also to TEQUILA\ for hosting the Alt.Net Beers on Friday. We would also like to thank our sponsors for giving us support during a time of constrained budgets.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Please note: the website is in the process of shifting DNS entries, so if you don’t see the new version at &lt;/em&gt;&lt;a href="http://altnetuk.com"&gt;&lt;em&gt;http://altnetuk.com&lt;/em&gt;&lt;/a&gt;&lt;em&gt; then try &lt;/em&gt;&lt;a href="http://www.altnetuk.com"&gt;&lt;em&gt;http://www.altnetuk.com&lt;/em&gt;&lt;/a&gt;&lt;em&gt; instead.&lt;/em&gt;&lt;/p&gt;  </description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Golden Hours</title><link>http://alandean.blogspot.com/2009/04/golden-hours.html</link><category>Agile</category><pubDate>Sun, 26 Apr 2009 05:52:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-4971820162361533510</guid><description>&lt;p&gt;&lt;a title="John Harrison&amp;#39;s H4 Watch" href="http://www.horology-stuff.com/watches/H4.html" rel="bookmark"&gt;&lt;img style="display: inline" align="right" src="http://farm4.static.flickr.com/3645/3475407805_0e7181fc47_m.jpg" /&gt;&lt;/a&gt; I quite often talk about “Golden Hours”. I employ the practice both at &lt;a title="moveme.com" href="http://www.moveme.com/" rel="bookmark"&gt;work&lt;/a&gt; and at the &lt;a title="Open Space Coding Days" href="http://openspacecode.com/home" rel="bookmark"&gt;Open Space Coding Days&lt;/a&gt;. However, I find that there are relatively few people who have heard of the practice – a fact that I find somewhat surprising given the huge amount of value that I find that it delivers. Although I can’t quite recall where I first heard of Golden Hours, I have been using the practice for about 6 years, on and off.&lt;/p&gt;&lt;h4&gt;Background&lt;/h4&gt;&lt;p&gt;There has been a great deal of research over the years into human concentration and productivity, much of which indicates that humans tend to concentrate in sprints. Furthermore, deep concentration seems to take time to achieve (typically at least 10 to 15 minutes) and is easily disrupted, &lt;a title="Human concentration study is reported" href="http://www.physorg.com/news78417842.html" rel="bookmark"&gt;especially by multiple stimuli&lt;/a&gt;. The optimum concentration period seems to be in the region of 100 minutes and few are able to maintain deep concentration beyond that.&lt;/p&gt;&lt;p&gt;In addition to the general research, there is a body of productivity studies (including a great deal on &lt;a title="Maximising Development Productivity" href="http://www.byte-vision.com/ProductivityArticle.aspx" rel="bookmark"&gt;developer productivity&lt;/a&gt;). Much of this indicates that, regardless of the number of hours actually worked, the vast bulk of productive coding time amounts to about 4 hours a day.&lt;/p&gt;&lt;p&gt;When discussing this with developers, I find that this generally fits with their personal experience.&lt;/p&gt;&lt;h4&gt;In Practice&lt;/h4&gt;&lt;p&gt;Essentially, Golden Hours takes the observations made above and simply embraces them.&lt;/p&gt;&lt;p&gt;What does it look like in practice? I follow a regime as follows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Golden Hours run from 10:00 to 12:00 and from 14:00 to 16:00.&lt;/li&gt;
&lt;li&gt;All preparatory work must be carried out prior to the Golden Hours: all investigations and all communications must be complete. Preparation is regarded as ‘done’ when the pair who will work together are satisfied that they have sufficient knowledge to code for 2 hours without interruption.&lt;/li&gt;
&lt;li&gt;During the assigned Golden Hours, the developers should close all communications: shut off IM, close their email application, mute their phones and so on.&lt;/li&gt;
&lt;li&gt;During the assigned Golden Hours, nobody is allowed to interrupt the developers unless there is an emergency. Fire alarms count, the live systems failing catastrophically also count. Not much else counts as an emergency. This includes the CEO, other senior management and any other stakeholders. It isn’t negotiable. In reality, there is very little that can’t wait for a maximum of 2 hours.&lt;/li&gt;
&lt;li&gt;Depending upon your environment, there may need to be a buffer to protect the developers. In some organisations, that may involve having 1st-line tech support. In others, you may need a assign the ‘bouncer’ role to someone.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I have found that 2 hours is an excellent unit of time to work with. You can thoroughly prepare for a 2 hour coding stint in a relatively short time (I find to 30 minutes preparation time is typically sufficient). It is a length of time that external stakeholders are usually happy to live with the developers going incommunicado. Just the need to thoroughly prepare is an excellent practice that minimises wheel-spinning. Once you have bedded-in Golden Hours, I have also found that it is a good unit of time for estimation purposes – along the lines of &lt;em&gt;“Assuming that you know everything that you need to know, how many golden hours do you estimate that this task / feature / story will take?”&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;You may find the response to the introduction of Golden Hours surprising. When I brought the practice into MoveMe, the product owner immediately asked &lt;em&gt;“Does this mean that developers can’t interrupt &lt;strong&gt;me&lt;/strong&gt; during this time either?”&lt;/em&gt; with a big smile of his face. An excellent reminder that being unprepared and disorganised is a disruption to others.&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="http://farm4.static.flickr.com/3645/3475407805_0e7181fc47_t.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Turning 40</title><link>http://alandean.blogspot.com/2009/03/turning-40.html</link><category>REST</category><pubDate>Mon, 9 Mar 2009 08:49:00 -0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-1014158280433051777</guid><description>&lt;p&gt;&lt;img style="display: inline; margin: 0px 5px 0px 0px" src="http://farm4.static.flickr.com/3622/3341757990_21ae9f4553_t.jpg" align="left" /&gt; This evening I am off to Coventry to give my “&lt;a title="Video of REST at DDD7" href="http://alandean.blogspot.com/2009/01/video-of-rest-at-ddd7.html" rel="bookmark"&gt;Separating REST Facts from Fallacies&lt;/a&gt;” talk at the &lt;a title="You are under a REST!" href="http://www.nxtgenug.net/ViewEvent.aspx?EventID=181" rel="nofollow"&gt;Coventry NxtGenUG&lt;/a&gt;, after which I will head up to Yorkshire as it is my 40th tomorrow. I don’t have anything in particular planned as I’m not big on birthdays, although I have treated myself to a new car (nothing fancy – just a Honda Jazz).&lt;/p&gt;  &lt;p&gt;It’s odd, the prospect of turning 40, in that I really don’t feel like I am. Having never married nor had children, perhaps I haven’t been through the life events that make someone feel 40. It’s my working conjecture to explain it. In any event, I’ll only been sporadically connected in the next couple of days.&lt;/p&gt;  </description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="http://farm4.static.flickr.com/3622/3341757990_21ae9f4553_t.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Environment Preparation for Book</title><link>http://alandean.blogspot.com/2009/03/environment-preparation-for-book.html</link><pubDate>Sun, 1 Mar 2009 04:32:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-1510454838892730435</guid><description>&lt;p&gt;Personally, I am a big fan of using Virtual PC for development as it makes changing between software versions so easy and allows easy switching between host machines. So, naturally, an important task in preparation for my book is to set up an image for the development. Here is my recipe:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a title="Windows Server 2008" href="http://www.microsoft.com/windowsserver2008" rel="nofollow"&gt;Windows Server 2008&lt;/a&gt; &lt;em&gt;(I could use Vista but I prefer to develop on a Server OS)&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;&lt;a title="Microsoft Visual Studio" href="http://www.microsoft.com/visualstudio" rel="nofollow"&gt;Microsoft Visual Studio 2008 Team System&lt;/a&gt;, including &lt;a title="SQL Server" href="http://www.microsoft.com/sqlserver" rel="nofollow"&gt;SQL Express 2005&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Ancillary Software     &lt;ul&gt;       &lt;li&gt;&lt;a title="Visual Studio 2008 Add-in Compatibility" href="http://www.csharper.net/blog/visual_studio_2008_add_in_compatibility.aspx" rel="nofollow"&gt;C# Shiznit&lt;/a&gt;          &lt;ul&gt;           &lt;li&gt;Explore In Windows for Visual Studio 2008&lt;/li&gt;            &lt;li&gt;MRU Cleaner for Visual Studio 2008&lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;&lt;a title="Google Chrome" href="http://www.google.com/chrome" rel="nofollow"&gt;Chrome&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="CopySourceAsHtml (CSAH)" href="http://www.jtleigh.com/CopySourceAsHtml" rel="nofollow"&gt;CopySourceAsHtml&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="Fiddler Web Debugger" href="http://www.fiddler2.com/" rel="nofollow"&gt;Fiddler&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="Firefox web browser" href="http://www.mozilla.com/firefox" rel="nofollow"&gt;Firefox&lt;/a&gt;          &lt;ul&gt;           &lt;li&gt;&lt;a title="Abduction! :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/3408" rel="nofollow"&gt;Abduction!&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="ColorZilla :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/271" rel="nofollow"&gt;ColorZilla&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Copy Plain Text Mozilla Extension by Jeremy Gillick" href="http://mozmonkey.com/copyplaintext/" rel="nofollow"&gt;Copy Plain Text&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="CSS Validator :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/2289" rel="nofollow"&gt;CSS Validator&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="CSS Viewer :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/2104" rel="nofollow"&gt;CSS Viewer&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Dublin Core Viewer :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/528" rel="nofollow"&gt;Dublin Core Viewer&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Firebug :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/1843" rel="nofollow"&gt;Firebug&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="FireFTP - The Free FTP Client for Mozilla Firefox" href="http://fireftp.mozdev.org/" rel="nofollow"&gt;FireFTP&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Html Validator :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/249" rel="nofollow"&gt;Html Validator&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="HttpFox :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/6647" rel="nofollow"&gt;HttpFox&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="IE View - Launch pages in IE from Firefox" href="http://ieview.mozdev.org/" rel="nofollow"&gt;IE View&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="LinkChecker :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/532" rel="nofollow"&gt;LinkChecker&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Live HTTP Headers :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/3829" rel="nofollow"&gt;Live HTTP Headers&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="MeasureIt :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/539" rel="nofollow"&gt;MeasureIt&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="NoScript :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/722" rel="nofollow"&gt;NoScript&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Operator :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/4106" rel="nofollow"&gt;Operator&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="pastego :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/3201" rel="nofollow"&gt;pastego&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Quick Locale Switcher :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/1333" rel="nofollow"&gt;Quick Locale Switcher&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Ubiquity :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/9527" rel="nofollow"&gt;Ubiquity&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="View Dependencies :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/2214" rel="nofollow"&gt;View Dependencies&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="View Source Chart (Firefox Extension)" href="http://jennifermadden.com/scripts/ViewRenderedSource.html" rel="nofollow"&gt;View Source Chart&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="WAVE Toolbar" href="http://wave.webaim.org/toolbar" rel="nofollow"&gt;WAVE Toolbar&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="Window Resizer :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/1985" rel="nofollow"&gt;Window Resizer&lt;/a&gt;&lt;/li&gt;            &lt;li&gt;&lt;a title="YSlow :: Firefox Add-ons" href="https://addons.mozilla.org/firefox/addon/5369" rel="nofollow"&gt;YSlow&lt;/a&gt;&lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;&lt;a title="HttpWatch: An HTTP Viewer and HTTP Sniffer for IE and Firefox" href="http://www.httpwatch.com/" rel="nofollow"&gt;HttpWatch&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="Internet Explorer Developer Toolbar" href="http://www.microsoft.com/downloads/details.aspx?familyid=E59C3964-672D-4511-BB3E-2D5E1DB91038" rel="nofollow"&gt;Internet Explorer Developer Toolbar&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="StyleCop" href="http://code.msdn.microsoft.com/sourceanalysis" rel="nofollow"&gt;Microsoft StyleCop&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="Visual Studio Gallery | PowerCommands for Visual Studio 2008" href="http://www.visualstudiogallery.com/ExtensionDetails.aspx?ExtensionID=df3f0c30-3d37-4e06-9ef8-3bff3508be31" rel="nofollow"&gt;Microsoft Visual Studio 2008 Power Commands&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="RedGate Reflector" href="http://www.red-gate.com/products/reflector" rel="nofollow"&gt;Reflector&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="TortoiseSVN" href="http://tortoisesvn.tigris.org/" rel="nofollow"&gt;TortoiseSVN&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a title="Windows Sysinternals" href="http://technet.microsoft.com/sysinternals" rel="nofollow"&gt;Windows Sysinternals&lt;/a&gt;          &lt;ul&gt;           &lt;li&gt;Debug View&lt;/li&gt;            &lt;li&gt;Process Explorer&lt;/li&gt;            &lt;li&gt;Process Monitor&lt;/li&gt;            &lt;li&gt;TCP View&lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;&lt;a title="WinMerge" href="http://winmerge.org/" rel="nofollow"&gt;WinMerge&lt;/a&gt;&lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;a title="ASP.NET MVC" href="http://asp.net/mvc" rel="nofollow"&gt;ASP.NET MVC 1.0 Release Candidate&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a title="Microsoft Azure Resources" href="http://www.microsoft.com/azure/resources" rel="nofollow"&gt;Microsoft Azure&lt;/a&gt;&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a title="Microsoft Azure SDKs" href="http://www.microsoft.com/azure/sdk" rel="nofollow"&gt;Developer SDKs&lt;/a&gt;        &lt;ul&gt;         &lt;li&gt;Windows Azure Software Development Kit (January 2009 CTP)&lt;/li&gt;          &lt;li&gt;Windows Azure Tools for Microsoft Visual Studio January 2009 CTP&lt;/li&gt;          &lt;li&gt;Microsoft .NET Services SDK (Dec 2008 CTP)&lt;/li&gt;          &lt;li&gt;SQL Data Services (SDS) SDK (CTP)&lt;/li&gt;       &lt;/ul&gt;     &lt;/li&gt;      &lt;li&gt;&lt;a title="Microsoft Azure Training Kit" href="http://www.microsoft.com/azure/trainingkit" rel="nofollow"&gt;Training Kit&lt;/a&gt;&lt;/li&gt;   &lt;/ul&gt; &lt;/ol&gt;  </description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item><item><title>Working out a writing schedule</title><link>http://alandean.blogspot.com/2009/02/working-out-writing-schedule.html</link><category>Book</category><pubDate>Sat, 28 Feb 2009 04:29:00 -0800</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5703778183485988456.post-4138875482447337907</guid><description>&lt;p&gt;This is the top-level view of my book:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Introduction (20 pages)&lt;/li&gt;    &lt;li&gt;Chapter 1: Introducing the Project (10 pages)&lt;/li&gt;    &lt;li&gt;Chapter 2: The Product Data Store (20 pages)&lt;/li&gt;    &lt;li&gt;Chapter 3: User Authentication (50 pages)&lt;/li&gt;    &lt;li&gt;Chapter 4: Product Management (80 pages)&lt;/li&gt;    &lt;li&gt;Chapter 5: Product Pages (50 pages)&lt;/li&gt;    &lt;li&gt;Chapter 6: The Shopping Cart (100 pages)&lt;/li&gt;    &lt;li&gt;Chapter 7: Checkout (150 pages)&lt;/li&gt;    &lt;li&gt;Chapter 8: Personalization (100 pages)&lt;/li&gt;    &lt;li&gt;Chapter 9: Deployment, Monitoring and Management (50 pages)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;My next task is to work out a writing schedule to accomplish these chapters. This is my first book, so I am on a steep learning curve.&lt;/p&gt;  &lt;p&gt;Aside from community commitments, I will be devoting my weekends to writing and my weekday evenings to preparation, editorial and revisions.&lt;/p&gt;  &lt;p&gt;I will backload the Introduction and Chapter 1. Luckily Chapters 2 to 4 form an ‘up ramp’ in terms of page count, which I hope will allow me to accelerate into the writing rather than needing to be at high velocity from the start (an objective I would be unlikely to achieve). Another piece of luck is that the UK Bank Holiday season falls right in the middle of the schedule, just at the point where I have the largest pieces of work to accomplish.&lt;/p&gt;  &lt;p&gt;So, thinking in units of ‘weekend’ my initial plan is as follows:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Feb 28 = Environment Prep &amp;amp; Ancillary Tasks&lt;/li&gt;    &lt;li&gt;Mar 07 = Chapter 2: The Product Data Store (20 pages)&lt;/li&gt;    &lt;li&gt;Mar 14 = Chapter 3: User Authentication (50 pages)&lt;/li&gt;    &lt;li&gt;Mar 21 = Chapter 4: Product Management (80 pages)&lt;/li&gt;    &lt;li&gt;Mar 28 = Chapter 4: Product Management (80 pages) &lt;em&gt;[Open Space Coding Day]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;Apr 04 = Chapter 5: Product Pages (50 pages) &lt;em&gt;[DDD Belfast]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;Apr 11 = Chapter 6: The Shopping Cart (100 pages) &lt;em&gt;[Easter Bank Holidays]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;Apr 18 = Chapter 6: The Shopping Cart (100 pages)&lt;/li&gt;    &lt;li&gt;Apr 25 = Chapter 6: The Shopping Cart (100 pages)&lt;/li&gt;    &lt;li&gt;May 02 = Chapter 7: Checkout (150 pages) &lt;em&gt;[DDD Scotland], [May Day Bank Holiday]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;May 09 = Chapter 7: Checkout (150 pages)&lt;/li&gt;    &lt;li&gt;May 16 = Chapter 7: Checkout (150 pages)&lt;/li&gt;    &lt;li&gt;May 23 = Chapter 8: Personalization (100 pages) &lt;em&gt;[Whitsun Bank Holiday]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;May 30 = Chapter 8: Personalization (100 pages) &lt;em&gt;[Open Space Coding Day]&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;Jun 06 = Chapter 9: Deployment, Monitoring and Management (50 pages)&lt;/li&gt;    &lt;li&gt;Jun 13 = Introduction, Chapter 1&lt;/li&gt;    &lt;li&gt;Jun 20 = &lt;em&gt;&lt;strong&gt;(manuscript)&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A tough schedule, I know, but I &lt;em&gt;&lt;strong&gt;really&lt;/strong&gt;&lt;/em&gt; want this book out on the shelves by the time that &lt;a title="PDC &amp;#39;09" href="http://channel9.msdn.com/posts/PDCNews/Announcing-PDC2009/" rel="nofollow"&gt;PDC ‘09&lt;/a&gt; rolls around.&lt;/p&gt;  </description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><author>alan.dean@gmail.com (Alan Dean)</author></item></channel></rss>