<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Shannon Cornish</title>
	<atom:link href="http://www.shannoncornish.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.shannoncornish.com/blog</link>
	<description></description>
	<lastBuildDate>Mon, 26 Jul 2010 09:22:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Building SpecificationFor&lt;T&gt;</title>
		<link>http://www.shannoncornish.com/blog/2010/07/building_specificationfor/</link>
		<comments>http://www.shannoncornish.com/blog/2010/07/building_specificationfor/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 08:09:07 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=185</guid>
		<description><![CDATA[We had a new developer join our team recently and while going over the codebase, there were a few things that we had built that might not have been obvious as to how we got there. One of them was the way we write and structure our unit tests. At the time we had started [...]]]></description>
			<content:encoded><![CDATA[<p>We had a new developer join our team recently and while going over the codebase, there were a few things that we had built that might not have been obvious as to how we got there. One of them was the way we write and structure our unit tests.</p>
<p>At the time we had started the project, we were following the one test fixture per class convention and have since moved on to a scenario based specification style convention and have introduced a unit test base class that simplifies and increases our development velocity.</p>
<p>The goal of this post is to explain <b>SpecificationFor&lt;T&gt;</b>, our unit test base class, by building it step by step in a way that you can follow on at home.</p>
<p>We&#8217;re going to be using a sample class <b>FormatterDecorator</b> and it&#8217;s unit test fixture <b>FormatterDecoratorFixture</b>. Our decorator doesn&#8217;t do anything special, but should be complex enough to our needs.</p>
<div class="filename">FormatterDecorator.cs</div>
<pre class="prettyprint lang-cs">
public class FormatterDecorator : IFormatter {
  private readonly IFormatter _formatter;
  public FormatterDecorator(IFormatter formatter) {
    _formatter = formatter;
  }

  public string Format(string s) {
    return _formatter.Format(s);
  }
}
</pre>
<p>And here is the unit test fixture. Note we&#8217;re using <a href="http://nunit.org">NUnit</a> for our testing framework and <a href="http://nsubstitute.github.com/">NSubstitute</a> for mocks.</p>
<div class="filename">FormatterDecoratorFixture.cs</div>
<pre class="prettyprint lang-cs">
public class FormatterDecoratorFixture {
  private const string Formatted = "f";
  private const string Unformatted = "p";

  private IFormatter _formatter;
  private FormatDecorator _decorator;

  [SetUp]
  public void SetUp() {
    _formatter = Substitute.For&lt;IFormatter&gt;();
    _formatter.Format(Unformatted).Returns(Formatted);

    _decorator = new FormatterDecorator(_formatter);
  }

  [Test]
  public void FormatShouldReturnFormattedValue() {
    var result = _decorator.Format(Unformatted);
    Assert.That(result, Is.EqualTo(Formatted);
  }
}
</pre>
<p>The first thing we&#8217;re going to change is our convention for one unit test fixture per class. We&#8217;re going to move to a scenario based specification style. Fortunately for us, <a href="http://www.davesquared.net/">Dave</a> has written a great post on <a href="http://www.davesquared.net/2009/06/moving-to-scenario-based-unit-testing.html">moving to scenario based unit testing</a>. Make sure to read it for the why.</p>
<p>To change to scenario based unit testing, we&#8217;re going to rename our test fixture class to match our scenario. For our example, the scenario we&#8217;re dealing with formatting, so we&#8217;re going to rename our class and filename from <b>FormatterDecoratorFixture</b> to <b>WhenFormatting</b>. If we had any additional scenarios for our class, we would move them into separate scenario based classes and files.</p>
<p>In order to support Resharper&#8217;s <i>Navigate To Type</i> feature for moving around our solution, we&#8217;re going to group each of the scenarios associated with our class into a <b>FormatterDecoratorFixture</b> outer class. Our new test fixture file should look something like below.</p>
<div class="filename">WhenFormatting.cs</div>
<pre class="prettyprint lang-cs">
public partial class FormatterDecoratorFixture {
  public class WhenFormatting {
    // SetUp and Tests etc
    ....
  }
}
</pre>
<p>As we&#8217;re now working with an individual scenario for each test fixture, it makes sense to move the code that executes the scenario out of the test and into the setup.</p>
<pre class="prettyprint lang-cs">
  [SetUp]
  public void SetUp() {
    _formatter = Substitute.For<IFormatter>();
    _formatter.Format(Unformatted).Returns(Formatted);

    _decorator = new FormatterDecorator(_formatter);
    _result = _decorator.Format(Unformatted);
  }
</pre>
<p>Now our <b>SetUp</b> method contains the code to initialise and execute our scenario. We can improve the situation by moving these into separate methods. First, we&#8217;ve got scenario setup code, our context. Let&#8217;s move this into a <b>Context</b> method. Second, we&#8217;ve got code that executes our scenario, let&#8217;s move this into a <b>Because</b> method.</p>
<pre class="prettyprint lang-cs">
  [SetUp]
  public void SetUp() {
    Context();
    Because();
  }

  private void Context() {
    _formatter = Substitute.For<IFormatter>();
    _formatter.Format(Unformatted).Returns(Formatted);

    _decorator = new FormatterDecorator(_formatter);
  }

  private void Because() {
    _result = _decorator.Format(Unformatted);
  }
</pre>
<p>Our <b>SetUp</b> method is going to be the same for each scenario, so we can move that into a base class that each test fixture will inherit from. Let&#8217;s call this <b>SpecificationFor</b>.</p>
<div class="filename">SpecificationFor.cs</div>
<pre class="prettyprint lang-cs">
public abstract class SpecificationFor {
  [SetUp]
  public void SetUp() {
    Context();
    Because();
  }

  protected virtual void Context() { }
  protected virtual void Because() { }
}
</pre>
<p>Now a lot of our contexts are going to be creating our subject (or class under test) and it&#8217;s dependencies (our substitutes). This is code that is going to be repeated for each scenario associated with a class. For example, if we added a new scenario for our decorator, we would need to duplicate the code that creates our <b>_decorator</b> subject and our <b>_formatter</b> substitute. We could move this code into a base class (i.e. <b>FormatterDecoratorFixtureBase</b>) and have each scenario inherit from that, but instead we&#8217;re going to introduce an auto mocker.</p>
<p>As we&#8217;re using StructureMap in our code base, it made sense to use the auto mocker built in. Jeremy Miller has a great post explaining the <a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/02/09/automocker-in-structuremap-2-5.aspx">AutoMocker in StructureMap 2.5</a>.</p>
<p>After introducing the auto mocker, our <b>SpecificationFor</b> now looks like this.</p>
<pre class="prettyprint lang-cs">
public abstract class SpecificationFor&lt;TSubject&gt; {
  private IAutoMocker _autoMocker;

  protected TSubject Subject {
    get { return _autoMocker.ClassUnderTest; }
  }

  [SetUp]
  public void SetUp() {
    _autoMocker = new NSubstituteAutoMocker&lt;TSubject&gt;()

    Context();
    Because();
  }

  protected T Resolve&lt;T&gt;() {
    return _autoMocker.Get&lt;T&gt;();
  }

  ...
}
</pre>
<p>With our auto mocker in place, our <b>WhenFormatting</b> scenario should be.</p>
<div class="filename">WhenFormatting.cs</div>
<pre class="prettyprint lang-cs">
public partial class FormatterDecoratorFixture {
  public class WhenFormatting
    : SpecificationFor&lt;FormatterDecorator&gt; {
    private const string Formatted = "f";
    private const string Unformatted = "p";

    private string _result;

    public override void Context() {
      Resolve&lt;IFormatter&gt;().Format(Unformatted)
        .Returns(Formatted);
    }

    public override void Because() {
      _result = Subject.Format(Unformatted);
    }

    [Test]
    public void ShouldReturnFormattedValue() {
      Assert.That(_result, Is.EqualTo(Formatted);
    }
  }
}
</pre>
<p>Improvements that we can make to our <b>SpecificationFor&lt;T&gt;</b> are ensuring that the <b>Subject</b> is created before <b>Because</b> and to lazily initialise Subject to allow us to access it in our <b>Context</b> (should we need to set up the state of our subject or add event subscriptions etc). We can do this by wrapping the subject with a <b>Lazy&lt;T&gt;</b>.</p>
<pre class="prettyprint lang-cs">
public abstract class SpecificationFor&lt;TSubject&gt; {
  private IAutoMocker _autoMocker;
  private Lazy&lt;T&gt; _lazySubject;

  protected TSubject Subject {
    get { return _lazySubject.Value; }
  }

  [SetUp]
  public void SetUp() {
    _autoMocker = new NSubstituteAutoMocker&lt;TSubject&gt;()
    _lazySubject = new Lazy&lt;T&gt;(() => _autoMocker.ClassUnderTest);

    Context();
    EnsureSubjectIsCreated();
    Because();
  }

  private void EnsureSubjectIsCreated() {
    if (Subject == null) {
      throw new InvalidOperationException();
    }
  }

  ...
}
</pre>
<p>Using <b>SpecificationFor&lt;T&gt;</b> reduces mundane and repetitive setup code in our unit tests, gives us conventions for naming and placement of code. It&#8217;s been a big improvement for our productivity and our tests in general.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2010/07/building_specificationfor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Agile 2009 &#8211; Day 1</title>
		<link>http://www.shannoncornish.com/blog/2009/08/agile-2009-day-1/</link>
		<comments>http://www.shannoncornish.com/blog/2009/08/agile-2009-day-1/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 05:35:16 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile2009]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=153</guid>
		<description><![CDATA[Developing Agile Leaders and Teams: A Developmental Path to Agile Leadership with Gilles Brouillette A surprisingly interesting session to kick off Agile 2009, Gilles presented on developmental stages on how we&#8217;re influenced by the stage we&#8217;re in. There are seven leadership levels, with most of us being in the &#8216;Heroic&#8217; stage (Expert &#38; Achiever). Perhaps [...]]]></description>
			<content:encoded><![CDATA[<h3>Developing Agile Leaders and Teams: A Developmental Path to Agile Leadership with Gilles Brouillette</h3>
<p>
A surprisingly interesting session to kick off Agile 2009, Gilles presented on developmental stages on how we&#8217;re influenced by the stage we&#8217;re in.
</p>
<p>
There are seven leadership levels, with most of us being in the &#8216;Heroic&#8217; stage (Expert &amp; Achiever). Perhaps a little bit disheartening, Gilles has suggested that<br />
only 10% of the population is capable of operating at the &#8216;Post-Heroic&#8217; stage.
</p>
<ol>
<li>Opportunist</li>
<li>Diplomat</li>
<li>Expert</li>
<li>Achiever</li>
<li>Catalyst</li>
<li>Co-Creator</li>
<li>Synergist</li>
</ol>
<p>
There is an assumption that we move back and forth between the levels. For example, if we are stressed, we might slip back to the previous level. Also, the further developed you are, the quicker you are to adapt and the less defensive you are (less desire to hide your mistakes or need to know all of the answers).
</p>
<p>
Going from the heroic to the post-heroic stage requires a different mind set. A different way to think that is more strategic, more team focussed. An example is that a person at the heroic level will consider something a win if they manage to advance some aspect of themselves, we as a person in the post heroic stage will only consider something a win if they are able to advance some aspect of the entire team.
</p>
<p>
It was an interesting session and with the examples of the various levels, I was able to pinpoint myself somewhere between the Expert and the Achiever level, but I&#8217;ve noticed all too often that I&#8217;ll do something that that brings me back a level. Something I plan on working on for this year.
</p>
<h3>Craftsmanship wtih Robert Martin</h3>
<p>
Uncle Bob began the presentation by talking about how big plans don&#8217;t work, even if we&#8217;re wired to think they will. Actually, he started his talk with how electrons are fired form an electron gun through a filter and on to a screen to make a dot, but I can&#8217;t remember why now? Anyway, it came around to being about big plans and it all made sense at the time.
</p>
<p>
Big plans don&#8217;t work and even if we know it, there is a part of us that believes that if we plan enough, if we sit around this talk about everything we&#8217;ll get it covered and we&#8217;ll get it right this time. As much as we&#8217;re wired to believe that, it doesn&#8217;t work that way.
</p>
<p>
Complex systems that worked have invariably found to have evolved from a simple system that worked.<br />
Complex systems that are designed from scratch never work and cannot be patched to make it work. Most people will start over, beginning with a simple working system.
</p>
<p>
Simple things live and evolve, complex things die a horrible and expensive death.
</p>
<ul>
<li>
<strong>Short iterations</strong></p>
<p>
The consensus in the industry is that 1 to 2 weeks is the optimal iteration length. Bob believes that in a few years from now, this will drop to 3 to 5 days.
</p>
<p>
What gets delivered at the end of the iteration? Something that is useful and delivers value to the customer. The customer does not have to agree that the functionality is complete but every iteration needs to deliver something that works.
</p>
<p>
The Harvard Business Review had an article which concluded that the earlier you release, the happier your customers are, even if what you release is under-functioned.
</p>
</li>
<li><strong>No grand redesigns</strong>
<p>
We are the ones that made the mess and we must be the ones that clean up the mess.<br />
You don&#8217; clean up your house by moving.
</p>
</li>
<li><strong>Incremental improvement</strong>
<p>
It&#8217;s not a technique, but a way of life.<br />
A commitment to never making the source code worse.
</p>
<p>
We have the mess because we don&#8217;t practice incremental improvement; we practice incremental destruction. There should be no reason why<br />
a developer checks in source code in a worse state than they checked it out.
</p>
<p>
Always improve the code as much as you can.<br />
Every time you make a mess you will slow yourself down.</p>
<p>
Big Dave Thomas&#8217; law of continuos improvements is that progress is a<br />
sequence of decisions, some of them wrong.
</p>
</li>
<li><strong>The only way to go fast is to go well</strong></li>
<li><strong>Clean code</strong>
<p>Is an attitude, something that we commit to.</p>
</li>
<li><strong>TDD</strong></li>
<li><strong>QA should find nothing</strong>
<p>Every time QA finds something, we should be asking ourselves how did this get out.</p>
</li>
<li><strong>100% code coverage</strong></li>
<li><strong>Avoid debugging</strong></li>
<li><strong>Manual test scripts are immoral</strong></li>
<li><strong>Definition of done</strong>
<p>All tests pass (unit, acceptance, UI etc), nothing less.</p>
</li>
<li><strong>Test through the right interface</strong>
<p>Business rules should be tested at the business layer, not the UI layer.<br />
You should test that the UI is wired up to your application, but do not drive your application from the UI tests.</p>
<p>There should still be a few tests that drive all parts of your application from the UI, but these should be limited.</p>
</li>
<li><strong>Never be blocked</strong>
<p>Never say to yourself that I can&#8217;t move forward because&#8230;</p>
</li>
</ul>
<p>
Uncle Bob ended the session with a quick note on how craftsmanship does<br />
not limit you from taking shortcuts. You can implement code with the<br />
intention of removing it in the following iteration. However,<br />
shortcuts must be clean.<br />
</P></p>
<p>This aligns with some of the thinking that I&#8217;ve been doing regarding the<br />
advice of &#8220;simplest thing possible that will make the test pass&#8221;. I&#8217;ve heard, perhaps even uttered,<br />
this phrase when justifying code that is not clean, not well factored.<br />
Perhaps we need to replace the &#8220;simplest thing possible&#8221; with &#8220;simplest thing that isn&#8217;t crap&#8221; :)
</p>
<h3>Integration Tests are a Scam with J. B. Rainsberger</h3>
<p>
Hoping to get some answers to my questions regarding unit testing vs acceptance testing, I went a long to the session by J. B. (Joe) Rainsberger. However, as it turned out, the session was about integration tests, with integration tests being defined as defined as any test where the result of the test depends on more than one object being correct.
</p>
<p>
The solution presented to the problem of integration tests was to isolate the service or entity being tested via interfaces and use mock objects to allow the class under test to be tested without bringing in the dependencies of other concrete classes. Once these dependencies are broken and you&#8217;re dealing with a single concrete object, the test is no longer an integration test but an isolated object test, or focused test.
</p>
<p>
Joe challenged the audience to write our tests using the single assert per test principle for 3 months. He wasn&#8217;t presenting the principle as the correct way to write tests, only that after 3 months of writing the tests as such, we would learn how to write better tests.
</p>
<p>
Joe also presented on the idea of Contract Testing, where you create a super test fixture class that tests the behavior of an interface and then create sub test fixture classes for all of the classes that implement that interface.
</p>
<p>
I was quite disappointed in how the talk turned into a unit testing practices session. Unfortunately this only became apparent around 45 minutes into the session and it was too late to change. It could have been a better session if it was more targeted as a way to improve monolithic and highly coupled unit tests and billed as such.
</p>
<p>
Before the session had started, Joe was talking about talking in <a href="http://en.wikipedia.org/wiki/E-Prime">E-Prime</a>. E-Prime is a subset of the English language that does not use any form of the verb <em>to be</em>. He presented it as a way to be, or to project as being less judgmental. It sounds like an interesting exercise and something to investigate.</p>
<h3>Swag</h3>
<p><img alt="Agile 2009 Swag" src="/blog_uploads/2009/08/agile_2009_swag.jpg" width="467" height="359" /></p>
<p>
A drink bottle, <em>Becoming Agile in an imperfect world</em> by Greg Smith and Ahmed Sidky, <em>Agile 2009 Conference</em> book, <em>Lean-Agile Pocket Guide for Scrum Teams</em> by Alan Shalloway and James R. Trott <em>Real Options at Agile 2009</em> comic and a bunch of useless advertising.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2009/08/agile-2009-day-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting up Gitosis with Windows Server 2008</title>
		<link>http://www.shannoncornish.com/blog/2009/04/gitosis-windows-server-2008/</link>
		<comments>http://www.shannoncornish.com/blog/2009/04/gitosis-windows-server-2008/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 03:56:35 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[gitosis]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=121</guid>
		<description><![CDATA[As part of our Git server configuration, we&#8217;re using Gitosis manage multiple repositories with different authorization requirements using a single SSH account. I&#8217;m assuming you&#8217;ve read my previous post on Setting up a Git server with Windows Server 2008 and are ready to follow along as the steps assume you&#8217;ve already installed Cygwin with Git, [...]]]></description>
			<content:encoded><![CDATA[<p>As part of our Git server configuration, we&#8217;re using <a href="http://eagain.net/gitweb/?p=gitosis.git">Gitosis</a> manage multiple repositories with different authorization requirements using a single SSH account.</p>
<p>I&#8217;m assuming you&#8217;ve read my previous post on <a href="http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/">Setting up a Git server with Windows Server 2008</a> and are ready to follow along as the steps assume you&#8217;ve already installed Cygwin with Git, OpenSSH and Python.</p>
<p>The blog post by Sandesh Singh on <a href="http://sandesh247.blogspot.com/2009/03/on-git-gitosis-and-python-issues-on.html">setting up Gitosis with Windows Vista</a> was an amazing resource and without it, I would still be trying to get Gitosis working.</p>
<h3>Installing Python Setuptools</h3>
<ul>
<li>Download the <a href="http://pypi.python.org/pypi/setuptools">Python Setuptools</a> egg.</li>
<li>Open a Cygwin bash prompt and navigate to the directory containing your download.</li>
<li>Execute
<pre>sh setuptools-0.6c9-py2.5.egg</pre>
</li>
<li>You should see
<pre>
Processing setuptools-0.6c9-py2.5.egg
Copying setuptools-0.6c9-py2.5.egg to /usr/lib/python2.5/site-packages
Adding setuptools 0.6c9 to easy-install.pth file
Installing easy_install script to /usr/bin
Installing easy_install-2.5 script to /usr/bin

Installed /usr/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg
Processing dependencies for setuptools==0.6c9
Finished processing dependencies for setuptools==0.6c9
</pre>
</li>
<li>Execute
<pre>chmod +r /usr/lib/python2.5/ -R</pre>
</li>
</ul>
<h3>Installing Gitosis</h3>
<ul>
<li>Download or clone the Gitosis repository</li>
<li>Open a Cygwin bash prompt and navigate to the directory containing Gitosis.</li>
<li>
Execute</p>
<pre>python setup.py install</pre>
</li>
<li>Copy the public key of the user you wish to administer the Gitosis server to /tmp directory.</li>
<li>Log out of the Administrator account and login as the git account.</li>
<li>Open a Cygwin bash prompt and execute
<pre>gitosis-init < /tmp/id_rsa.pub</pre>
</li>
<li>
You should see</p>
<pre>
Initialized empty Git repository in /home/git/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /home/git/repositories/gitosis-admin.git/
</pre>
</li>
<li> Execute
<pre>chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update</pre>
</li>
</ul>
<p>Gitosis is now setup and we're ready to clone the gitosis-admin repository to create and administer Git repositories on our server.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2009/04/gitosis-windows-server-2008/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Setting up a Git server with Windows Server 2008</title>
		<link>http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/</link>
		<comments>http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 05:55:15 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cygwin]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=88</guid>
		<description><![CDATA[I&#8217;m in the middle of setting up a Git server at work and needed to document the process that I used for installation, setup and administration. I figured the best place to put the documentation was to blog about it so that others might benefit and improve it. The server operating system we&#8217;re running is [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m in the middle of setting up a <a href="http://git-scm.com/">Git</a> server at work and needed to document the process that I used for installation, setup and administration. I figured the best place to put the documentation was to blog about it so that others might benefit and improve it.</p>
<p>The server operating system we&#8217;re running is Windows Server 2008.</p>
<h3>What is Git?</h3>
<p>Git is a distributed version control system originally developed by Linus Torvalds to manage the Linux kernel.</p>
<p>Git is available on Windows using <a href="http://cygwin.com">Cygwin</a> or <a href="http://code.google.com/p/msysgit/">msysGit</a>.</p>
<p>
For the server installation, I&#8217;ve chosen to use the Cygwin version of Git. We will be using a SSH server for our server to authenticate users and allow access to the repositories. Using Cygwin will allow us to use the Cygwin version OpenSSH for our server.</p>
<h3>Installing Cygwin</h3>
<ul>
<li>Create the C:\Cygwin directory.</li>
<li>Create the C:\Cygwin\packages directory.</li>
<li>Modify the permissions on the C:\Cygwin directory to grant the USERS group modify permissions.</li>
<li>Download the Cygwin setup package into the C:\Cygwin directory and run the setup.</li>
<li>Use the following options for the Cygwin setup package:
<ul>
<li>Choose Installation Type
<ul>
<li>Leave default Install from Internet</li>
</ul>
</li>
<li>Choose Installation Directory
<ul>
<li>Leave default root directory C:\Cygwin</li>
<li>Leave default install for All Users</li>
<li>Leave default text file type Unix/binary</li>
</ul>
</li>
<li>Select Local Packages Directory
<ul>
<li>Change local packages directory to C:\Cygwin\packages</li>
</ul>
</li>
<li>Select Connection Type
<ul>
<li>Leave default direct connection</li>
</ul>
</li>
<li>Choose Download Site(s)
<ul>
<li>Add a local <a href="http://cygwin.com/mirrors.html">mirror</a></li>
</ul>
</li>
<li>Select Packages
<ul>
<li>Select Devel &gt; git</li>
<li>Select Devel &gt; git-completion</li>
<li>Select Devel &gt; git-gui</li>
<li>Select Devel &gt; gitk</li>
<li>Select Net &gt; openssh</li>
<li>Select Python &gt; python</li>
</ul>
</li>
<li>Installation Status and Create Icons
<ul>
<li>Leave default create icon on Desktop</li>
<li>Leave default Add icon to Start Menu</li>
</ul>
</li>
</ul>
</li>
<li> Modify the C:\Cygwin\cygwin.bat file to set the CYGWIN environment variable. The whole file should appear as follows:
<pre>@echo off
set CYGWIN=binmode tty ntsec

c:
chdir c:\cygwin\bin

bash --login -i</pre>
</li>
<li>
Run Cygwin from the desktop. It should display:</p>
<pre>Copying skeleton files.
These files are for the user to personalise
their cygwin experience.

These will never be overwritten.

'./.bashrc' -&gt; '/home/Administrator//.bashrc'
'./.bash_profile' -&gt; '/home/Administrator//.bash_profile'
'./.inputrc' -&gt; '/home/Administrator//.inputrc'</pre>
</li>
<li>
Execute</p>
<pre>
mount -s --change-cygdrive-prefix /
</pre>
</li>
<li>
Execute</p>
<pre>
mkdir -p /home
</pre>
</li>
<li>
Execute</p>
<pre>
chmod +r //etc//passwd
chmod +r //etc//group
chmod 755 //var
</pre>
<p>Note: The above statements should use a single slash rather than a double slash. The double slash is required to work around the filter from my blogging software.
</li>
<li>Close the Cygwin bash prompt</li>
</ul>
<h3>Installing OpenSSH</h3>
<ul>
<li>Open the Cygwin bash prompt as an Administrator via right clicking and selecting Run as administrator.</li>
<li>Execute
<pre>ssh-host-config</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Generating /etc/ssh_host_key
*** Info: Generating /etc/ssh_host_rsa_key
*** Info: Generating /etc/ssh_host_dsa_key
*** Info: Creating default /etc/ssh_config file
*** Info: Creating default /etc/sshd_config file
*** Info: Privilege separation is set to yes by default since OpenSSH 3.3.
*** Info: However, this requires a non-privileged account called 'sshd'.
*** Info: For more info on privilege separation read /usr/share/doc/openssh/README.privsep.
*** Query: Should privilege separation be used? (yes/no)
</pre>
</li>
<li>
Type</p>
<pre>
yes
</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Note that creating a new user requires that the current account have
*** Info: Administrator privileges.  Should this script attempt to create a
*** Query: new local account 'sshd'? (yes/no)
</pre>
</li>
<li>
Type</p>
<pre>
yes
</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Updating /etc/sshd_config file

*** Warning: The following functions require administrator privileges!

*** Query: Do you want to install sshd as a service?
*** Query: (Say "no" if it is already installed as a service) (yes/no)
</pre>
</li>
<li>
Type</p>
<pre>
yes
</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Note that the CYGWIN variable must contain at least "ntsec"
*** Info: for sshd to be able to change user context without password.
*** Query: Enter the value of CYGWIN for the daemon: [ntsec]
</pre>
</li>
<li>
Type</p>
<pre>
binmode tty ntsec
</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: On Windows Server 2003, Windows Vista, and above, the
*** Info: SYSTEM account cannot setuid to other users -- a capability
*** Info: sshd requires.  You need to have or to create a privileged
*** Info: account.  This script will help you do so.

*** Info: You appear to be running Windows 2003 Server or later.  On 2003
*** Info: and later systems, it's not possible to use the LocalSystem
*** Info: account for services that can change the user id without an
*** Info: explicit password (such as passwordless logins [e.g. public key
*** Info: authentication] via sshd).

*** Info: If you want to enable that functionality, it's required to create
*** Info: a new account with special privileges (unless a similar account
*** Info: already exists). This account is then used to run these special
*** Info: servers.

*** Info: Note that creating a new user requires that the current account
*** Info: have Administrator privileges itself.

*** Info: No privileged account could be found.

*** Info: This script plans to use 'cyg_server'.
*** Info: 'cyg_server' will only be used by registered services.
*** Query: Do you want to use a different name? (yes/no)
</pre>
</li>
<li>
Type</p>
<pre>
no
</pre>
</li>
<li>
You should see</p>
<pre>
*** Query: Create new privileged user account 'cyg_server'? (yes/no)
</pre>
</li>
<li>
Type</p>
<pre>
yes
</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Please enter a password for new user cyg_server.  Please be sure
*** Info: that this password matches the password rules given on your system.
*** Info: Entering no password will exit the configuration.
*** Query: Please enter the password:
</pre>
</li>
<li>Type and confirm a password for the new &#8216;cyg_server&#8217; account.</li>
<li>After confirming the password, you should see
<pre>
*** Info: User 'cyg_server' has been created with password 'azxggsri7#35z'.
*** Info: If you change the password, please remember also to change the
*** Info: password for the installed services which use (or will soon use)
*** Info: the 'cyg_server' account.

*** Info: Also keep in mind that the user 'cyg_server' needs read permissions
*** Info: on all users' relevant files for the services running as 'cyg_server'.

*** Info: In particular, for the sshd server all users' .ssh/authorized_keys
*** Info: files must have appropriate permissions to allow public key
*** Info: authentication. (Re-)running ssh-user-config for each user will set
*** Info: these permissions corrently. [Similary restrictions apply, for
*** Info: instance, for .rhosts files if the rshd server is running, etc].

*** Info: The sshd service has been installed under the 'cyg_server'
*** Info: account.  To start the service now, call `net start sshd' or
*** Info: `cygrunsrv -S sshd'.  Otherwise, it will start automatically
*** Info: after the next reboot.

*** Info: Host configuration finished. Have fun!
</pre>
</li>
<li>
Execute</p>
<pre>net start sshd</pre>
</li>
<li>Open the Windows Firewall Editor and create an exception to allow TCP traffic on port 22.
</ul>
<h3>Creating a Git user account for SSH access</h3>
<p>
Single SSH account will run under.
</p>
<ul>
<li>Create a &#8216;git&#8217; account via the standard windows tools and make sure to disable password expiry.<br />
The account should be a member of the USERS group.</li>
<li>Open the Cygwin bash prompt and type
<pre>mkpasswd -l -u git -p //home >> //etc//passwd</pre>
<p>Note: The above statements should use a single slash rather than a double slash. The double slash is required to work around the filter from my blogging software.
</li>
<li>Log out of the Administrator account and login as the git account.</li>
<li>
Run Cygwin from the desktop. It should display:</p>
<pre>Copying skeleton files.
These files are for the user to personalise
their cygwin experience.

These will never be overwritten.

'./.bashrc' -&gt; '/home/git//.bashrc'
'./.bash_profile' -&gt; '/home/git//.bash_profile'
'./.inputrc' -&gt; '/home/git//.inputrc'</pre>
</li>
<li>
Execute</p>
<pre>ssh-user-config</pre>
</li>
<li>You should see
<pre>
*** Warning: group and other have been revoked write permission to your home
*** Warning: directory /home/git.
*** Warning: This is required by OpenSSH to allow public key authentication using
*** Warning: the key files stored in your .ssh subdirectory.
*** Warning: Revert this change ONLY if you know what you are doing!

*** Query: Shall I create an SSH1 RSA identity file for you? (yes/no)
</pre>
</li>
<li>Type
<pre>no</pre>
</li>
<li>
You should see</p>
<pre>*** Query: Shall I create an SSH2 RSA identity file for you? (yes/no)</pre>
</li>
<li>
Type</p>
<pre>yes</pre>
</li>
<li>
You should see</p>
<pre>
*** Info: Generating /home/git/.ssh/id_rsa
Enter passphrase (empty for no passphrase):
</pre>
</li>
<li>Press enter to create with an empty passphrase and press enter again to confirm.</li>
<li>You should see
<pre>
*** Query: Do you want to use this identity to login to this machine? (yes/no)
</pre>
</li>
<li>Type
<pre>yes</pre>
</li>
<li>You should see
<pre>
*** Info: Adding to /home/git/.ssh/authorized_keys
*** Query: Shall I create an SSH2 DSA identity file for you? (yes/no)
</pre>
</li>
<li>Type
<pre>no</pre>
</li>
<li>
You should see</p>
<pre>*** Info: Configuration finished. Have fun!</pre>
</li>
</ul>
<p>We have now configured our Windows Server 2008 machine with Git and an account to use with SSH access. In the next blog post, I&#8217;ll cover installation and configuration of <a href="http://eagain.net/gitweb/?p=gitosis.git">Gitosis</a> to secure access and authentication of repositories.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2009/04/git-server-windows-2008/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Phil Haack on SOLID and dynamic languages&#8230;</title>
		<link>http://www.shannoncornish.com/blog/2009/02/phil-haack-on-solid-and-dynamic-languages/</link>
		<comments>http://www.shannoncornish.com/blog/2009/02/phil-haack-on-solid-and-dynamic-languages/#comments</comments>
		<pubDate>Sat, 31 Jan 2009 23:07:07 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=47</guid>
		<description><![CDATA[From twitter If the Interface Segregation Principle is less relevant for dynamic languages, does that mean SOLID => SOLD for dynamic languages? :P]]></description>
			<content:encoded><![CDATA[<p>From <a href="https://twitter.com/haacked/statuses/1165539441">twitter</a></p>
<blockquote><p>
If the Interface Segregation Principle is less relevant for dynamic languages, does that mean SOLID => SOLD for dynamic languages? :P</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2009/02/phil-haack-on-solid-and-dynamic-languages/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Link Blog</title>
		<link>http://www.shannoncornish.com/blog/2008/11/new-link-blog/</link>
		<comments>http://www.shannoncornish.com/blog/2008/11/new-link-blog/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 01:06:35 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=35</guid>
		<description><![CDATA[Just a quick update to say that I&#8217;m back from LA, running extremely late on my PDC posts and I&#8217;ve got a new link blog to boot! Using Google Reader Shared items, you can subscribe to posts I find interesting&#8230; Shannon&#8217;s shared items]]></description>
			<content:encoded><![CDATA[<p>Just a quick update to say that I&#8217;m back from LA, running extremely late on my PDC posts and I&#8217;ve got a new link blog to boot! Using Google Reader Shared items, you can subscribe to posts I find interesting&#8230;</p>
<p><a href="http://www.google.com/reader/shared/05384695639749622510"><br />
Shannon&#8217;s shared items</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2008/11/new-link-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PDC 2008 &#8211; Day 0</title>
		<link>http://www.shannoncornish.com/blog/2008/10/pdc-2008-day-0/</link>
		<comments>http://www.shannoncornish.com/blog/2008/10/pdc-2008-day-0/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 16:12:19 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[pdc2008]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=12</guid>
		<description><![CDATA[I attended the Concurrent Multi-Core programming pre con session by Joe Duffy, Stephen Toub and David Callahan. It was a very interesting session, with David providing an overview of the problem and the Steven and Joe sharing the presentation responsibilities for the rest of the day. A couple of themes came out in the talk, [...]]]></description>
			<content:encoded><![CDATA[<p>I attended the Concurrent Multi-Core programming pre con session by Joe Duffy, Stephen Toub and David Callahan. It was a very interesting session, with David providing an overview of the problem and the Steven and Joe sharing the presentation responsibilities for the rest of the day.</p>
<p>A couple of themes came out in the talk, being that scalable parallel programs will continue to see improvements, but single threaded software will not. Microsoft is moving away from a thread based model and more towards a task based model. Tasks are a more generic term for a unit of work which is more closely aligned with the problem domain. Another focus is on scalable data structures.</p>
<p>Stephen Toub presented on current ways to do concurrent programming in .NET using the existing frameworks.</p>
<ul>
<li>System.Threading.Thread</li>
<li>System.Threading.ThreadPool</li>
<li>Asynchronous delegate invocation</li>
<li>Asynchronous Programming Model</li>
</ul>
<p>An interesting item of note that using the ThreadPool to execute a delegate was faster than asynchronous delegate invocation, as the delegate invocation involves the remoting stack and then ends up using the ThreadPool anyway.</p>
<p>Manual thread management (calling Thread.Interupt, Thread.Abort, Thread.Pause &amp; Thread.Resume) was extremely discouraged. So much so, there was talk about these APIs being deprecated in a future version of the CLR.</p>
<ul>
<li><strong>Interupt</strong> only interupts a thread in a wait/sleep or join cycle. Calling this method will throw a ThreadInterruptException</li>
<li><strong>Abort</strong> will abort a thread at any moment (except during PInvoke) and will throw a ThreadAbortException. This exception is special cased by the runtime to rethrow this exception if you have caught it.</li>
<li><strong>Suspend/Resume</strong> will suspend the thread at any point, including inside a lock.</li>
</ul>
<p>In .NET, when you lock on an object, information is stored in the available memory associated with the object. The reason this is interesting is because this additional memory allows the CLR to take a &#8216;slim&#8217; lock rather than a &#8216;fat&#8217; lock. However, if you call <code>GetHashCode</code> on this object (unless you have overridden the base implementation), this memory is used to store hash code information, and any locks on this object will be &#8216;fat&#8217; locks.</p>
<p>Another interesting item is that items marked <code>ThreadStatic</code> will only be run once (not once per thread as you might assume). What this means is that if thread 1 loads up a class with a static field marked as <code>ThreadStatic</code>, it will have the expected value. If thread 2 then loads up this class, the static field will be null.</p>
<p>Joe Duffy gave a very low level talk on concurrency and shared state. It was an extremely interesting talk, about a quarter of which I was able to follow with my brain melting :(. An great example highlighted that on an x86 machine, setting an int64 value is not an atomic operation, and it&#8217;s possible for the value to be half set when the thread switches out. Compilers are free to re-order and inline statements, so you might get what you&#8217;ve asked for, but not what you&#8217;re written, which can have an impact if you&#8217;re sharing state across threads.</p>
<p><strong>Synchronization best practices (Stephen Toub)</strong></p>
<ul>
<li>Lock consistently
<ul>
<li>Do lock over all mutable shared state</li>
<li>Do Always use the same lock for the same state</li>
<li>Do comment on how state is protected</li>
</ul>
</li>
<li>Lock for the right duration
<ul>
<li>Do lock over the entire invariant</li>
<li>Don&#8217;t lock for longer than is absolutely necessary</li>
</ul>
</li>
<li>Make critical regions short and sweet
<ul>
<li>Do minimize the time you hold on to a lock</li>
<li>Don&#8217;t call other&#8217;s code while you hold lock</li>
<li>Don&#8217;t block while you hold lock</li>
</ul>
</li>
<li>Encapsulate your locks
<ul>
<li>Don&#8217;t use public lock objects</li>
<li>Don&#8217;t lock on Types or Strings</li>
</ul>
</li>
<li>Avoiding deadlocks
<ul>
<li>Do acquire locks in a consistent order</li>
</ul>
</li>
<li>Locking Misceallany
<ul>
<li>Do document your locking policy (especially for public APIs)</li>
<li>Do use a reader/writer lock if readers are common</li>
<li>Do prefer lock based code to lock free code</li>
<li>Do prefer monitors over kernel synchronization</li>
<li>Avoid lock recursion in your design</li>
<li>Don&#8217;t build your own locks</li>
<li>Avoid writing your own thread pool</li>
</ul>
</li>
</ul>
<p><strong>So what&#8217;s coming in .NET 4.0?</strong></p>
<ul>
<li>No real surprise, PLINQ and the Task Parallel Library (currently available in the Parallel Extensions CTP) will be included.</li>
<li>A Concurrency Runtime, consisting of an improved ThreadPool with a work stealing algorith, A new task scheduler and a resource manager.</li>
<li>Improved tooling support with parallel debugger windows and profiler concurrency analysis.</li>
<li>Data structures such as thread safe collections ConcurrentStack&lt;T&gt;, ConcurrentQueue&lt;T&gt; and ConcurrentDictionary&lt;K,V&gt;. Work exchange structures such as BlockingCollection&lt;T&gt; and new locks such as ManualResetEventSlim&lt;T&gt; and SemaphoneSlim&lt;T&gt;.</li>
</ul>
<p><strong>Concurrent Programming on Windows by Joe Duffy</strong><br />
It looks like the trend continues, I managed to win something by sticking my hands up and answering a quiz question :) I scored the first copy to be given away of Joe Duffy&#8217;s new Concurrent Programming book. This adds to the impressive list of list of things I&#8217;ve won at nerd events.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2008/10/pdc-2008-day-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello Hollywood Blvd</title>
		<link>http://www.shannoncornish.com/blog/2008/10/hello-hollywood-blvd/</link>
		<comments>http://www.shannoncornish.com/blog/2008/10/hello-hollywood-blvd/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 06:43:34 +0000</pubDate>
		<dc:creator>Shannon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[pdc2008]]></category>

		<guid isPermaLink="false">http://www.shannoncornish.com/blog/?p=3</guid>
		<description><![CDATA[After a long and tiring flight, I&#8217;ve finally arrived in LA. It&#8217;s hot. After an expensive taxi ride from LAX, I arrive at the hotel to find Scott Guthrie hacking away on his laptop in the lobby. At the reception, they inform me that they need my credit card, which they scan, then decline. Apparently [...]]]></description>
			<content:encoded><![CDATA[<p>After a long and tiring flight, I&#8217;ve finally arrived in LA.</p>
<p>It&#8217;s hot.</p>
<p>After an expensive taxi ride from LAX, I arrive at the hotel to find Scott Guthrie hacking away on his laptop in the lobby. </p>
<p>At the reception, they inform me that they need my credit card, which they scan, then decline. Apparently when you book a room they don&#8217;t charge the room, they wait until you get here and here I am without a corporate credit card or a room. 5 dollars, 5 minutes of internet usage later I&#8217;m back at reception, cashed up and manage to get into my room. </p>
<p>I manage to get in contact with Alex and we head out to Santa Monica Pier and the beach. We took some really cool photos and had the eerie experience of being familiar with a place you&#8217;ve never been too before&#8230;</p>
<p>Next up tomorrow is the pre conference&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shannoncornish.com/blog/2008/10/hello-hollywood-blvd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
