<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8336318365940619669</id><updated>2012-01-30T23:18:24.632+01:00</updated><category term='SOLID'/><category term='psake'/><category term='Python'/><category term='Lean'/><category term='MVVM'/><category term='MVC'/><category term='Castle.ActiveRecord'/><category term='Repository'/><category term='Software Craftsmanship'/><category term='AutoFixture'/><category term='VB.NET'/><category term='software design'/><category term='F#'/><category term='Boy Scout Rule'/><category term='Software Architecture'/><category term='RHoK'/><category term='Refactoring'/><category term='ASP.NET MVC'/><category term='Actor'/><category term='MongoDB'/><category term='C#'/><category term='xUnit'/><category term='NDepend'/><category term='Scala'/><category term='Opinion'/><category term='Scala-msil'/><category term='TDD'/><category term='PowerShell'/><category term='XmlUnit.Xunit'/><category term='Ruby'/><category term='active record'/><category term='Re-architecting'/><category term='functional programming'/><category term='Eclipse'/><category term='IronRuby'/><category term='Grails'/><category term='Flex'/><category term='NancyFx'/><category term='version control'/><category term='DCI'/><category term='Clean Code'/><category term='automation'/><category term='IronPython'/><category term='WPF'/><category term='Tiobe'/><category term='Entity Framework'/><category term='.NET'/><title type='text'>Horsdal</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4348429575067162980</id><published>2012-01-30T23:18:00.001+01:00</published><updated>2012-01-30T23:18:24.641+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Repository'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><category scheme='http://www.blogger.com/atom/ns#' term='SOLID'/><title type='text'>Repositories and Single Responsibility from the Trenches</title><content type='html'>In a project I'm involved with we've done what I suspect lots and lots of projects do. We've used the repository pattern to encapsulate database adds, queries and deletes. We have one such repository per entity type. That worked well for me in earlier projects. But in this case several of the repositories have become somewhat unfocused. None of them are big hairy monsters, but the different public methods really don't have much in common except the fact that they mainly act on the same entity type. In other words cohesion is low. Let me exemplify (anonymized just as the rest of the code in this post):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: hidden; width: 800px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IDeviceRepository&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; TDeviceType Get&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: blue;"&gt;long&lt;/span&gt; id) &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; TDeviceType FindByControllerIdentifier&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: blue;"&gt;string&lt;/span&gt; controllerIdentifer)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;TDeviceType&amp;gt; GetAll&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: blue;"&gt;int&lt;/span&gt; offset, &lt;span style="color: blue;"&gt;int&lt;/span&gt; max, &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? createdAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? updatedAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? disconnectedAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;int&lt;/span&gt; Count&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? createdAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? updatedAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;DateTimeOffset&lt;/span&gt;? disconnectedAfter = &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType: &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Add&amp;lt;TDeviceType&amp;gt;(TDeviceType device) &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;TDeviceType&amp;gt; GetAll&amp;lt;TDeviceType&amp;gt;() &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;TDeviceType&amp;gt; GetAll&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: blue;"&gt;long&lt;/span&gt;[] deviceIds) &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;TDeviceType&amp;gt; FindByControllerIdentifiers&amp;lt;TDeviceType&amp;gt;(&lt;span style="color: blue;"&gt;string&lt;/span&gt;[] controllerIdentifiers)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;where&lt;/span&gt; TDeviceType : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;NodeDevice&lt;/span&gt;&amp;gt; FindNodesDevicesForRootDevice(&lt;span style="color: blue;"&gt;string&lt;/span&gt; controllerIdentifier, &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; active = &lt;span style="color: blue;"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;ICollection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;NodeDevice&lt;/span&gt;&amp;gt; FindNodeDevicesForRootDevice(&lt;span style="color: blue;"&gt;long&lt;/span&gt; rootDeviceId, &lt;span style="color: blue;"&gt;bool&lt;/span&gt; active = &lt;span style="color: blue;"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;DeviceLink&lt;/span&gt;&amp;gt; GetTopology&amp;lt;T&amp;gt;(&lt;span style="color: blue;"&gt;long&lt;/span&gt; id, &lt;span style="color: blue;"&gt;bool&lt;/span&gt; active) &lt;span style="color: blue;"&gt;where&lt;/span&gt; T : &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;DeviceLink&lt;/span&gt; GetDeviceLink(&lt;span style="color: blue;"&gt;string&lt;/span&gt; controllerIdentifierA, &lt;span style="color: blue;"&gt;string&lt;/span&gt; controllerIdentifierB);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;DeviceLink&lt;/span&gt; GetDeviceLink(&lt;span style="color: blue;"&gt;long&lt;/span&gt; id);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddDeviceLink(&lt;span style="color: #2b91af;"&gt;DeviceLink&lt;/span&gt; link);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Route&lt;/span&gt;&amp;gt; FindRoutesByDeviceLink(&lt;span style="color: #2b91af;"&gt;DeviceLink&lt;/span&gt; deviceLink);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Delete(&lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt; device);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This doesn't look like the interface of a class that has only one reason to change - i.e. it violates the single responsibility principle (SRP). This is in part because it in fact does not only act on one entity type but on a hierarchy of entity types; device is a base class and the are a handful of concrete types of devices. The obvious solution to that, is to move away from a repository for the base class to a number of repositories for the concrete entities - but that's where we came from. That's a route that led to duplicated code, which led to abstracting into a common device repository, so we did not want to go back down that route again.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Taking Single Responsibility Seriously&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The solution we've come up with is - at it's core - simply to take SRP seriously: We want classes that do not do a bunch of database related operations around a type of enity. We want classes that does just one such operation. Take the Delete method on the interface above. That seems innocent enough, but it turns out that the implemetation is a bit complicated: There are a number of relations that need to be untied, and there is some cascading to take care of before the device can be deleted from the database. As a&amp;nbsp;colleague&amp;nbsp;commented: "It looks like a bad stored proc, written in C#". We decided to view that delete operation as "one thing", and decided it justified a class of its own:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 800px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DeleteDeviceRequest&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NHibernateWriteRequest&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt; device;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; DeleteDeviceRequest(&lt;span style="color: #2b91af;"&gt;Device&lt;/span&gt; device)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.device = device;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; DoExecute()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; links =&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; Session.QueryOver&amp;lt;&lt;span style="color: #2b91af;"&gt;DeviceLinkReference&lt;/span&gt;&amp;gt;().Where(x =&amp;gt; x.ControllerIdentifier == device.ControllerIdentifier).&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; List();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; links.ForEach(x =&amp;gt; x.Device = &lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DeleteStatistics();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DeleteRoutesWriteRequest&lt;/span&gt;(device.Routes).ExecuteWith(DataStore);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DeleteFromGroup();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DeleteFromOrder();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DeleteProfiles();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DataStore.Delete(device);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// more private methods...&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The only thing public here is the constructor. The contructor takes all arguments for the delete, so once the object is constructed it completely incapsulates the delete. And - importantly - it is incapable of doing anything else than that particular delete.&lt;br /&gt;How is the delete executed? -Through an execute method on the base class NHibernateWriteRequest.&lt;br /&gt;&lt;br /&gt;This swaps the repository pattern for the command pattern plus the template method pattern. But more importantly this swaps a small collection of ever growing repositories for a large collection of small never growing query classes (which, btw, also plays better into the open/closed principle). We've only just started down this path, but I think we'll be happy about it.&lt;br /&gt;&lt;br /&gt;There are a few twists I've left out, particularly around making these request objects easy to get at for client code, while maintaining encapsulation and testability. I might revisit those in a future post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4348429575067162980?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4348429575067162980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2012/01/repositories-and-single-responsibility.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4348429575067162980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4348429575067162980'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2012/01/repositories-and-single-responsibility.html' title='Repositories and Single Responsibility from the Trenches'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4211663295767319062</id><published>2011-12-20T21:07:00.000+01:00</published><updated>2011-12-20T21:07:37.274+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><category scheme='http://www.blogger.com/atom/ns#' term='NancyFx'/><title type='text'>Slides from ANUG talk on Nancy</title><content type='html'>I did a talk on Nancy a week ago in the Aarhus -NET User Group. And in my own humble and unbiased opinion it went quite well :-) So I thought I'd share the slides with you - although they probably only make semi-sense without the talk to go along. Anyway here they are; enjoy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_10650147" style="width: 425px;"&gt; &lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/c_horsdal/nancy-a-lightweight-net-web-framework" target="_blank" title="Nancy - A Lightweight .NET Web Framework"&gt;Nancy - A Lightweight .NET Web Framework&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/10650147" width="425"&gt;&lt;/iframe&gt; &lt;div style="padding: 5px 0 12px;"&gt; View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/c_horsdal" target="_blank"&gt;Christian Horsdal&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4211663295767319062?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4211663295767319062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/12/slides-from-anug-talk-on-nancy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4211663295767319062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4211663295767319062'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/12/slides-from-anug-talk-on-nancy.html' title='Slides from ANUG talk on Nancy'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-5440475176070503093</id><published>2011-12-05T21:38:00.001+01:00</published><updated>2011-12-05T22:03:01.070+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='XmlUnit.Xunit'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Announcing: XmlUnit.Xunit</title><content type='html'>&lt;br /&gt;I wanted to announce a small library I have on my GitHub: &lt;a href="https://github.com/horsdal/XmlUnit.Xunit"&gt;XmlUnit.Xunit&lt;/a&gt;, which a library for testing against XML. It's a port of &lt;a href="http://xmlunit.sourceforge.net/"&gt;XmlUnit &lt;/a&gt;over to use &lt;a href="http://xunit.codeplex.com/"&gt;Xunit.NET&lt;/a&gt; assertions instead of NUnit assertions, plus an addition of a fluent assertion style. The following is the projects README, and gives you a feel for the purpose of the project. Enjoy.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Intro&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;XmlUnit.Xunit provides Xunit.NET based assertions tailored to testing XML. The project contains assertions for comparing XML, applying XPath and XSLT expression to XML under test. All assertions come in two flavors: A traditional set of static assertion methods, and a fluent "should" style assertions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Usage&lt;/b&gt;&lt;br /&gt;You grab the source from here, download a build from &lt;a href="https://github.com/horsdal/XmlUnit.Xunit/downloads"&gt;here&lt;/a&gt;&amp;nbsp;or install &lt;a href="http://nuget.org/List/Packages/XmlUnit.Xunit"&gt;the NuGet package&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Beware that both the binary in the download tab and the NuGet package may give you assembly conflicts on Xunit.NET. To get around that you need an &lt;a href="http://horsdal.blogspot.com/2011/09/tip-for-making-autofixture-and-xunitnet.html"&gt;assmebly rebind of Xunit.NET&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Traditional Assertions&lt;/b&gt;&lt;br /&gt;The traditional assertions in XmlUnit.Xunit er all static methods on the class XmlAssertion, and are used like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 700px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;404&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;405&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertStringEqualAndIdenticalToSelf()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;406&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;407&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; control = &lt;span style="color: #a31515;"&gt;"&amp;lt;assert&amp;gt;true&amp;lt;/assert&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;408&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; test = &lt;span style="color: #a31515;"&gt;"&amp;lt;assert&amp;gt;true&amp;lt;/assert&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;409&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;XmlAssertion&lt;/span&gt;.AssertXmlIdentical(control, test);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;410&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;XmlAssertion&lt;/span&gt;.AssertXmlEquals(control, test);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;411&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;412&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;413&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; MY_SOLAR_SYSTEM =&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;414&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #a31515;"&gt;"&amp;lt;solar-system&amp;gt;&amp;lt;planet name='Earth' position='3' supportsLife='yes'/&amp;gt;&amp;lt;planet name='Venus' position='4'/&amp;gt;&amp;lt;/solar-system&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;415&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;416&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;417&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathExistsWorksForExistentXPath()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;418&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;419&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;XmlAssertion&lt;/span&gt;.AssertXPathExists(&lt;span style="color: #a31515;"&gt;"//planet[@name='Earth']"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;420&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; MY_SOLAR_SYSTEM);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;421&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;422&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;423&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;424&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathEvaluatesToWorksForMatchingExpression()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;425&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;426&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;XmlAssertion&lt;/span&gt;.AssertXPathEvaluatesTo(&lt;span style="color: #a31515;"&gt;"//planet[@position='3']/@supportsLife"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;427&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MY_SOLAR_SYSTEM,&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;428&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #a31515;"&gt;"yes"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;429&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;430&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;431&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;432&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXslTransformResultsWorksWithStrings()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;433&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;434&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; xslt = &lt;span style="color: #2b91af;"&gt;XsltTests&lt;/span&gt;.IDENTITY_TRANSFORM;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;435&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; someXml = &lt;span style="color: #a31515;"&gt;"&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;b/&amp;gt;&amp;lt;/a&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;436&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;XmlAssertion&lt;/span&gt;.AssertXslTransformResults(xslt, someXml, someXml);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;437&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;438&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fluent Assertions&lt;/b&gt;&lt;br /&gt;The fluent assertions are all extension methods with names starting with Should, and are used like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 575px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;404&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;405&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertStringEqualAndIdenticalToSelf()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;406&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;407&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; control = &lt;span style="color: #a31515;"&gt;"&amp;lt;assert&amp;gt;true&amp;lt;/assert&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;408&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; test = &lt;span style="color: #a31515;"&gt;"&amp;lt;assert&amp;gt;true&amp;lt;/assert&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;409&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; test.ShouldBeXmlIdenticalTo(control);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;410&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; test.ShouldBeXmlEqualTo(control);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;411&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;412&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;413&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; MY_SOLAR_SYSTEM =&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;414&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #a31515;"&gt;"&amp;lt;solar-system&amp;gt;&amp;lt;planet name='Earth' position='3' supportsLife='yes'/&amp;gt;&amp;lt;planet name='Venus' position='4'/&amp;gt;&amp;lt;/solar-system&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;415&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;416&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;417&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathExestsWorksForXmlInput()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;418&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;419&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;XmlInput&lt;/span&gt;(MY_SOLAR_SYSTEM)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;420&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .XPath(&lt;span style="color: #a31515;"&gt;"//planet[@name='Earth']"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;421&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExist();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;422&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;423&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;424&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;425&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathEvaluatesToWorksForMatchingExpression()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;426&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;427&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; MY_SOLAR_SYSTEM&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;428&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .XPath(&lt;span style="color: #a31515;"&gt;"//planet[@position='3']/@supportsLife"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;429&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldEvaluateTo(&lt;span style="color: #a31515;"&gt;"yes"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;430&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;431&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;432&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;433&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathExistsWorksWithXpathFirstWithXmlInput()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;434&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;435&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; sut = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;XmlInput&lt;/span&gt;(MY_SOLAR_SYSTEM);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;436&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;437&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #a31515;"&gt;"//planet[@name='Earth']"&lt;/span&gt;.AppliedTo(sut).ShouldExist();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;438&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;439&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;440&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;441&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXPathEvaluatesToWorksWithXPathFirst()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;442&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;443&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #a31515;"&gt;"//planet[@position='3']/@supportsLife"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;444&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .AppliedTo(MY_SOLAR_SYSTEM)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;445&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldEvaluateTo(&lt;span style="color: #a31515;"&gt;"yes"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;446&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;447&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;448&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;449&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AssertXslTransformResultsWorksWithStrings()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;450&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;451&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; xslt = &lt;span style="color: #2b91af;"&gt;XsltTests&lt;/span&gt;.IDENTITY_TRANSFORM;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;452&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; someXml = &lt;span style="color: #a31515;"&gt;"&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;&amp;lt;b/&amp;gt;&amp;lt;/a&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;453&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;454&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; someXml.XsltTransformation(xslt).ShouldResultIn(someXml);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;455&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Further Information&lt;/b&gt;&lt;br /&gt;Is probably best gleened off &lt;a href="https://github.com/horsdal/XmlUnit.Xunit/tree/master/XmlUnit.xUnitTests"&gt;the tests&lt;/a&gt;&amp;nbsp;in this project, especially the tests for &lt;a href="https://github.com/horsdal/XmlUnit.Xunit/blob/master/XmlUnit.xUnitTests/XmlAssertionTests.cs"&gt;XmlAssertions&lt;/a&gt; and the tests for &lt;a href="https://github.com/horsdal/XmlUnit.Xunit/blob/master/XmlUnit.xUnitTests/XmlShouldAssertionTests.cs"&gt;Should assertions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Contribute&lt;/b&gt;&lt;br /&gt;Please do! Fork, code, send pull request. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-5440475176070503093?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/5440475176070503093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/12/announcing-xmlunitxunit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/5440475176070503093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/5440475176070503093'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/12/announcing-xmlunitxunit.html' title='Announcing: XmlUnit.Xunit'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-8713407883509787366</id><published>2011-11-08T22:27:00.000+01:00</published><updated>2011-11-08T22:30:26.766+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='NancyFx'/><title type='text'>Frictionless .NET Web App Development with Nancy Part IV - Hosting</title><content type='html'>Continuing my URL shortener sample (part &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html"&gt;I&lt;/a&gt;, &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_16.html"&gt;II&lt;/a&gt;, &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_24.html"&gt;III&lt;/a&gt;), I'll talk about one the things &lt;a href="http://www.nancyfx.org/"&gt;Nancy&lt;/a&gt;&amp;nbsp;does quite differently from your average web framework: Nancys concept of hosting. At this point you may be thinking serves or clouds or storage etc, but that's not exactly what Nancy hosting is about.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nancy Hosting&lt;/b&gt;&lt;br /&gt;Nancy hosting is about which stack Nancy runs on top of. Such stacks include ASP.NET, WCF, &lt;a href="http://owin.org/"&gt;OWIN&lt;/a&gt;, and self hosting. That means that a Nancy app can be run on top of any of those four hosts. You decide. So if you have an existing ASP.NET/IIS setup you can use it to run Nancy, if you have a WCF setup already you can use that.&lt;br /&gt;&lt;br /&gt;The two last hosts may need a bit of introduction:&lt;br /&gt;&lt;br /&gt;OWIN is Open Web Interface for .NET, which is an attempt to create a common interface between web frameworks and web servers. Currently it's not implemented by that many web servers, but could potentially allow web frameworks and the apps built on them to be move unchanged from one web server to another. One example of an OWIN compliant web server is Kayak, which can run on Mono. Combining these things means that our Nancy app can run on a stack of Nancy/Hosting.OWIN/&lt;a href="https://github.com/kayak/kayak"&gt;Kayak&lt;/a&gt;/&lt;a href="http://www.mono-project.com/Main_Page"&gt;Mono&lt;/a&gt;/Linux. In other words a web app written in C# running on OSS all the way down. Who'd have thunk!&lt;br /&gt;&lt;br /&gt;Self hosting is another interesting option: Self hosting means running a Nancy app in any .NET or Mono executable. This means that you can slap a web interface onto a desktop app or a windows service. Both of these possiblities are very interesting IMO.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Multiple Hosts - One Code Base&lt;/b&gt;&lt;br /&gt;In the URL shortener sample I'd like to use the same application in two different settings: In a stand alone executable (just for kicks) and in ASP.NET stack. To do that I add two projects to my solution, one for each host:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-FF_-X_wJvs8/TrmX_T5vpZI/AAAAAAAAEYE/kQ9QaRR4FqM/s1600/solution+ex+-+closed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/-FF_-X_wJvs8/TrmX_T5vpZI/AAAAAAAAEYE/kQ9QaRR4FqM/s640/solution+ex+-+closed.png" width="444" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;First lets look at bit closer at the ASP.NET hosting project. I.e. the one called ShortUrlWebApp. It's simply an empty web project, as created by Visual Studio, with the Nancy.Hosting.Aspnet &lt;a href="http://www.nuget.org/"&gt;NuGet &lt;/a&gt;package and a project reference to ShortUrl added. Not &lt;i&gt;one&lt;/i&gt; line of code wirtten. The project contains:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-t2U80Kq8NHA/TrmYnWgxVZI/AAAAAAAAEYM/Vpl2fPsj55Q/s1600/solution+ex+-+web+app+open.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/-t2U80Kq8NHA/TrmYnWgxVZI/AAAAAAAAEYM/Vpl2fPsj55Q/s640/solution+ex+-+web+app+open.png" width="446" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The Nancy.Hosting.Aspnet NuGet rewrites the web.config to make Nancy handle all incoming request. Nancy automatically picks up the Bootstrapper and Module in the ShortUrl assembly. That's all there is to running our url shortener on top of ASP.NET.&lt;br /&gt;&lt;br /&gt;Second lets loot at the self hosting project. I.e. the one called ShortUrlDesktopApp. It's just a console application with a project reference to ShortUrl and the Nancy.Hosting.Self NuGet added:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-k99cIC6Qf30/TrmZAl4v26I/AAAAAAAAEYU/FDq1m9A-1YI/s1600/solution+ex+-+both+open.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-k99cIC6Qf30/TrmZAl4v26I/AAAAAAAAEYU/FDq1m9A-1YI/s640/solution+ex+-+both+open.png" width="446" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;In this case a little bit of work is needed in the program.cs - but not much, just instantiating and starting the NancyHost:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 625px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrlDesktopApp&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy.Hosting.Self;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; ShortUrl;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Program&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;  &amp;nbsp; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color: blue;"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;   {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; artificiaReference;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; nancyHost = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;NancyHost&lt;/span&gt;(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"http://localhost:8080/"&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; nancyHost.Start();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Console&lt;/span&gt;.ReadKey();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; nancyHost.Stop();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;With this setup we can run the app on ASP.NET of from a console app. There is no difference in the browser and the application code is the same. This - IMO - is very cool indeed.&lt;br /&gt;&lt;br /&gt;And the code is still on &lt;a href="https://github.com/horsdal/ShortURL"&gt;GitHub&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-8713407883509787366?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/8713407883509787366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/11/frictionless-net-web-app-development.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8713407883509787366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8713407883509787366'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/11/frictionless-net-web-app-development.html' title='Frictionless .NET Web App Development with Nancy Part IV - Hosting'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-FF_-X_wJvs8/TrmX_T5vpZI/AAAAAAAAEYE/kQ9QaRR4FqM/s72-c/solution+ex+-+closed.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-2141676996382246834</id><published>2011-10-24T22:29:00.000+02:00</published><updated>2011-10-24T22:29:19.498+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='NancyFx'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Frictionless .NET Web App Development with Nancy Part III - Introducing MongoDB</title><content type='html'>Continuing the URL shortener sample from thesse post: &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html"&gt;part I&lt;/a&gt; and &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_16.html"&gt;part II&lt;/a&gt;, I'll go from (stupidly) storing the shortened URLs in a static variable, as was the case in the code in &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_16.html"&gt;part I&lt;/a&gt;, to storing the shortened URLs in &lt;a href="http://www.google.dk/url?sa=t&amp;amp;rct=j&amp;amp;q=mongodb&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CCcQFjAA&amp;amp;url=http%3A%2F%2Fwww.mongodb.org%2F&amp;amp;ei=_8GlTpb8G4zN4QSUkvXmBA&amp;amp;usg=AFQjCNFkupTrrD2YYX6ydM2wb9IbWll3Vw"&gt;MongoDB&lt;/a&gt;. The reasons for choosing MongoDB for persistence in this sample (compared to the "traditional" NHibernate + SQL Server approach) are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;We will only store and retrieve one document at a time. Those are atomic operations in Mongo, so as far as this sample goes Mongo is fully consistent.&lt;/li&gt;&lt;li&gt;Mongo is simple to setup, and very simple to code against. For instance there is no O/R mapping layer at all.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In summary, Mongo is a nice frictionless option for this sample.&lt;br /&gt;&lt;br /&gt;Enough talk, show me the code!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Decoupling interface from persistence&lt;/b&gt;&lt;br /&gt;The first thing to do is to pull the persistence related code out of the &lt;a href="http://www.nancyfx.orf/"&gt;Nancy&lt;/a&gt;&amp;nbsp;module. We use the following couple of tests to drive that. They use a &lt;a href="http://www.google.dk/url?sa=t&amp;amp;rct=j&amp;amp;q=moq&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CCIQFjAA&amp;amp;url=http%3A%2F%2Fcode.google.com%2Fp%2Fmoq%2F&amp;amp;ei=YcKlTtDREOjl4QSz9ry_CQ&amp;amp;usg=AFQjCNFt1wxK2x8HQzwQzpfGgSTeDtLRRQ"&gt;Moq &lt;/a&gt;&lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;mock &lt;/a&gt;to specify the interface to the persistence code; that is the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;interface:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 640px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrlTest&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Xunit;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy.Testing;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Moq;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; ShortUrl;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;UrlStorageTest&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Browser&lt;/span&gt; app;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Mock&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt;&amp;gt; fakeStorage;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; UrlStorageTest()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; artificiaReference;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Given&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; fakeStorage = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Mock&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; app = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Browser&lt;/span&gt;(&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ConfigurableBootstrapper&lt;/span&gt;(&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with =&amp;gt; with.Dependency(fakeStorage.Object)));&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; app_should_store_url_when_one_is_posted()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//When&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; app.Post(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with =&amp;gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;   &amp;nbsp; with.FormValue(&lt;span style="color: #a31515;"&gt;"url"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://www.longurlplease.com/"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with.HttpRequest();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; fakeStorage&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Verify(store =&amp;gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; store.SaveUrl(&lt;span style="color: #a31515;"&gt;"http://www.longurlplease.com/"&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt;.IsAny&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt;()));&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; app_should_try_to_retrieve_url_when_getting_a_short_url()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//When&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; app.Get(&lt;span style="color: #a31515;"&gt;"/shorturl"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with =&amp;gt; with.HttpRequest());&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; fakeStorage&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Verify(store =&amp;gt; &lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; store.GetUrlFor(&lt;span style="color: #a31515;"&gt;"shorturl"&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;A few interesting things go on in these tests.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Firstly&lt;/b&gt;, as stated above they specifify the interface &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore&lt;/span&gt;. They do so via the mock &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;fakeStorage&lt;/span&gt;, and the calls to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;fakeStorage.Verify(...)&lt;/span&gt; which tells us that &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;should have two methods, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SaveUrl &lt;/span&gt;and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GetUrlFor&lt;/span&gt;.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Secondly &lt;/b&gt;we again use the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Nancy.Testing.Browser&lt;/span&gt; type to call into the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ShortUrl&lt;/span&gt; Nancy module. Remember that this goes though the whole Nancy pipeline, just like a real request from a browser. So we're genuinely testing the module from the outside. In the first test we do a HTTP POST, and in the second one we do a HTTP GET.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Thirdly &lt;/b&gt;in the constructor we're using another feature of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Nancy.Testing&lt;/span&gt;; the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ConfigurableBootstrapper&lt;/span&gt;. To understand this bit, a little detour is required. Nancy is very modular, everything in Nancy can be swapped for an alternative implementation via configuration. Furthermore Nancy apps uses &lt;a href="http://martinfowler.com/articles/injection.html"&gt;IoC/DI&lt;/a&gt; from the get go. Out of the box Nancy uses &lt;a href="https://github.com/grumpydev/TinyIoC"&gt;TinyIOC&lt;/a&gt;, but that can (of course) be swapped with any other container - and NuGets exists for most (if not all) popular containers. The swapping out of things in Nancy apps is done through code, in a bootstrapper, which is a class in the app that implements &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;INancyBootstrapper&lt;/span&gt;, and sets up the whole of Nancy and the app. To make this easy Nancy provides the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DefaultNancyBootstrapper&lt;/span&gt; which can be used as the base class for app specific bootstrappers. Back to tests above. The &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ConfigurableBootstrapper&lt;/span&gt;, provides a simple way for tests to create specialized configurations through a &lt;a href="http://martinfowler.com/bliki/FluentInterface.html"&gt;fluent interface&lt;/a&gt;. The contructor in the code above registers the mock &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;as a dependincy, which means registering it in the TinyIOC container. In other words the parts of a the app that receives a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;from the container will get the mock one when in the context of these tests.&lt;br /&gt;&lt;br /&gt;But the UrlStore interface doesn't exists, so lets write it to make the tests compile:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrl&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SaveUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; url, &lt;span style="color: blue;"&gt;string&lt;/span&gt; shortenedUrl);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; GetUrlFor(&lt;span style="color: blue;"&gt;string&lt;/span&gt; shortenedUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The tests don't run yet though, since our app does not use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;at all. To make it do so, we change the application code to take a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;in the module contructor, and use it for storage (particularly lines 7, 14 and 22):&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 750px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrl&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NancyModule&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;   &lt;span style="color: blue;"&gt;public&lt;/span&gt; ShortUrlModule(&lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt; urlStore)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   Get[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;gt; View[&lt;span style="color: #a31515;"&gt;"index.html"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; Post[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;gt; ShortenUrl(urlStore);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/{shorturl}"&lt;/span&gt;] = param =&amp;gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;   &lt;span style="color: blue;"&gt;string&lt;/span&gt; shortUrl = param.shorturl;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; Response.AsRedirect(urlStore.GetUrlFor(shortUrl.ToString()));&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; };&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Response&lt;/span&gt; ShortenUrl(&lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt; urlStore)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   &lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl = Request.Form.url;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; shortUrl = ShortenUrl(longUrl);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; urlStore.SaveUrl(longUrl, shortUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View[&lt;span style="color: #a31515;"&gt;"shortened_url"&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt; { Request.Headers.Host, ShortUrl = shortUrl }];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: #a31515;"&gt;"a"&lt;/span&gt; + longUrl.GetHashCode();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;And that makes the above tests run. But the end-to-end tests shown in &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html"&gt;part I&lt;/a&gt; don't run. The reason is they don't register a UrlStore with the container. They use the DefaultNancyBootstrapper, where no &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;is setup. To get past this we need to do a few things: Change the end-to-end tests to use an app specific bootstrapper, create an implementation of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;that uses Mongo, and create an app specific bootstrapper. We'll start by driving out the Mongo implementation of UrlStore.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Shifting gears&lt;/b&gt;&lt;br /&gt;To implement &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;against Mongo we need to shift TDD gears to using integration tests. The following tests, that drive the implementation of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MongoUrlStore&lt;/span&gt; assume a Mongo server is running on localhost at port 27010:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 700px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrlTest&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Bson;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Driver;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Driver.Builders;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; ShortUrl.DataAccess;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Xunit;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoUrlStoreTest&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; connectionString = &lt;span style="color: #a31515;"&gt;"mongodb://localhost:27010/short_url_test"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoDatabase&lt;/span&gt; database;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoCollection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;BsonDocument&lt;/span&gt;&amp;gt; urlCollection;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; MongoUrlStoreTest()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//given&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; database = &lt;span style="color: #2b91af;"&gt;MongoDatabase&lt;/span&gt;.Create(connectionString);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; urlCollection = database.GetCollection(&lt;span style="color: #a31515;"&gt;"urls"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urlCollection.RemoveAll();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_store_urls_in_mongo()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//when&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; store = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoUrlStore&lt;/span&gt;(connectionString);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; store.SaveUrl(&lt;span style="color: #a31515;"&gt;"http://somelongurl.com/"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://shorturl/abc"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; urlFromDB = urlCollection&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Find(&lt;span style="color: #2b91af;"&gt;Query&lt;/span&gt;.EQ(&lt;span style="color: #a31515;"&gt;"url"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://somelongurl.com/"&lt;/span&gt;))&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .FirstOrDefault();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.NotNull(urlFromDB);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.Equal(urlFromDB[&lt;span style="color: #a31515;"&gt;"shortenedUrl"&lt;/span&gt;], &lt;span style="color: #a31515;"&gt;"http://shorturl/abc"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_be_able_to_find_shortened_urls()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//given&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; store = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoUrlStore&lt;/span&gt;(connectionString);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; store.SaveUrl(&lt;span style="color: #a31515;"&gt;"http://somelongurl.com/"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://shorturl/abc"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//when&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; longUrl = store.GetUrlFor(&lt;span style="color: #a31515;"&gt;"http://shorturl/abc"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.Equal(&lt;span style="color: #a31515;"&gt;"http://somelongurl.com/"&lt;/span&gt;, longUrl);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;These two test cases simply use the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UrlStore &lt;/span&gt;interface, but also go directly to the Mongo instance to check that things are stored there. This is all quite straight forward, the one thing to notice though is that these test only assume that there is a Mongo server running, not that there is any particular database or collection present from the start. This is one of the ways Mongo is easy to work with, the databases and collections used in the code are just created for us behind the scenes. No friction.&lt;br /&gt;To satisfy these tests we simply implement the UrlStore interface as follows:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 520px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrl.DataAccess&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Bson;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Driver;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; MongoDB.Driver.Builders;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoUrlStore&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoDatabase&lt;/span&gt; database;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoCollection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;BsonDocument&lt;/span&gt;&amp;gt; urls;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; MongoUrlStore(&lt;span style="color: blue;"&gt;string&lt;/span&gt; connectionString)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; database = &lt;span style="color: #2b91af;"&gt;MongoDatabase&lt;/span&gt;.Create(connectionString);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; urls = database.GetCollection(&lt;span style="color: #a31515;"&gt;"urls"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SaveUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; url, &lt;span style="color: blue;"&gt;string&lt;/span&gt; shortenedUrl)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; urls.Insert(&lt;span style="color: blue;"&gt;new&lt;/span&gt; {url, shortenedUrl});&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; GetUrlFor(&lt;span style="color: blue;"&gt;string&lt;/span&gt; shortenedUrl)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; urlDocument =&amp;nbsp; &lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urls&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;   &amp;nbsp; &amp;nbsp; &amp;nbsp; .Find(&lt;span style="color: #2b91af;"&gt;Query&lt;/span&gt;.EQ(&lt;span style="color: #a31515;"&gt;"shortenedUrl"&lt;/span&gt;, shortenedUrl))&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;   &amp;nbsp; &amp;nbsp; .FirstOrDefault();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urlDocument == &lt;span style="color: blue;"&gt;null&lt;/span&gt; ? &lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;null&lt;/span&gt; : urlDocument[&lt;span style="color: #a31515;"&gt;"url"&lt;/span&gt;].AsString;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The thing I really want to point out here is line 21. We just tell Mongo to store an anonymous object and the driver does the rest for us (i.e. serializes it to json). No O/R mapping code!&lt;br /&gt;Now we have an interface for persisting things, our module uses that interface, and we have an implemtation of it against Mongo. The only thing remaining is wiring things up.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Shifting gears back the end-to-end tests&lt;/b&gt;&lt;br /&gt;As mentioned earlier the end-to-end tests from &lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html"&gt;part I&lt;/a&gt; don't run right now, to make them run we first change their setup to use an app specific bootstrapper:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 10pt; overflow-x: auto; overflow-y: auto; width: 500px;"&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;    &lt;span style="color: blue;"&gt;public&lt;/span&gt; BaseUrlSpec()&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;  {&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;    &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; artificiaReference;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;  app = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Browser&lt;/span&gt;(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Bootstrapper&lt;/span&gt;());&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;   }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;We've changed line 17 to use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Bootstrapper &lt;/span&gt;instead of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DefaultNancyBootstrapper&lt;/span&gt;. The type &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Bootstrapper &lt;/span&gt;does not exists yet, so lets create it, and have it register &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MongoUrlStore &lt;/span&gt;with the container:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 800px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ShortUrl&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; DataAccess;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Bootstrapper&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;DefaultNancyBootstrapper&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ConfigureApplicationContainer(TinyIoC.&lt;span style="color: #2b91af;"&gt;TinyIoCContainer&lt;/span&gt; container)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;base&lt;/span&gt;.ConfigureApplicationContainer(container);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; mongoUrlStore = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MongoUrlStore&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"mongodb://localhost:27010/short_url"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; container.Register&amp;lt;&lt;span style="color: #2b91af;"&gt;UrlStore&lt;/span&gt;&amp;gt;(mongoUrlStore);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;We use the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DefaultNancyBootstrapper &lt;/span&gt;as a starting point, and just use one its hooks to do a little bit of app specific setup, namely registering &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MongoUrlStore&lt;/span&gt;. Using other overrides we could configure anything in Nancy. I really like that a lot.&lt;br /&gt;&lt;br /&gt;Well that's it. All tests run again.&lt;br /&gt;&lt;br /&gt;Updated code is a available on &lt;a href="https://github.com/horsdal/ShortURL"&gt;GitHub&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-2141676996382246834?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/2141676996382246834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_24.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2141676996382246834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2141676996382246834'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_24.html' title='Frictionless .NET Web App Development with Nancy Part III - Introducing MongoDB'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4096382285310178633</id><published>2011-10-16T22:28:00.000+02:00</published><updated>2011-11-08T22:35:36.913+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NancyFx'/><title type='text'>Frictionless .NET Web App Development with Nancy Part II - Introducing a View Engine</title><content type='html'>In the&lt;a href="http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html"&gt; last post&lt;/a&gt; I introduced a litte sample web app coded up with the &lt;a href="http://www.nancyfx.org/"&gt;Nancy&lt;/a&gt; web framework. The code presented in that post left a few things open for later enhancement. This post takes a stab one of those things: The part where a string.Format is used to create a bit of html, which is then just returned directly to the client, namely the POST action in this code:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 575px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NancyModule&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Dictionary&lt;/span&gt;&amp;amp;amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;amp;amp;gt; urlMap = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Dictionary&lt;/span&gt;&amp;amp;amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;amp;amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ShortUrlModule()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;amp;amp;gt; View[&lt;span style="color: #a31515;"&gt;"index.html"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Post[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;amp;amp;gt; ShortenUrl();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl = Request.Form.url;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; shortUrl = ShortenUrl(longUrl);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urlMap[shortUrl] = longUrl;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; ShortenedUrlView(shortUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: #a31515;"&gt;"a"&lt;/span&gt; + longUrl.GetHashCode();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;29&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenedUrlView(&lt;span style="color: blue;"&gt;string&lt;/span&gt; shortUrl)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515;"&gt;"&amp;lt;a id=\"shorturl\" href=\"http://{0}/{1}\"&amp;gt;;http://{0}/{1}&amp;lt;/a&amp;gt;"&lt;/span&gt;, Request.Headers.Host, shortUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Specifically the last method, 'ShortenedUrlView' is bad code: It's brittle, it doesn't produce valid HTML, and it's open for script injection. Therefore I want to separate that bit of view code from the module code: I want a view engine. Luckily Nancy supports a number of standard view engines(&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx"&gt;Razor&lt;/a&gt;, &lt;a href="http://sparkviewengine.com/"&gt;Spark&lt;/a&gt;, &lt;a href="http://dotliquidmarkup.org/"&gt;DotLiquid&lt;/a&gt;, &lt;a href="http://ndjango.org/index.php?title=NDjango_Home"&gt;NDjango&lt;/a&gt;) each of which are only a NuGet package away, but it also comes with its own appropriately named &lt;a href="https://github.com/grumpydev/SuperSimpleViewEngine"&gt;Super Simple View Engine&lt;/a&gt;, SSVE. For this sample SSVE will do, so let's just stick with that.&lt;br /&gt;&lt;br /&gt;We add a file called shortened_url.sshtml to the Views folder and put this into it:&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;a id="shorturl" href="http://@Model.Host/@Model.ShortUrl"&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; http://@Model.Host/@Model.ShortUrl&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/a&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;As with Razor views the @ indicates code snippets. In the above we insert 'Host' and 'ShortUrl' properties from the view model in the view.&lt;br /&gt;&lt;br /&gt;To use this we also need to modify the Nancy module code a bit. We need to return a View[] instead of simply a string:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 580px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Response&lt;/span&gt; ShortenUrl()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl = Request.Form.url;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; shortUrl = ShortenUrl(longUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urlMap[shortUrl] = longUrl;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View[&lt;span style="color: #a31515;"&gt;"shortened_url"&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; { Host = Request.Headers.Host, ShortUrl = shortUrl }];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: #a31515;"&gt;"a"&lt;/span&gt; + longUrl.GetHashCode();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;We saw use of View[] last time, this time around we provide a model object along with the view name. This object is passed to the view code as the @Model.&lt;br /&gt;&lt;br /&gt;That's it. Introduced a view engine. No friction.&lt;br /&gt;&lt;br /&gt;The &lt;a href="https://github.com/horsdal/ShortURL"&gt;code &lt;/a&gt;for this sample is still available on GitHub. Now with the updates described here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4096382285310178633?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4096382285310178633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_16.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4096382285310178633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4096382285310178633'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development_16.html' title='Frictionless .NET Web App Development with Nancy Part II - Introducing a View Engine'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-408970624943629509</id><published>2011-10-10T22:34:00.000+02:00</published><updated>2011-10-12T13:24:00.522+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='NancyFx'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Frictionless .NET Web App Development with Nancy</title><content type='html'>&lt;br /&gt;This post is about a low ceremony approach to web apps in .NET. It's about just writting the app, without the framework getting in the way. It's about the same sort of feeling that&amp;nbsp;&lt;a href="https://twitter.com/mookid8000"&gt;Mogens Heller Grabe&lt;/a&gt; talks about with his notion of &lt;a href="http://channel9.msdn.com/Events/GOTO/GOTO-2011-Copenhagen/Frictionless-Persistence-in-NET-with-MongoDB"&gt;frictionless persistence with MongoDB&lt;/a&gt;. Only here it's about the web part.&lt;br /&gt;&lt;br /&gt;I'll take you through a short and simple URL shortener sample app done with the &lt;a href="http://www.nancyfx.org/"&gt;Nancy &lt;/a&gt;web framework. A couple of more posts will probably follow on the subjects of view engines, persistence and hosting for this app. Also with an eye on low ceromony and frictionsless development.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is Nancy?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;Nancy is a lightweight open source web framework in .NET. It has a declared goal of being the developers super-duper-happy-path. Nancy is lightweight in the sense that the number of concepts and the amount syntax you have to grok is minimal. That's why I like it, and that's why it provides the frictionless experience I'm after here.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;First things first: The first red-green cycle&lt;/b&gt;&lt;br /&gt;One of the first very nice things to notice about Nancy is that it supports TDD really well (much more so than ASP.NET MVC), so lets start looking at the sample by looking at the first test:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 550px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;BaseUrlSpec&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_respond_ok()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; app = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Browser&lt;/span&gt;(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DefaultNancyBootstrapper&lt;/span&gt;());&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; response&amp;nbsp; = app.Get(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;, with =&amp;gt; with.HttpRequest());&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; statusCode = response.StatusCode;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.Equal(&lt;span style="color: #2b91af;"&gt;HttpStatusCode&lt;/span&gt;.OK, statusCode);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This is just an &lt;a href="http://agileotter.blogspot.com/2008/12/unit-test-ice-breakers.html"&gt;ice breaker test&lt;/a&gt; to get us going: It just tests that our app responds with an http 200 OK status code. There are nevertheless a couple of things to notice:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Nancy.Testing provides us with the Browser class, which gives our tests an easy way to interact with the app as if they were a browser: The browser object allows for doing GET, PUT, POST and DELETE, PATCH and OPTIONS against the app, including setting up the body, the headers and the protocol. In the case of the above we're doing a GET over http to the relative URL "/", no body, no special headers.&lt;/li&gt;&lt;li&gt; Nancy.Testing also provides a BrowserResponse type that allows for testing all sorts of things on the response from the app. The variable 'response' in the above has this type. Here we just check the status code, but in later examples we'll do a lot more.&lt;/li&gt;&lt;/ol&gt;There, that's the red part.&lt;br /&gt;&lt;br /&gt;To make this run we only have to write this little snippet of Nancy based code:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NancyModule&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ShortUrlModule()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] =_ =&amp;gt; &lt;span style="color: #2b91af;"&gt;HttpStatusCode&lt;/span&gt;.OK;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Firstly this little piece of code shows the central concept of Nancy: It provides a DSL for responding to http requests. It does so by letting you specify what code should run on GET, PUT, POST, DELETE, PATCH and OPTIONS requests for different URIs. In the above we only specify one such action for one URI: GET for '/'. Secondly it shows another defining trait of Nancy: The framework really tries to make things easy for you, in this case illustrated by the fact we just return a 200 OK status code, but Nancy accepts that and turns it into a full response for us.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;GETting the form&lt;/b&gt;&lt;br /&gt;So returning a 200 OK does not make for much of an app. What we want here is a very simple URL shortener, so lets turn the front page of the app into a form with a field for the URL the user wants shortened and a submit button. Again we start with a test:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 710px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_contain_a_form_with_an_input_field_for_a_url_and_a_button()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//when&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; baseUrlGetResponse = app.Get(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;, with =&amp;gt; with.HttpRequest());&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; baseUrlGetResponse.Body[&lt;span style="color: #a31515;"&gt;"form"&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExist();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; baseUrlGetResponse.Body[&lt;span style="color: #a31515;"&gt;"input#url"&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExistOnce();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; baseUrlGetResponse.Body[&lt;span style="color: #a31515;"&gt;"label"&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExistOnce().And&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldContain(&lt;span style="color: #a31515;"&gt;"Url: "&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; baseUrlGetResponse.Body[&lt;span style="color: #a31515;"&gt;"input#submit"&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExistOnce();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here we see some more of Nancys test emphasis: The BrowseResponse type mentioned above provides a Body property that lets our tests search through the body of the response using CSS selectors and make assertions on the results using a set of fluent 'Should' style extensions. For instance the above asserts that there is exactly one input tag with the id 'url' and that there is one label tag which furthermore contains the text 'Url: '. This, I must sat, is just awesome, and is a very good level to test at: Just below the pixels of the UI, and just above the real http stack of the real web server.&lt;br /&gt;&lt;br /&gt;To make this run we need only do slightly more than in the previous cycle: We alter the application code to this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NancyModule&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ShortUrlModule()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;gt; View[&lt;span style="color: #a31515;"&gt;"index.html"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;and add the following index.html file to a Views folder:&lt;br /&gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;form method="post"&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;label&amp;gt;Url: &amp;lt;/label&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;input type="text" name="url" id="url"/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;input type="submit" value="shorten" id="submit"/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;Now we see Nancy trying to make things easy again: Just indicate in the application code that you want to return a view by saying View["index.html"], and Nancy looks in your views folders, finds the view and off we go.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;POSTing the form&lt;/b&gt;&lt;br /&gt;Next step is reacting to a POST of the form we just made, by shortening the URL. Let's set up a test for that:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 610px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_return_shortened_url_when_posting_url()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//when&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; baseUrlPostResponse = app.Post(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with =&amp;gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with.FormValue(&lt;span style="color: #a31515;"&gt;"url"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://http://www.longurlplease.com/"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with.HttpRequest();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; baseUrlPostResponse.Body[&lt;span style="color: #a31515;"&gt;"a#shorturl"&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldExist().And&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldContain(&lt;span style="color: #a31515;"&gt;"http://"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here we see how the app object is used for sending a POST to the app, and along with it the appropriate form values; in this case just the url. This starts to show the flexibility and ease of use of the Browser type.&lt;br /&gt;&lt;br /&gt;Considering how we've handled the GET request until now, handling the POST is as straightforward:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 850px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; Nancy;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShortUrlModule&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;NancyModule&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt; urlMap = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ShortUrlModule()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;gt; View[&lt;span style="color: #a31515;"&gt;"index.html"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Post[&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;] = _ =&amp;gt; ShortenUrl();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl = Request.Form.url;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; shortUrl = ShortenUrl(longUrl);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; urlMap[shortUrl] = longUrl;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; ShortenedUrlView(shortUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenUrl(&lt;span style="color: blue;"&gt;string&lt;/span&gt; longUrl)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: #a31515;"&gt;"a"&lt;/span&gt; + longUrl.GetHashCode();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;29&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ShortenedUrlView(&lt;span style="color: blue;"&gt;string&lt;/span&gt; shortUrl)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515;"&gt;"&amp;lt;a id=\"shorturl\" href=\"http://{0}/{1}\"&amp;gt;http://{0}/{1}&amp;lt;/a&amp;gt;"&lt;/span&gt;, Request.Headers.Host, shortUrl);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This is all pretty straight forward. The Nancy parts of this are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The use of POST...which does just what you expect.&lt;/li&gt;&lt;li&gt;The return of a string in the last method. That bubles all the way up, and becomes the repsonse back to Nancy. Again Nancy is nice to us, sets the content type to text/html and the status code to 200 OK. This is not the nicest code on my part, so I might just return to refactor it in a future post.&lt;/li&gt;&lt;/ol&gt;The above of course is not very clever about the shortening, and does not exactly persist the short URLs in a good permanent place. I'll return to the persistence in a furture post.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Redirect&lt;/b&gt;&lt;br /&gt;Only one part is missing for a simplistic but functioning URL shortener: The app must redirect the shortened URLs to the original longer one.&lt;br /&gt;Again lets start with the test:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 650px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Fact&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should_redirect_to_original_url_when_getting_short_url()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//when&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; baseUrlPostResponse = app.Post(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with =&amp;gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with.FormValue(&lt;span style="color: #a31515;"&gt;"url"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"http://www.longurlplease.com/"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with.HttpRequest();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }).GetBodyAsXml();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; shortUrl = baseUrlPostResponse&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Element(&lt;span style="color: #a31515;"&gt;"a"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Attribute(&lt;span style="color: #a31515;"&gt;"href"&lt;/span&gt;).Value&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Split(&lt;span style="color: #a31515;"&gt;'/'&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .Last();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; app.Get(&lt;span style="color: #a31515;"&gt;"/"&lt;/span&gt; + shortUrl, with =&amp;gt; with.HttpRequest())&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .ShouldHaveRedirectedTo(&lt;span style="color: #a31515;"&gt;"http://www.longurlplease.com/"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;We do the POST again, find the short URL with a bit of LINQ-to-xml and then do a GET to that. And then just assert that the redirect happened. Pretty straight forward except maybe for the Linq-to-xml part.&lt;br /&gt;&lt;br /&gt;To make the last test run we add this to our application code:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;14&lt;/span&gt;&amp;nbsp; Get[&lt;span style="color: #a31515;"&gt;"/{shorturl}"&lt;/span&gt;] = param =&amp;gt;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;15&lt;/span&gt;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;16&lt;/span&gt; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; shortUrl = param.shorturl;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;17&lt;/span&gt; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; Response.AsRedirect(urlMap[shortUrl.ToString()]);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;18&lt;/span&gt;&amp;nbsp; };&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;which is an action for a whole set of URIs, namely the URIs matching the URI template "/{shorturl}". In the action we access the 'shorturl' part of the URI through the param.shorturl; all parts of the templatized URI will be availbe like that through the dynamic param. Nice.&lt;br /&gt;&lt;br /&gt;That's it. We have a simplistic URL shortener. No friction.&lt;br /&gt;&lt;br /&gt;The source is &lt;a href="https://github.com/horsdal/ShortURL"&gt;availble on github&lt;/a&gt;, and more Nancy information is avaible on the &lt;a href="http://www.nancyfx.org/"&gt;Nancy web site&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-408970624943629509?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/408970624943629509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/408970624943629509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/408970624943629509'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/10/frictionless-net-web-app-development.html' title='Frictionless .NET Web App Development with Nancy'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-7243435090869171705</id><published>2011-09-06T22:24:00.000+02:00</published><updated>2011-09-06T22:25:58.853+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='AutoFixture'/><title type='text'>Tip for making AutoFixture and xUnit.net play nice</title><content type='html'>Just a quick tip, for making &lt;a href="http://autofixture.codeplex.com/"&gt;AutoFixture &lt;/a&gt;2.1 play nice with newer &lt;a href="http://xunit.codeplex.com/"&gt;xUnit.net&lt;/a&gt; versions:&lt;br /&gt;&lt;br /&gt;I installed Autofixture via NuGet, which gave me AutoFixture 2.1 and xUnit 1.7, when running my tests they threw this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;System.IO.FileNotFoundException:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Could not load file or assembly&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;'Ploeh.AutoFixture, Version=2.1.0.1, Culture=neutral,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;PublicKeyToken=b24654c590009d4f'&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;or one of its dependencies.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;The system cannot find the file specified.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The reason is that the test runner thinks that AutoFixture needs and older version of xUnit (&lt;a href="http://autofixture.codeplex.com/workitem/4241"&gt;although it doesn't really&lt;/a&gt;).&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The solution is to put this in the app.config for the test projects:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;runtime&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;assemblyBinding&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;urn:schemas-microsoft-com:asm.v1&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;dependentAssembly&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;assemblyIdentity&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;xunit.extensions&lt;/span&gt;"&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: red;"&gt;publicKeyToken&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;8d05b1bb7a6fdb6c&lt;/span&gt;"&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: red;"&gt;culture&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;neutral&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;bindingRedirect&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;oldVersion&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;1.6.1.1521&lt;/span&gt;"&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: red;"&gt;newVersion&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;1.7.0.1540&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;dependentAssembly&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;assemblyBinding&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;runtime&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;You'll probably have to fix up the newVersion to the exact version you have.&lt;br /&gt;&lt;br /&gt;That's it for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-7243435090869171705?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/7243435090869171705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/09/tip-for-making-autofixture-and-xunitnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/7243435090869171705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/7243435090869171705'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/09/tip-for-making-autofixture-and-xunitnet.html' title='Tip for making AutoFixture and xUnit.net play nice'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-2671568940778595449</id><published>2011-09-05T10:39:00.002+02:00</published><updated>2011-09-05T10:39:53.785+02:00</updated><title type='text'>Upcoming Events</title><content type='html'>I have couple of events coming up that I thought I'd share here: &lt;a href="http://aaosconf.eventbrite.com/"&gt;The Agile Architecture Open Space Conference&lt;/a&gt; and an &lt;a href="http://www.anug.dk/"&gt;ANUG &lt;/a&gt;code camp on enhancing legacy test suites.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Agile Architecture Open Space Conference&lt;/b&gt;&lt;br /&gt;On the 29th and 30th of September a couple of&amp;nbsp;colleagues&amp;nbsp;and I are running a small conference under the headline of sustainable architecture in an agile world. It's an open space conference, so there's next to no official program. But there is plenty of room for in-depth discussions and networking. With the line up of attendees so far I think it'll be awesome. There are still a few spaces left, so check it out at&amp;nbsp;&lt;a href="http://aaosconf.eventbrite.com/"&gt;http://aaosconf.eventbrite.com/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Enhancing Legacy Test Suites&lt;/b&gt;&lt;br /&gt;On the 19th of November I'll be running a code camp on the subject of enhancing legacy test suites. It'll be a longer, more in-depth and more hands-on version of the &lt;a href="http://horsdal.blogspot.com/2011/05/take-away-points-from-my-software.html"&gt;workshop &lt;/a&gt;on the same subject I did at &lt;a href="http://www.codemanship.co.uk/softwarecraftsmanship/programme.html"&gt;SC2011&lt;/a&gt;. The premise of the code camp is that we see more and more code bases with some automated tests around them, but these tests are often lacking in quality. The tests are sometimes just there to cover&amp;nbsp;somebody's&amp;nbsp;ass, sometimes they are very&amp;nbsp;tightly&amp;nbsp;coupled to the implementation, sometimes they are flaky, and they almost always cover only a fraction of the production code.&lt;br /&gt;At the code camp we'll dive into techniques to improve this situation, and move towards a situation where the test suite is an asset. Where the tests are not a&amp;nbsp;burden&amp;nbsp;to maintain, and where they provide the confidence they should.&lt;br /&gt;I'll start the day by introducing a few techniques, and an example code base with some tests associated. The bulk of the day will be spent applying the techniques to the example code base through a number of iterations with tasks set be me for each one. Should be a lot of hacking fun&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-2671568940778595449?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/2671568940778595449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/09/upcoming-events.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2671568940778595449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2671568940778595449'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/09/upcoming-events.html' title='Upcoming Events'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-8602708094703694052</id><published>2011-08-29T23:25:00.000+02:00</published><updated>2011-08-29T23:26:39.913+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><title type='text'>Developer Survey Results - Part 4</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;This is the forth and last post in my series summaries of the develop practices survey I ran &amp;nbsp;(the other posts are &lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-1.html"&gt;here&lt;/a&gt;, &lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-2.html"&gt;here &lt;/a&gt;and &lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-3.html"&gt;here&lt;/a&gt;).&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;This one is about practices to ensure code quality. But tool driven things. I'm less interested in the use &lt;a href="http://en.wikipedia.org/wiki/Lint_(software)"&gt;LINT-style&lt;/a&gt; tools, than in the use reviews, pair programming and refactoring. so the last ones were the ones I asked about.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Asking "do you pair programming" survey says:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table id="table#26" style="border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 239px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, all the time&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;2%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, often&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;6%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, from time to time&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;19%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;No, almost never&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;47%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;No, never&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;18%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;In other words, next to no respondents practice pairing often, and two thirds almost never or never practice it. , I honestly almost never pair myself. &amp;nbsp;Can't decide if this is good or bad.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Next question was if respondents use code reviews. The responses were:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table id="table#27" style="border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 243px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, all code is reviewed&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;6%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, most code is reviewed&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;16%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Yes, some code is reviewed&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;27%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;No, almost no code is reviewed&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;34%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;No, never&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;8%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Again usage is pretty low. Now, this I do think is a waste. In my experience reviews really do work, when they are kept at the right balance between the totally informal "just discussing stuff" and the totally formal "you have to sign this before you leave".&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Of the 92% that do use code reviews on at least at bit of code now and then, the types of reviews used were:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table id="table#28" style="border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 342px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Formal reviews with formal approvals&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;4%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Formal reviews without formal approvals&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;17%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Code walk throughs&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;48%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td active="" class="ss-table-label" design="" reviews&lt;="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;" td=""&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Active design reviews&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;7%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;"Hey, come take a look at this code on my screen"&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;72%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;The weight here is one the more informal review types. Not surprising I guess. They are easy and cheap. And they &lt;i&gt;can&lt;/i&gt;&amp;nbsp;return a lot of value.Lastly I asked about a personal favorite - something I think is absolutely&amp;nbsp;necessary&amp;nbsp;in order keep code maintainable: "Do you use refactoring?" The responses were:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;table id="table#29" style="border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 372px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;Yes, I always try to leave the code cleaner than I found it&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;26%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;Yes, from time to time&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;44%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;Yes, as separate tasks&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;10%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;No&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;11%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;Other&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #cccccc; font-family: Verdana, sans-serif;"&gt;10%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Which is a fairly good note to end on :-)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-8602708094703694052?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/8602708094703694052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/08/developer-survey-results-part-4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8602708094703694052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8602708094703694052'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/08/developer-survey-results-part-4.html' title='Developer Survey Results - Part 4'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-7532593047904945930</id><published>2011-07-31T22:04:00.009+02:00</published><updated>2011-07-31T22:52:57.098+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><title type='text'>Developer Survey Results - Part 3</title><content type='html'>This is the third part of my walk through of the results of a survey I recently did (&lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-1.html"&gt;part 1&lt;/a&gt;, &lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-2.html"&gt;part 2&lt;/a&gt;). This time I focus on practices around&amp;nbsp;continuous&amp;nbsp;integration.&lt;br /&gt;&lt;br /&gt;The survey shows that 58% of respondents use CI, which &amp;nbsp;is fewer than I expected.&lt;br /&gt;&lt;br /&gt;Those who use CI have their CI servers do different things. The answers show respondents use their servers to:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table id="table#22" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; font-size: 1em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 390px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Build&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;94%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Run unit tests&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;86%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Run integration tests&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;75%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Run system tests&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;22%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Run UI tests&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;14%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Run acceptance tests&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;14%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Create release or deployment package&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;58%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Create tag/branch in source control on success&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;19%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Deploy to non-production environment (like test or staging)&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;22%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Deploy to production&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;11%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Other&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #f3f3f3; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #f3f3f3; font-family: Verdana, sans-serif;"&gt;8%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div&gt;So - not surprisingly - people build their code on the CI server. Then they seem to run the tests they've written - the numbers for running different kinds of tests align nicely with the numbers for writing different kinds of tests (see &lt;a href="http://horsdal.blogspot.com/2011/07/developer-survey-results-part-1.html"&gt;part 1&lt;/a&gt;). Furthermore over half create releases of deployment packages. That's pretty high, I think - even if it's only just over half of the half of the respondents that use CI at all; i.e. about a quarter of all respondents. Only very few take the next step and actually deploy to production. This is as expected; continuous deployment is still pretty new.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next question how often CI runs and it shows that by far most people have it running on every commit.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Turning to how often things brake the distribution is as follows:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;table id="table#24" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; font-size: 1em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 239px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Most of the time&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;11%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Several times a day&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;3%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Once a day&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;33%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Once a week&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;42%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Once a month&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;6%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Never&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;3%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Other&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;3%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So its seems something is broken sort of often. Is that a problem? -Not in my opinion. It just shows that the CI server finds stuff. What could be a problem is if this stuff isn't fixed. Asking about how long from something brakes to work to fix it is started the answer were:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;table id="table#25" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-bottom-width: 0px; border-collapse: collapse; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; empty-cells: show; font-size: 1em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 239px;"&gt;&lt;tbody style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within 15 minutes&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;22%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within an hour&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;47%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within half a day&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;14%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within a day&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;11%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within a week&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;3%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Within a month&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;0%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Never&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;3%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="ss-table-label" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: top; white-space: nowrap;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;Other&lt;/span&gt;&lt;/td&gt;&lt;td class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;/td&gt;&lt;td class="ss-table-number" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: black; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;/td&gt;&lt;td class="ss-table-percentage" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 1.38em; padding-right: 0px; padding-top: 0px; text-align: right; vertical-align: top;"&gt;&lt;span class="Apple-style-span" style="color: #eeeeee; font-family: Verdana, sans-serif;"&gt;0%&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;which I thinks shows that the issues found by CI are taken seriously.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all, it's a mixed impression on this one: Too few do any CI, but those who do have it build, run the tests they have, and create releases. And they react quickly to issues.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-7532593047904945930?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/7532593047904945930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-3.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/7532593047904945930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/7532593047904945930'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-3.html' title='Developer Survey Results - Part 3'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-8673829785393597065</id><published>2011-07-06T21:10:00.000+02:00</published><updated>2011-07-06T21:10:01.004+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><title type='text'>Developer Survey Results - Part 2</title><content type='html'>This second part of my walk through of the result of a survey I did recently focuses on practices around source control.&lt;br /&gt;&lt;br /&gt;Again this section of the survey started by asking if respondents use source control at all. Luckily most did, 95% (although, what do those last five percent do? -They also answered that they code more than 10% of their time at work).&lt;br /&gt;&lt;br /&gt;So looking at the distribution among source control systems, the results were:&lt;br /&gt;&lt;br /&gt;&lt;table id="table#15"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Sourcesafe&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;6%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;TFS&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;11%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;CVS&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;2%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;SVN&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;72%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Git&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;22%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Mercurial&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;6%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;ClearCase&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;17%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Other&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;11%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;This is not to be seen as an indication of the popularity of each of these vcs's in general, just as background on what the respondents to this survey use. And, as can be seen, this is an SVN crowd. That may very well have an effect on the rest of the answers in this section.&lt;br /&gt;&lt;br /&gt;How often do respondents commit, then? -I think this an important indicator of how developers work. Do they take small focused steps, or big leaps of faith? Well, here are the results:&lt;br /&gt;&lt;br /&gt;&lt;table id="table#16"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;All the time&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;3%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Several times an hour&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;6%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;About once an hour or every other hour&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;18%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;About twice a day&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;34%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;About once a day&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;23%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;About once a week&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;3%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;About once a month&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;0%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;So the weight here is around the twice a day answer. Some a bit more often than that, and some a bit less often that than. That's OK. I've seen shops where the norm was committing once a month. Awful. But these result do - on the other hand - leave room for improvement. I don't think commiting once an hour is unreasonable for the vast majority of development tasks. And more often if you're using a distributed version control system.&lt;br /&gt;&lt;br /&gt;Last question in this section was about how the VCS is used in terms of branching and the likes. Results are:&lt;br /&gt;&lt;br /&gt;&lt;table id="table#17"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Feature branches&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;39%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Experimentation branches&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;35%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Release branches&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;59%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Tags&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;57%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;None of the above&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;15%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="ss-table-label"&gt;Other&lt;/td&gt;&lt;td class=""&gt;&lt;/td&gt;&lt;td class="ss-table-percentage"&gt;0%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Don't know what to say about this. People use some amount branching generally it seems, but I suspect some of these would differ if most respondents had been Git users instead of SVN users. I don't know.&lt;br /&gt;&lt;br /&gt;Next section of the survey was about continuous integration. I'll cover that in my next post.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-8673829785393597065?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/8673829785393597065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-2.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8673829785393597065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8673829785393597065'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-2.html' title='Developer Survey Results - Part 2'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4538015096957323472</id><published>2011-07-01T22:40:00.001+02:00</published><updated>2011-07-01T22:41:13.787+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><title type='text'>Developer Survey Results - Part 1</title><content type='html'>I ran a survey recently asking about a variety of practices on the developer level. The survey is now closed and the results are in.&lt;br /&gt;The areas covered in the survey were test automation, source control,&amp;nbsp;continuous&amp;nbsp;integration, and code quality assurance. Nothing too fancy, but a collection of practices that I consider important, and which are all quite well known. I was curious to see how wide spread these practices are.&lt;br /&gt;&lt;br /&gt;In this post I'll cover the results of the first part.I got 62 responses to the survey. Not enough for statistical significance. And there's probably also some bias in the group, since they come mainly from my network. So don't take the results for more than they are.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Test Automation Practices&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So 71% of respondents use automated tests. That's pretty high. And then again it's sort of low. The benefits of test automation are so widely accepted, that did actually expect this number to be even higher.The next few questions where only asked of the respondents that use automated tests.Here's how many respondents use&amp;nbsp;each type of test automation:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Unit tests&lt;/td&gt;&lt;td&gt;95%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Integration tests&lt;/td&gt;&lt;td&gt;80%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Systems tests&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;UI tests&lt;/td&gt;&lt;td&gt;14%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Acceptance tests&lt;/td&gt;&lt;td&gt;16%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Performance tests &amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Load tests&lt;/td&gt;&lt;td&gt;11%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;So unit tests and integration tests are wide used, while the rest are only sporadically used. No big surprise, I'd say.&lt;br /&gt;&lt;br /&gt;Next I asked how much of the code is covered. This is an important question; there's a lot of difference in what tests gives you between having low coverage percentages, having high percentage and having 100%. So how much do respondents cover?&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;0-25%&lt;/td&gt;&lt;td&gt;14%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25-50%&lt;/td&gt;&lt;td&gt;34%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50-75%&lt;/td&gt;&lt;td&gt;36%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;75-100%&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;I can't estimate that &amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;td&gt;2%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Not too high.So who writes those tests?&lt;br /&gt;&lt;br /&gt;&lt;table id="table#12"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;I do&lt;/td&gt;&lt;td&gt;98%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The testers do&lt;/td&gt;&lt;td&gt;9%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The business people do &amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;td&gt;0%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;...responds writes their own tests. That's good.So when are the tests written?&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Before the production code (test first)&lt;/td&gt;&lt;td&gt;3%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Along side the production code&lt;br /&gt;(sometimes before, sometimes right after)&lt;/td&gt;&lt;td&gt;47%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shortly after the production&lt;br /&gt;(after production code, but in the same workflow)&lt;/td&gt;&lt;td&gt;19%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;After the production code for a complete feature is finished &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;td&gt;2%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;During a separate test phase&lt;/td&gt;&lt;td&gt;0%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;...so mainly alongisde or shortly after. But not before. This probably explains why the coverage percentages seem to be a bit low.&lt;br /&gt;&lt;br /&gt;OK, I'll the rest of the interpretation to you.&lt;br /&gt;&lt;br /&gt;Next post I'll go through the result for the source control questions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4538015096957323472?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4538015096957323472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-1.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4538015096957323472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4538015096957323472'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/07/developer-survey-results-part-1.html' title='Developer Survey Results - Part 1'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-2867159297277400788</id><published>2011-05-27T20:07:00.000+02:00</published><updated>2011-05-27T20:07:50.195+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Take-Away Points From my Software Craftmanship 2011 Session</title><content type='html'>At the &lt;a href="http://www.softwarecraftsmanship.org.uk/"&gt;Software Craftsmanship 2011&lt;/a&gt; conference yesterday I had the pleasure of running a workshop on how to deal with "legacy" test suites. A part from having a lot fun I also learned a lot from the discussions during the workshop.&lt;br /&gt;&lt;br /&gt;The premise of the workshop was a problem that I think is becoming more and more common: Even though more and more code bases have test suites around them, the quality of those tests are low. This lack of quality can stem from a number of things. First of all most automated tests, in my experience, still aren't written in a TDD workflow, they are written some time after the production code. Sometimes right after, sometimes days or weeks later. Secondly automated testing efforts sometimes seem to lack a clear purpose. Lastly test suites are often (as in very often) abandoned as soon the project comes under any sort of pressure - from deadlines, budgets, changing requirements or whatever else. These things lead to test suites that are treated as second or third class code; code that is not seen as important. That leads to a range of problems, such as tests with bland names - like test001 - tests that assert nothing or next to nothing, tests that just mimic the structure of the implementation without showing or exercising the behaviour from a domain/specification perspective and to low coverage of both code and features.&lt;br /&gt;&lt;br /&gt;To get concrete we took a hard look at the tests for the &lt;a href="http://nerddinner.codeplex.com/"&gt;NerdDinner &lt;/a&gt;sample application. In there we found most of the problems listed above, which begs the question given that we where taking over maintainance and future development of NerdDinner how would we proceed with regard to the tests. Clearly the existing tests are not at a quality level that would allow us to have confidence in the changes to NerdDinner we make just based on the tests running. On the other hand they do cover about a third of the code, and most of them do assert stuff. So if one of them was to break that likely indicates a problem.&lt;br /&gt;&lt;br /&gt;The discussion during the workshop seemed to divide people into two camps: One that said, that these test are not worth carrying forward because they will require maintainance while not providing any real value as regressions guards or as specifications. The other camp said, keep them and incrementally improve or delete them, keeping in mind that we dont know how valid the individual tests are.&lt;br /&gt;&lt;br /&gt;To sum up the main points I got from the throw the test away camp were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Since coverage is way too low, we're better off with a small number of broad acceptance tests. We can write those in the initial iteration, where we need to familiarize ourselves with the code base anyway.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Tests that don't assert much just gives us false confidence, so they are a liability that we don't want to keep them around.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Tests that don't work as specifications are mainly a confusion to us, because we don't have access to the people that wrote, and consequently can't find out what the purpose of those tests was.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It's simply quicker to write a bunch of exploratory tests, than it is to try to understand and maintain the existing ones.&lt;/li&gt;&lt;/ul&gt;And the main points I got from the keep the tests camp were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Even though there are problems with the tests, each of them were written with some sort of a goal in mind. As such we suspect that they can point out something we haven't realized yet.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The tests are just another part of the code base, and as such it's natural that we will have to refactor - and improve - them over time.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;We can put the legacy tests in some kind of a quarantine, where we keep running them but don't necessarily trust them, and when one breaks we take look at it and then decide to either delete the test or fix it and move it from the quarantined suite to our normal test suite.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule"&gt;The Boy Scout Rule&lt;/a&gt; applies to tests as well. Use that as the discipline to incrementally improve the tests.&lt;/li&gt;&lt;/ul&gt;In general I'm in the keep the tests camp, but I guess it really comes down to making an informed decision on a case-by-case basis. Which camp are you in? Or which points do think we missed?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-2867159297277400788?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/2867159297277400788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/05/take-away-points-from-my-software.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2867159297277400788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/2867159297277400788'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/05/take-away-points-from-my-software.html' title='Take-Away Points From my Software Craftmanship 2011 Session'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-9025302737766382860</id><published>2011-05-04T07:59:00.001+02:00</published><updated>2011-05-04T13:17:04.218+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><category scheme='http://www.blogger.com/atom/ns#' term='DCI'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Building DCI Context with ASP.NET MVC</title><content type='html'>In this post I'll address one of the questions that I tend to get when talking about &lt;a href="http://www.artima.com/articles/dci_vision.html"&gt;DCI&lt;/a&gt;: How is the DCI context built at runtime?&lt;br /&gt;&lt;br /&gt;To that end lets expand a bit on the DCI with ASP.NET MVC sample that I showed in an &lt;a href="http://horsdal.blogspot.com/2011/01/doing-dci-with-aspnet-mvc.html"&gt;earlier post&lt;/a&gt;. The focus of that post was how to fit ASP.NET MVC and DCI together in a nice cohesive architecture. In this post I will zoom in on how the controller can build up the DCI context object in a conversation with the user.&lt;br /&gt;&lt;br /&gt;The example I'm using is still that of a very simplified online bank, where the user can trasfer money between accounts. The core DCI parts of this example is explained in&amp;nbsp;&lt;a href="http://horsdal.blogspot.com/2009/05/dci-in-c.html"&gt;this post&lt;/a&gt;, and the connection with ASP.NET MVC in &lt;a href="http://horsdal.blogspot.com/2011/01/doing-dci-with-aspnet-mvc.html"&gt;this post&lt;/a&gt;. Whereas the sample in the last post simply asked the user to input all the information about the transfer in one screen, this version asks for the information one thing at a time in a wizard like fashion. Whether this is good UX, is besides the point of this post. I just want to use an example where the context is build in a series of interactions with the user.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Interaction Between User and Code&lt;/b&gt;&lt;br /&gt;First off the user is asked to choose a source account on this simple (ugly) page:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-nVGB9hyTbck/TcBzITN6rjI/AAAAAAAAEV8/O7epQ7gvbwA/s1600/Choose+source+account.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="287" src="http://4.bp.blogspot.com/-nVGB9hyTbck/TcBzITN6rjI/AAAAAAAAEV8/O7epQ7gvbwA/s400/Choose+source+account.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Serving up this page is done by this rather straight forward action method:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; SelectSource()&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;    Session[&lt;span style="color: #a31515;"&gt;"Context"&lt;/span&gt;] = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt; View(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SelectAccountVm&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;    &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SelectedAccountId = &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Empty,&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Accounts = accountRepo.Accounts&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Worth noticing though, is that a MoneyTransferContext object is created and stored in the session.&lt;br /&gt;When the user hits the Next button this action is hit:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 10pt; overflow: auto; width: 750px;"&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;HttpPost&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; SelectSource(&lt;span style="color: #2b91af;"&gt;SelectAccountVm&lt;/span&gt; model)&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;    &lt;span style="color: blue;"&gt;var&lt;/span&gt; ctx = Session[&lt;span style="color: #a31515;"&gt;"Context"&lt;/span&gt;] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Source = &lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;accountRepo.GetById(&lt;span style="color: blue;"&gt;int&lt;/span&gt;.Parse(model.SelectedAccountId)) &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySource&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View(&lt;span style="color: #a31515;"&gt;"SelectDestination"&lt;/span&gt;, &lt;/pre&gt;&lt;div style="color: black;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace; white-space: pre;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;62&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SelectAccountVm&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;     SelectedAccountId = &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Empty,&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Accounts = accountRepo.Accounts&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/pre&gt;&lt;pre style="color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #ededed; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;This code updates the context with the chosen source account, and serves the next view in the interaction, where the user is asked for a destination account:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-dPJiPeaErY0/TcBzwqTXb3I/AAAAAAAAEWA/akKokIg_BBs/s1600/Choose+destination+account.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="287" src="http://4.bp.blogspot.com/-dPJiPeaErY0/TcBzwqTXb3I/AAAAAAAAEWA/akKokIg_BBs/s400/Choose+destination+account.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;When the user hits this Next button this action is hit:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto; width: 750px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;69 &lt;/span&gt;[&lt;span style="color: #2b91af;"&gt;HttpPost&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; SelectDestination(&lt;span style="color: #2b91af;"&gt;SelectAccountVm&lt;/span&gt; model)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;    &lt;span style="color: blue;"&gt;var&lt;/span&gt; ctx = Session[&lt;span style="color: #a31515;"&gt;"Context"&lt;/span&gt;] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Sink = &lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   accountRepo.GetById(&lt;span style="color: blue;"&gt;int&lt;/span&gt;.Parse(model.SelectedAccountId)) &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySink&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View(&lt;span style="color: #a31515;"&gt;"SelectAmount"&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SelectAmountVm&lt;/span&gt;());&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;which does almost the same as the previous action, except it puts the chosen account in the Sink property on the context, and then shows this page:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-_wT2y1Kx4M8/TcB0BlmD13I/AAAAAAAAEWE/-Rf24G6SgAE/s1600/Choose+amount.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="230" src="http://4.bp.blogspot.com/-_wT2y1Kx4M8/TcB0BlmD13I/AAAAAAAAEWE/-Rf24G6SgAE/s320/Choose+amount.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The post from this page does a bit more work. First it updates the context with the amount given by the user. At this point the MoneyTransferContext is complete and ready to be exectued. Finally a result page is shown:&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;br /&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;[&lt;span style="color: #2b91af;"&gt;HttpPost&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; SelectAmount(&lt;span style="color: #2b91af;"&gt;SelectAmountVm&lt;/span&gt; model)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;    &lt;span style="color: blue;"&gt;var&lt;/span&gt; ctx = Session[&lt;span style="color: #a31515;"&gt;"Context"&lt;/span&gt;] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Amount = model.SelectedAmount;&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Execute();&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;86&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; ResultPage(ctx);&lt;/pre&gt;&lt;pre style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;87&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;88&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;and the result page is:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-vv93kiLv6TA/TcB0TWMCXmI/AAAAAAAAEWI/Gt78JxiepUE/s1600/Result.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="287" src="http://3.bp.blogspot.com/-vv93kiLv6TA/TcB0TWMCXmI/AAAAAAAAEWI/Gt78JxiepUE/s400/Result.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summing Up&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To sum up: To build up a DCI context in ASP.NET MVC simply store a context object in the session context when a use case is started and execute it when it makes sense from a functionality perspective. This way the controller code is kept very simple, concentrating only on building up the context through interaction with the user, and the details of the use case execution is - from the perspective of the cotroller - hidden behind the context. Furthermore because of the way the controller builds the context the context object only knowns the domain objects through the roles they have been assigned by the controller - or in fact the user - allowing for the full strenght of DCI to play out there.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;You can find the complete code from this post on &lt;a href="https://github.com/horsdal/DCI-ASP.NET-MVC"&gt;GitHub&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-9025302737766382860?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/9025302737766382860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/05/building-dci-context-with-aspnet.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/9025302737766382860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/9025302737766382860'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/05/building-dci-context-with-aspnet.html' title='Building DCI Context with ASP.NET MVC'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-nVGB9hyTbck/TcBzITN6rjI/AAAAAAAAEV8/O7epQ7gvbwA/s72-c/Choose+source+account.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-8182958921016977339</id><published>2011-04-06T16:13:00.000+02:00</published><updated>2011-04-06T16:13:14.632+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NDepend'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Impressions of NDepend</title><content type='html'>&lt;br /&gt;I've been giving &lt;a href="http://www.ndepend.com/"&gt;NDepend&lt;/a&gt; a go lately, in part because I've had my eye on it for a while, and in part because &lt;a href="http://www.dotnetguru2.org/psmacchia/index.php"&gt;Patrick Smacchia&lt;/a&gt; offered me free trial of NDpedend Pro recently&lt;br /&gt;&lt;br /&gt;I decided to try out NDpedend in a few different scenarios, that relate to different ways I might use it at work, so I spent a few hours with NDepend on three different code bases&lt;br /&gt;&lt;ol&gt;&lt;li&gt; A small code base - ~3KLOC - that I know quite well because I wrote 80% of it. &lt;/li&gt;&lt;li&gt; A medium sized code base - ~70KLOC - that I also know well because I worked on the team that wrote. But I only wrote a small portion of it myself. &lt;/li&gt;&lt;li&gt; A small code base - ~5KLOC - that I don't know at all. -I've only had a 10 minute intro to the architecture. &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;These, IMHO, span a number of scenarios where I might use NDepend: From scenarios where I know the code well, but want NDepend to help keeping myself and my team in check, to scenarios where I am reviewing or taking over an unknown code base, and want NDepend to help me get an overview and to help me drill into problematic areas.&lt;br /&gt;&lt;br /&gt;Ok, but lets back up a bit: What is NDepend? -NDepend is a static analysis tool for .NET code that provides metrics like cyclomatic complexity, average and max methods per class, average and max statements per method, assembly dependencies, namespace dependencies and so on. Check the NDepend site for the&lt;a href="http://www.ndepend.com/Features.aspx"&gt; full feature list&lt;/a&gt;.&lt;br /&gt;And what does the pro version offer? -The pro version is an interactive version of the free NDepend. The free version will spit out a report with all the metrics in them, for you to look at, but the pro version integrates with Visual Studio to give you the possiblity to drill into the data, and to modify the metics using the so-called Code Query Language - CQL.&lt;br /&gt;&lt;br /&gt;My observations in general from running NDepend on the three code bases listed above:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; NDepend is pretty fast, at least when the code bases are not too big. This is less important if you intend only to run NDepend on your CI server as a late stage step, but if you want to take an interactive approach it's crucial. &lt;/li&gt;&lt;li&gt; The interactive drill down capabilities of the pro version are enticing...is that good or bad?...for me, on the one hand, it meant that I actually discovered more about the code bases than I think I otherwise would have, on the other hand, I also spent more time than I planned to. &lt;/li&gt;&lt;li&gt; The default NDepend analysis is expressed in CQL queries that can be modified in Visual Studio, which I used to tighten some of the metrics. Doing that was dead easy, and is a real benefit because it allows you to go with your own standards. &lt;/li&gt;&lt;li&gt; The default warning levels for the different metrics are, in my opinion, not tight enough. I especially want fewer statements per method and lower cyclomatic complexity. So that's sometihng I be tweaking in future uses of NDepend. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;My observations relating specifically to the three code base above are:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt; NDepend did not tell me anything I did not know about this code base. -But it's also a degenerate case becasue the code base is so small and because I wrote most of it myself, so I have all it in my head anyway. &lt;/li&gt;&lt;li&gt; This case is a lot more interesting: The code base is of a size where it is hard to hold it all in your head, and it was written by a team, so no one person has actually looked deeply at all the code. For this code base NDepend gave me some interesting insights:&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;ul&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; NDepend was able to produce a very sensible list of methods and classes that need refactoring. About half of them I was aware already, but the other half I wasn't. &lt;/li&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; NDepend was also able to pin point to major areas where the problematic code was concentrated. I sort of knew those were pain points, but NDepend made it a lot clearer. That's a big win. &lt;/li&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; NDepend quickly produced a complete dependency graph, with a half hour of moving boxes around, deleting irrelavant boxes and so on I had a useful diagram of the dependencies in the project. That was actually something we had wanted for a while, but hadn't gotten around to, so that was a nice by-product. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt; The third code base was another small one, but one I didn't know. In this case NDepend gave me:&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;ul&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; A quick overview of the internal and external dependencies. Again in a fairly clear and readable diagram that the teams tech lead was able to confirm quickly&lt;/li&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; Pinpointed the two methods that very overly complex (2 aren't many BTW - that team did a good job, so far) &lt;/li&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;li&gt; A single instance of a cyclic namespace dependency - that the teams tech lead wasn't aware of &lt;/li&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;To sum it's been very easy to get up and running with NDepend, and the tools has provided valuable insights in two of three cases. Considering that the first case was small and written mostly by me, it's not big deal that NDepend didn't tell me anything new in that case (in fact it would have been sort of a big deal if it had - I should know those things already). I recommend giving &lt;a href="http://www.ndepend.com/"&gt;NDepend &lt;/a&gt;a go, I know will be using it routinely in the future for code bases I work on and for code bases I review.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-8182958921016977339?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/8182958921016977339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/04/impressions-of-ndepend.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8182958921016977339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8182958921016977339'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/04/impressions-of-ndepend.html' title='Impressions of NDepend'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-6523455350407184920</id><published>2011-03-14T21:27:00.000+01:00</published><updated>2011-03-14T21:27:37.562+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Why Commit Comments Matter</title><content type='html'>Lets look at something pretty basic: Commit comments. Why are they important? -Good commit comments should summarize the context and intent of the commit. Writing good commit comments gives you a better version history and gives you better individual commits. Lets look at each of these claims in turn.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Better Version History&lt;/b&gt;&lt;br /&gt;Good commit comments makes the version history better in a number of ways: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Having commit comments that summarize intent turns the commit history of the previous day into a quick way for team members to check what happened in the code base yesterday - and they can readily drill down into the code diffs if they want.&lt;/li&gt;&lt;li&gt;Having commit comments that summarizes the context of the commit - e.g. by including a bug report number or a user story id - is a very simple and flexible way to introduce&amp;nbsp;traceability from code to requirements.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Having commit comments that summarize the context and the intent is an&amp;nbsp;excellent tool for understanding code later on: When something seems to work, but also seems a bit odd, it is great to be able do an &lt;a href="http://svnbook.red-bean.com/en/1.5/svn.ref.svn.c.blame.html"&gt;svn blame&lt;/a&gt;&amp;nbsp;or &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-blame.html"&gt;git blame&lt;/a&gt; and get an idea of the context and intent behind that code.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Better Individual Commits&lt;/b&gt;&lt;br /&gt;Writing good commit comments requires just a little bit more thought than writing no comment or writing a non-comment like "checking in code" or "bugfixes" or "I'm going home now". That little bit of extra thought is quite often just enough to make you realize if your commit could break that other part over there, or that you haven't run all the relevant tests, or that it just isn't one cohesive whole and should be split into two or three individual commits. That last point can also lead you to&amp;nbsp;committing&amp;nbsp;more often, and as a result synching and integrating with the rest of the team more often. Good cycle.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But I'm In a Hurry&lt;/b&gt;&lt;br /&gt;Yeah, well we all are. So don't waste teammates time by breaking the build or having them read through the version history diff by diff just so you save a commit comment. Besides writing good commit comments really doesn't take long. Seriously we're talking 10 seconds. Just pick a format and stick to it. I like&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;task id&amp;gt;: &amp;lt;Main intent&amp;gt;. &amp;lt;Important technicalities&amp;gt;&lt;/span&gt;&lt;/div&gt;&amp;nbsp;That's quick to write, right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-6523455350407184920?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/6523455350407184920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/03/why-commit-comments-matter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/6523455350407184920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/6523455350407184920'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/03/why-commit-comments-matter.html' title='Why Commit Comments Matter'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-1064552209296349661</id><published>2011-02-25T21:51:00.001+01:00</published><updated>2011-02-27T07:41:46.095+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Testable C# or C# TUFs and TUCs</title><content type='html'>&lt;br /&gt;Re-reading Michael Feathers nice article on &lt;a href="http://www.objectmentor.com/resources/articles/TestableJava.pdf"&gt;"Testable Java"&lt;/a&gt; I decided to see how the same thing looks in C#. Now, Java and C# aren't too far a part, so the difference isn't huge.&lt;br /&gt;&lt;br /&gt;The "Testable Java" article gives a simple rule for how we can write code that is friendly to unit tests. -As the article points out the rule is superflous if we follow TDD stricly. But - being human - we don't always do that. Sometimes we write only integration tests or even acceptance tests here and now, and postposne unit tests. Sometimes we skip the automated tests altogether. In these cases it's an advantage to have code that is at least friendly to unit tests. If so, it's afordable to add the unit tests later.&lt;br /&gt;&lt;br /&gt;Feathers' rule is:&lt;br /&gt;&lt;blockquote&gt;"Never hide a TUF within a TUC"&lt;/blockquote&gt;and Feathers goes on to define TUF as a "Test Unfriendly Feature" and TUC as a "Test Unfriendly Construct". Now TUFs are things that we want to mock out in many unit tests, but TUCs are language constructs that are hard to substitute for testing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TUFs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Examles, from the article, &amp;nbsp;of TUFs:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Database access&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;File system access&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Network access&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Access to side effecting APIs&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Long running computations&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Inscrutable computations&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;Static variable usage&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The first three are basically I/O, and in general I/O is test unfriendly because it is slow, and usually assumes things about the outside world - like "the webservice is reachable" or "the robot arm is connected through the serial port".&lt;br /&gt;The next - side effects - is about avoiding tests that changes something and annoys somebody.&lt;br /&gt;Long running computations are a nuisance, and will make you skip test runs.&lt;br /&gt;Inscrutable computations, are things that are just plain hard to understand - maybe due the "clever" code-smell or to essential complexity.&lt;br /&gt;These TUFs are all TUFs in .NET as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TUCs&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;The article lists a number of Java TUCs. This is my ported list of C# TUCs:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sealed classes&lt;/li&gt;&lt;li&gt;Static methods&lt;/li&gt;&lt;li&gt;Private methods&lt;/li&gt;&lt;li&gt;Static initializers&lt;/li&gt;&lt;li&gt;Constructors&lt;/li&gt;&lt;li&gt;Static constructors&amp;nbsp;&lt;/li&gt;&lt;li&gt;New expressions&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&amp;nbsp;and these are few more C# TUCs IMHO:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Non-virtual methods&lt;/li&gt;&lt;li&gt;Internal methods&lt;/li&gt;&lt;li&gt;Internal classes&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The point is to remember - even when you skip the TDD strictness - that testability is an important part of maintainability. So if maintainability is quality attribute you want, then keep an eye on the testability. If not, those TUFs inside of TUCs will come back and bite you.&lt;br /&gt;&lt;br /&gt;Oh, and the other point: Go read Michael Feathers' &lt;a href="http://www.objectmentor.com/resources/articles/TestableJava.pdf"&gt;article&lt;/a&gt;. It's well worth it.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-1064552209296349661?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/1064552209296349661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/02/testable-c-or-c-tufs-and-tucs.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1064552209296349661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1064552209296349661'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/02/testable-c-or-c-tufs-and-tucs.html' title='Testable C# or C# TUFs and TUCs'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-8804606669195470430</id><published>2011-02-03T00:09:00.000+01:00</published><updated>2011-02-03T00:09:28.606+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VB.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Tiobe'/><category scheme='http://www.blogger.com/atom/ns#' term='IronRuby'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='PowerShell'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><title type='text'>Random Thoughts on Tiobe Index January 2011</title><content type='html'>&lt;br /&gt;The &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Tiobe index&lt;/a&gt; is an index of the popularity of programming languages (formally defined &lt;a href="http://www.tiobe.com/content/paperinfo/tpci/tpci_definition.htm"&gt;here&lt;/a&gt;).&lt;br /&gt;According to the &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Tiobe web site&lt;/a&gt; "the index can be used to check whether your programming skills are still up to date or to make a strategic decision about what programming language should be adopted when starting to build a new software system."&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Some Data to Notice From the Index&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;As someone who has worked mainly in .NET through the last several years, my interest in the index focuses on .NET languages (and on my favorite language for recreational coding for some time now: Scala). The rankings of .NET languages in the January 2011 index are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;F# ranked between 50 and 100 (the index put these 50 in one big pile because differences the in scores are&amp;nbsp;minuscule)&lt;/li&gt;&lt;li&gt;VB.NET at no. 49&lt;/li&gt;&lt;li&gt;PowerShell at no. 28&lt;/li&gt;&lt;li&gt;C# at no. 6&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;For perspective here are some selected other languages:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;BETA ranked between 50 and 100&lt;/li&gt;&lt;li&gt;AWK at no. 31&lt;/li&gt;&lt;li&gt;T-SQL at no. 17&lt;/li&gt;&lt;li&gt;Ruby at no. 10&lt;/li&gt;&lt;li&gt;VB at no. 7&lt;/li&gt;&lt;li&gt;Python at no. 5&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;And also worth noticing is that Java, C and C++ take the top 3 spots, and have for a decade.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What I Get From That Data&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now what does this mean for a .NET developer?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;C# is hugely popular, but still much, much less popular than Java. Looking at the long term trend C# is steadlily gaining ground. So having and maintaining C# skills is a really good idea in terms of making a living.&lt;/li&gt;&lt;li&gt;VB.NET is so unpopular it's almost off the charts...in a bad way. But (!) considering how the Tiobe index is done I don't think it distinguishes VB and VB.NET properly. So IMHO it's more fair to add the VB and VB.NET scores which would place VB.NET at 5th place - where VB is now. If this is true having VB.NET skills is a really good idea too, but the long term VB.NET trend is downwards, especially over the last couple of years. So maybe it's time to translate those VB.NET chops to C# chops?&lt;/li&gt;&lt;li&gt;F# doesn't seem to be going anywhere. So don't learn F# for job security. Learn it to open your mind. But then again, if you want to open up your mind, and you're a .NET dev, why not look outside .NET and do Scala or Clojure or Erlang or something completly&amp;nbsp;left field?&lt;/li&gt;&lt;li&gt;PowerShell seems to be becoming important. Maybe it's time to really learn it.&lt;/li&gt;&lt;/ol&gt;&amp;nbsp;What does it mean for the .NET community?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Assuming the VB and VB.NET points needs to be added C# and VB.NET combined would weigh in at a 3rd place, meaning that .NET is doing very, very well in terms of popularity.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Both Ruby and Python are doing very well. So if the Iron* languages are dropped an opportunity for engaging two very large communities is lost. That would be really sad!&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Those were my 2 cents. Go check the index out, and make up your own mind. And let me know what you think :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Oh, and Scala is at place 50, just within the list proper. Still rooting for it :-)&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-8804606669195470430?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/8804606669195470430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/02/random-thoughts-on-tiobe-index-january.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8804606669195470430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/8804606669195470430'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/02/random-thoughts-on-tiobe-index-january.html' title='Random Thoughts on Tiobe Index January 2011'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-1536841574781208581</id><published>2011-01-13T22:01:00.001+01:00</published><updated>2011-01-13T22:02:45.126+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='DCI'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Architecture'/><title type='text'>Doing DCI with ASP.NET MVC</title><content type='html'>The DCI - Data, Context, Interaction - paradigm (&lt;a href="http://www.artima.com/articles/dci_vision.html"&gt;intro article&lt;/a&gt;, &lt;a href="http://horsdal.blogspot.com/2009/05/dci-in-c.html"&gt;an earlier post&lt;/a&gt;) brings the roles domain objects play at runtime to center stage. DCI also fits right into the gaps of MVC. What? Which gaps?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MVC Gaps&lt;/b&gt;&lt;br /&gt;Back in the day, when &lt;a href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html"&gt;MVC was originally described&lt;/a&gt;&amp;nbsp;by &lt;a href="http://heim.ifi.uio.no/~trygver/index.html"&gt;Trygve Reenskaug&lt;/a&gt; as an architecture approach it was all about the users mental model, giving the user the sense of just working directly with the domain objects. Now dont confuse this with the dreaded CRUDy forms-over-data battleship grey enterprise app. Those apps force the user to manipulate the &lt;i&gt;data&lt;/i&gt; directly; respecting, fighting and being forced into submission by the techniocal details of databases. MVC on the other hands puts that the model is the &lt;i&gt;users&lt;/i&gt; mental model - the programmer, then has to deal with hiding the technicalities of persistence and such. As illustrated below the users works as if manipulating the domain objects directly. The view simply reflects the model state, the controller reacts to user actions, and translates them to model updates, and that's it.&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_xTffwjsbUDw/TS9hsRWBS5I/AAAAAAAAEUY/11rqEpdiA_s/s1600/Direct+manipulation.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="130" src="http://3.bp.blogspot.com/_xTffwjsbUDw/TS9hsRWBS5I/AAAAAAAAEUY/11rqEpdiA_s/s320/Direct+manipulation.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Direct manipulation metphor as illustrated by Trygve Reenskaug&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;This is fantastic for fairly simple apps. But as soon we introduce business rules with a certain amount of complexity, the direct manipulation metaphor does not suffice anymore. We need somewhere to put those business rules. &amp;nbsp;-The controller already has clear responsibility, so in keeping with &lt;a href="http://www.objectmentor.com/resources/articles/srp.pdf"&gt;single responsibility principle&lt;/a&gt; that's not the place for the behaviour. -The &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;traditional OO answer&lt;/a&gt; is to put the behaviour into the model, but that leads to hard-to-follow logic jumping back and forth in the model objects, and (gark) up and down long inheritance chains. Moreover it turns out that a given domain object will play different roles over times. I.e. the object doesn't need just one behaviour, it needs several, and even worse it needs different behaviours over time. There goes SRP again, only this time in the "intelligent model".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Roles and &amp;nbsp;Contexts to Fill the Gap&lt;/b&gt;&lt;br /&gt;So we need something more than MVC: The view is not the place for the behaviour, the model is not the place for the bahivour, and the controller is not the place for it either. This is where roles as separate things come into play. We want explicit roles. We want those business rules implemented in the roles. And we want to assing those roles to domain objects as needed.&lt;br /&gt;&lt;br /&gt;The role a given object plays at a given moment depends on the context at that moment. So why not introduce contexts as something explict along with the explicit roles? Together roles implementing behaviour and contexts assigning roles to objects fill the gap in MVC.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Back to APS.NET MVC&lt;/b&gt;&lt;br /&gt;Lets get practical: Where do the contexts and the roles go then? Since the contexts manage assigning roles and kicking off the behaviuour the contexts and roles fit well together. In the ASP.NET MVC + DCI demo &lt;a href="http://horsdal.blogspot.com/2010/11/slides-from-dci-talk-at-anug.html"&gt;I did for ANUG&lt;/a&gt; I organized the code like this:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_xTffwjsbUDw/TS9iBhaDn6I/AAAAAAAAEUc/kDi-99TV4e0/s1600/DCI+%252B+MVC+solution+explorer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/_xTffwjsbUDw/TS9iBhaDn6I/AAAAAAAAEUc/kDi-99TV4e0/s640/DCI+%252B+MVC+solution+explorer.png" width="363" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;The Contexts folder has a subfolder for the use case I demoed. Other use cases would have their own subfolders. Inside the subfolder is the context for executing that use case, and the associated roles.&lt;br /&gt;&lt;br /&gt;What is a role in C#? A role in C# is a set of extension methods on an interface (see &lt;a href="http://horsdal.blogspot.com/2009/05/dci-in-c.html"&gt;this&lt;/a&gt; and &lt;a href="http://horsdal.blogspot.com/2010/12/options-for-dci-on-net.html"&gt;that&lt;/a&gt; for more on roles in C#):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySourceTrait&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; TransferTo(&lt;span style="color: blue;"&gt;this&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySource&lt;/span&gt; self, &lt;span style="color: #2b91af;"&gt;TransferMoneySink&lt;/span&gt; recipient, &lt;span style="color: blue;"&gt;decimal&lt;/span&gt; amount)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// The implementation of the use case&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (self.Balance &amp;lt; amount)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;throw&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ApplicationException&lt;/span&gt;(&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"insufficient funds"&lt;/span&gt;);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.Withdraw(amount);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.Log(&lt;span style="color: #a31515;"&gt;"Withdrawing "&lt;/span&gt; + amount);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; recipient.Deposit(amount);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; recipient.Log(&lt;span style="color: #a31515;"&gt;"Depositing "&lt;/span&gt; + amount);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;How does the context track the role assignments? Simple:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySource&lt;/span&gt; Source { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySink&lt;/span&gt; Sink { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;decimal&lt;/span&gt; Amount { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; TransferMoneyContext(&lt;span style="color: #2b91af;"&gt;TransferMoneySource&lt;/span&gt; source, &lt;span style="color: #2b91af;"&gt;TransferMoneySink&lt;/span&gt; sink, &lt;span style="color: blue;"&gt;decimal&lt;/span&gt; amount)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Source = source;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Sink = sink;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Amount = amount;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Execute()&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Source.TransferTo(Sink, Amount);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;Where are the objects mapped to roles? Right in the seam between the controller and the context (lines 35 to 37):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyController&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;Controller&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;AccountRepository&lt;/span&gt; accountRepo = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;AccountRepository&lt;/span&gt;();&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; Index()&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ViewData[&lt;span style="color: #a31515;"&gt;"SourceAccounts"&lt;/span&gt;] =&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; accountRepo.Accounts.Select(a =&amp;gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SelectListItem&lt;/span&gt; {Text = a.Name, Value = a.Id.ToString()});&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ViewData[&lt;span style="color: #a31515;"&gt;"DestinationAccounts"&lt;/span&gt;] =&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; accountRepo.Accounts.Select(a =&amp;gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SelectListItem&lt;/span&gt; {Text = a.Name, Value = a.Id.ToString()});&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;AcceptVerbs&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;HttpVerbs&lt;/span&gt;.Post)]&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ActionResult&lt;/span&gt; Index(&lt;span style="color: #2b91af;"&gt;FormCollection&lt;/span&gt; form)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; sourceAccountId = form[&lt;span style="color: #a31515;"&gt;"SourceAccounts"&lt;/span&gt;];&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; destinationAccountId = form[&lt;span style="color: #a31515;"&gt;"DestinationAccounts"&lt;/span&gt;];&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; amount = form[&lt;span style="color: #a31515;"&gt;"Amount"&lt;/span&gt;];&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; sourceAccount = accountRepo.GetById(&lt;span style="color: blue;"&gt;int&lt;/span&gt;.Parse(sourceAccountId));&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; destinationAccount = accountRepo.GetById(&lt;span style="color: blue;"&gt;int&lt;/span&gt;.Parse(destinationAccountId));&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneyContext&lt;/span&gt;(sourceAccount &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySource&lt;/span&gt;, &lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; destinationAccount &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TransferMoneySink&lt;/span&gt;, &lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;decimal&lt;/span&gt;.Parse(amount)).Execute();&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ViewData[&lt;span style="color: #a31515;"&gt;"Amount"&lt;/span&gt;] = amount;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ViewData[&lt;span style="color: #a31515;"&gt;"Source"&lt;/span&gt;] = sourceAccount.Name;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ViewData[&lt;span style="color: #a31515;"&gt;"Destination"&lt;/span&gt;] = destinationAccount.Name;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; View(&lt;span style="color: #a31515;"&gt;"Result"&lt;/span&gt;);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;Apart from lines 35 to 37 this is all just standard ASP.NET MVC stuff: Getting data in and out of the ViewData, and returning the view to render back to the user.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summing Up&lt;/b&gt;&lt;br /&gt;MVC is great for simple situations. It doesn't quite scale to complex business scenarios, but DCI does, and the two are a great match.&lt;br /&gt;Leveraging the power of C# to do DCI and the niceness of ASP.NET MVC to go along with it, makes for a - IMHO -very compelling architecte style for an enterprisy web app.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-1536841574781208581?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/1536841574781208581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2011/01/doing-dci-with-aspnet-mvc.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1536841574781208581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1536841574781208581'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2011/01/doing-dci-with-aspnet-mvc.html' title='Doing DCI with ASP.NET MVC'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xTffwjsbUDw/TS9hsRWBS5I/AAAAAAAAEUY/11rqEpdiA_s/s72-c/Direct+manipulation.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-5299659691868892677</id><published>2010-12-20T15:03:00.015+01:00</published><updated>2011-01-07T09:22:07.739+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><category scheme='http://www.blogger.com/atom/ns#' term='DCI'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Options for DCI on .NET</title><content type='html'>Here's a short summary of the technical/language options for doing &lt;a href="http://www.google.dk/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;sqi=2&amp;amp;ved=0CBYQFjAA&amp;amp;url=http%3A%2F%2Fwww.artima.com%2Farticles%2Fdci_vision.html&amp;amp;ei=bnwkTcmAGs_zsgbyluC5Ag&amp;amp;usg=AFQjCNEEQZgTMXq9sizrYeQ5hWjwxIhDSQ"&gt;DCI&lt;/a&gt; on the .NET platform. The list below is loosely ordered in order of increasing "mainstreamness" - according to me :-).&lt;br /&gt;The list notes the language, how roles and contexts are handled and how the solution is run on .NET.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; &lt;b&gt;&lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; &lt;/b&gt;"cross-compiled" to MSIL/CLR:&lt;br /&gt;In Scala contexts are simply objects instantiated at runtime from context classes. The contexts have the responsibility of instantiating data objects and mapping roles to them. Roles are traits that are mixed into data objects at instantiation time. So typically the contexts receive ids for data objects, pull the corresponding data from e.g. a database, and instantiate the data object with a role trait mixed in. In Scala this is all strongly typed and looks like this:&lt;div style="overflow: auto; width: 900px;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;class MoneyTransferContext(sourceAccountId: int,&lt;br /&gt;                            sinkAccountId: int){&lt;br /&gt;   val source =&lt;br /&gt;        new SavingsAccount(sourceAccountId) with TransferMoneySource&lt;br /&gt;   val sink =&lt;br /&gt;         new CheckingAccount(sinkAccountId) with TransferMoneySink&lt;br /&gt;   def execute = {&lt;br /&gt;     source.deposit(100000)&lt;br /&gt;     source.transferTo(200, sink)&lt;br /&gt;     }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;To run this in a .NET setting the Scala code must "cross-compiled" to MSIL, and must use the .NET standard library along with the Scala APIs. For details on this &lt;a href="http://horsdal.blogspot.com/2010/10/notes-from-getting-scala-running-on-net.html"&gt;see my earlier post&lt;/a&gt;, or &lt;a href="http://www.scala-lang.org/node/168"&gt;the introduction&lt;/a&gt; on the Scala language web site.&lt;/li&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; &lt;/b&gt;running on IronPython:&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;In Python contexts are objects, that take the responsibility of mixing roles into data objects dynamically. The data objects can be instantiated outside the context or inside the context depending on taste. When the context is done the roles can be yanked back out of the data objects. I dont know a whole lot of Python, so I wont go into details, but refer you to &lt;a href="http://object-composition.googlegroups.com/web/dci.py?gda=NZrI7TgAAAA1RlaiSgDc8DeoAIkDpN7DGgoy5sAEnc_LMhagM9LnNq6YfLL9o0UI_lYHhldHUo8aNWB3A2L4HCtTMEZPaE7O"&gt;Serge Beaumonts sample&lt;/a&gt;.&lt;br /&gt;To run this on .NET use &lt;a href="http://ironpython.net/"&gt;IronPython&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; &lt;/b&gt;running on IronRuby:&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;In Ruby contexts are also objects, that take the responsibility of mixing roles into data objects dynamically. Data objects can be instantiated inside the context or outside the context. Roles in Ruby are implemented as modules, which using the Ruby standard library can be mixed into any Ruby object. The Ruby code looks like this:&lt;span class="Apple-style-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;class TransferMoneyContext&lt;br /&gt;   attr_reader :source_account, :destination_account, :amount&lt;br /&gt;   include ContextAccessor&lt;br /&gt;   &lt;br /&gt;   def self.execute(amt, source_account_id, destination_account_id)&lt;br /&gt;     TransferMoneyContext.new(amt, source_account_id,&lt;br /&gt;                              destination_account_id).execute&lt;br /&gt;   end&lt;br /&gt; &lt;br /&gt;   def initialize(amt, source_account_id, destination_account_id)&lt;br /&gt;     @source_account = Account.find(source_account_id)&lt;br /&gt;     @source_account.extend MoneySource&lt;br /&gt;     @destination_account = Account.find(destination_account_id)&lt;br /&gt;     @amount = amt&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   def execute&lt;br /&gt;     in_context do&lt;br /&gt;       source_account.transfer_out&lt;br /&gt;     end&lt;br /&gt;   end&lt;/pre&gt;&lt;pre&gt;end&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;To run this on .NET just use &lt;a href="http://ironruby.net/"&gt;IronRuby&lt;/a&gt;. It runs fine out of the box.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?familyid=DFBF523C-F98C-4804-AFBD-459E846B268E&amp;amp;displaylang=en"&gt;C#&lt;/a&gt; and Dynamic&lt;/b&gt;:&lt;br /&gt;Using the dynamic features of C#, contexts are objects that receive either data objects or IDs of data objects. In case of an ID the context instantiates the data object and populates it based on the ID and some data source. In both cases the data object has a role reference which will point to an expando object, into which the roles methods are injected. The code looks roughly like this:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;dynamic transfer = new ExpandoObject();&lt;br /&gt; transfer.Transfer = (Action&lt;dynamicobject, decimal=""&gt;)&lt;br /&gt;  ((source, sink, amount) =&amp;gt;&lt;/dynamicobject,&gt;{ &lt;br /&gt;    dynamic mSource = source;&lt;br /&gt;    dynamic mSink = sink;&lt;br /&gt;    mSource.DecreaseBalance(amount);&lt;br /&gt;    mSink.IncreaseBalance(amount);});&lt;br /&gt; Account sourceAcct = new Account { CashBalance = 100m };&lt;br /&gt; sourceAcct.Role = transfer;&lt;br /&gt; Account sinkAcct = new Account { CashBalance = 50m };&lt;br /&gt; sourceAcct.Role.Transfer(sourceAcct,sinkAcct,10m);&lt;/pre&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Running on .NET? Well, it's C#, so just do it.&lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?familyid=DFBF523C-F98C-4804-AFBD-459E846B268E&amp;amp;displaylang=en"&gt;C#&lt;/a&gt; and extention methods&lt;/b&gt;:&lt;br /&gt;Using C# extension methods for roles contexts are objects that receive either data objects or IDs of data objects. In either case the context maps the data objects to roles. Roles are implemented as static classes containing extension methods for role interfaces. Data objects capable of playing a given role implement that role interface. The code looks like this:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;   public class TransferMoneyContext &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 13px; white-space: pre;"&gt;  {        public TransferMoneySource Source { get; private set; }        public TransferMoneySink Sink { get; private set; }        public decimal Amount { get; private set; }        public TransferMoneyContext(TransferMoneySource source,                                    TransferMoneySink sink,                                    decimal amount) &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 13px; white-space: pre;"&gt;       {            Source = source;            Sink = sink;           Amount = amount;        }        public void Execute()        {            Source.TransferTo(Sink, Amount);        }    }    public interface TransferMoneySink    {        void Deposit(decimal amount);        void Log(string message);    }    public interface TransferMoneySource    {        decimal Balance { get; }        void Withdraw(decimal amount);        void Log(string message);    }    public static class TransferMoneySourceTrait    {        public static void TransferTo(this TransferMoneySource self,                                      TransferMoneySink recipient,                                      decimal amount)        {            // The implementation of the use case            if (self.Balance &amp;lt; amount           {                throw new ApplicationException("insufficient funds");           }            self.Withdraw(amount);            self.Log("Withdrawing " + amount);            recipient.Deposit(amount);            recipient.Log("Depositing " + amount);        }    }&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;How to run this on .NET is ... well ... pretty obvious :-)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-5299659691868892677?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/5299659691868892677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/12/options-for-dci-on-net.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/5299659691868892677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/5299659691868892677'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/12/options-for-dci-on-net.html' title='Options for DCI on .NET'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-1895384155571114918</id><published>2010-12-06T19:39:00.000+01:00</published><updated>2010-12-06T19:39:45.962+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RHoK'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>RHoK'ing for Unicef</title><content type='html'>I was at the&lt;a href="http://rhok.dk/"&gt; RHoK 2.0 Aarhus&lt;/a&gt; event this weekend, and got the opportunity to do a simple little web app for Unicef. The app itself is not that interesting for people outside of Unicef, but it will save real money for Unicef that they can use on something else...like helping children. The app is something like 80% done, and we did it in about 28 hours. Wow, it feels great to have been able to actually help Unicef just by doing a saturday to sunday hackathon along with a few other geeks.&lt;br /&gt;&lt;br /&gt;The app was done in ASP.NET MVC 2, with Enitity Framework 4 and SQL Express underneath, and the experience was pretty good: The architecture just came out of the box with MVC. EF code first made thinking about the database schema a non-issue (and the load on the app is expected to be low, so I don't think will need to go in a tweak for performance later). We were able to get by with some of the auto generated CRUD views that Visual Studio can make for ASP.NET MVC model objects. All in all the development was pretty quick.&lt;br /&gt;The code is on &lt;a href="https://code.google.com/p/virtualwearhous/"&gt;google code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-1895384155571114918?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/1895384155571114918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/12/rhoking-for-unicef.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1895384155571114918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1895384155571114918'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/12/rhoking-for-unicef.html' title='RHoK&apos;ing for Unicef'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-1695576059831437801</id><published>2010-11-26T06:22:00.001+01:00</published><updated>2010-11-28T08:46:33.412+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DCI'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Architecture'/><title type='text'>Slides from DCI talk at ANUG</title><content type='html'>I did a talk on &lt;a href="http://en.wikipedia.org/wiki/Data,_Context,_and_Interaction"&gt;DCI &lt;/a&gt;at my local .NET User Group, &lt;a href="http://www.anug.dk/"&gt;ANUG&lt;/a&gt;, the other night and had a great time. The slides from the talk were:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_5911839" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/c_horsdal/dci-anug-24th-november-2010-5911839" title="DCI ANUG - 24th November 2010"&gt;DCI ANUG - 24th November 2010&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse5911839" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dcianug-share-101125142521-phpapp02&amp;amp;stripped_title=dci-anug-24th-november-2010-5911839&amp;amp;userName=c_horsdal" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5911839" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dcianug-share-101125142521-phpapp02&amp;amp;stripped_title=dci-anug-24th-november-2010-5911839&amp;amp;userName=c_horsdal" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/c_horsdal"&gt;c_horsdal&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The slides were followed by three demos:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A simple Scala example &lt;a href="http://horsdal.blogspot.com/2010/10/notes-from-getting-scala-running-on-net.html"&gt;"cross"-compiled to run on .NET&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A simple Ruby example running on &lt;a href="http://ironruby.net/"&gt;IronRuby&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A slightly larger &lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC&lt;/a&gt; based C# example, which I will be posting details about in the furture.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-1695576059831437801?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/1695576059831437801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/11/slides-from-dci-talk-at-anug.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1695576059831437801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1695576059831437801'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/11/slides-from-dci-talk-at-anug.html' title='Slides from DCI talk at ANUG'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4703788722668790566</id><published>2010-11-16T22:28:00.000+01:00</published><updated>2010-11-16T22:28:21.111+01:00</updated><title type='text'>Upcoming events</title><content type='html'>I just wanted to point to 2 events that are coming up soon that I am participating in:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;I am doing a talk on DCI in the Aarhus .NET User Group on the 24th of&amp;nbsp;November&amp;nbsp;2010. Register at&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;a href="http://on.fb.me/9QOa3s" style="color: #0065cc;" target="_blank"&gt;http://on.fb.me/9QOa3s&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;I am participating in Random Hacks of Kindness during the weekend 4th and 5th of&amp;nbsp;December&amp;nbsp;2010. More info and registration at:&amp;nbsp;&lt;a href="http://rhokaarhus.eventbrite.com/"&gt;http://rhokaarhus.eventbrite.com/&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4703788722668790566?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4703788722668790566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/11/upcoming-events.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4703788722668790566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4703788722668790566'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/11/upcoming-events.html' title='Upcoming events'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-3468142266243430397</id><published>2010-10-14T21:44:00.000+02:00</published><updated>2010-10-14T21:44:29.979+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>A Pinch of Functional in my C# - An Everyday Example</title><content type='html'>I'm working on a codebase that, like many other code bases, &amp;nbsp;has a number of data access objects(DAOs) that all inherit a common superclass. The other day I got tired of looking this pattern of code repeated a lot in the DAOs:&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; MyDTO GetMyDTO(&lt;span style="color: #2b91af;"&gt;...)&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;DataContext&lt;/span&gt; DB = NewDBContext;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DB.Connection.Open();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;//Fetch something from the DB and return it&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;finally&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (DB.Connection.State == &lt;span style="color: #2b91af;"&gt;ConnectionState&lt;/span&gt;.Open)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DB.Connection.Close();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;I wanted the creation of the DBContext and the handling of the connection to be factored into somewhere reusable. So I applied the functional "suround with" pattern and introduced this method in the superclass:&lt;br /&gt;&lt;div style="overflow: auto; width: 700px;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; TReturn UsingDBConnection&amp;lt;TReturn&amp;gt;(&lt;span style="color: #2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;DataContext&lt;/span&gt;, TReturn&amp;gt; func)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;DataContext&lt;/span&gt; DB = NewDBContext;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DB.Connection.Open();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; func(DB);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;finally&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (DB.Connection.State == &lt;span style="color: #2b91af;"&gt;ConnectionState&lt;/span&gt;.Open)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DB.Connection.Close();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;/div&gt;and the DAO code then turns into this:&lt;/div&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; MyDTO GetMyDTO(&lt;span style="color: #2b91af;"&gt;...)&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; UsingDBConnection(DB =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;//Fetch something from the DB and return it&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;C# has supported this for years now, so why am I posting it? -Because I wish I saw more of this type of code. To me it's easy to read and I get to reuse the common part.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-3468142266243430397?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/3468142266243430397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/10/pinch-of-functional-in-my-c-everyday.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/3468142266243430397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/3468142266243430397'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/10/pinch-of-functional-in-my-c-everyday.html' title='A Pinch of Functional in my C# - An Everyday Example'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4507052334299020369</id><published>2010-10-02T21:03:00.000+02:00</published><updated>2010-10-02T21:03:21.342+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Scala-msil'/><title type='text'>Notes from getting Scala running on .NET</title><content type='html'>I just spend an evening getting &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; to run on .NET 4.0. Here my notes:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Scala 2.8.0&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I started downloading Scala 2.8.0-final as a &lt;a href="http://www.scala-lang.org/downloads/distrib/files/scala-2.8.0.final.zip"&gt;zip file&lt;/a&gt; (), and unpacking it to my scala playground directory. That gave me:&lt;br /&gt;&lt;pre&gt;PS C:\Scala-playground\scala-2.8.0.final&amp;gt; tree&lt;br /&gt;Folder PATH listing for volume OSDisk&lt;br /&gt;Volume serial number is 00690066 6A5B:A532&lt;br /&gt;C:.&lt;br /&gt;+---bin&lt;br /&gt;+---doc&lt;br /&gt;¦ &amp;nbsp; +---sbaz&lt;br /&gt;¦ &amp;nbsp; +---sbaz-setup&lt;br /&gt;+---lib&lt;br /&gt;+---meta&lt;br /&gt;¦ &amp;nbsp; +---cache&lt;br /&gt;+---misc&lt;br /&gt;¦ &amp;nbsp; +---sbaz&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---config&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---descriptors&lt;br /&gt;¦ &amp;nbsp; +---sbaz-testall&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---tests&lt;br /&gt;¦ &amp;nbsp; +---scala-devel&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---plugins&lt;br /&gt;¦ &amp;nbsp; +---scala-tool-support&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---a2ps&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---bash-completion&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---bluefish&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---context&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Highlighters&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Template&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---emacs&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---contrib&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---enscript&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---geshi&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---intellij&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---jedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---console&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; ¦ &amp;nbsp; +---commando&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---modes&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---latex&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---notepad-plus&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---scite&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---subethaedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---artwork&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Scala.mode&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Contents&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Resources&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---English.lproj&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Scripts&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textmate&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Bundles&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textpad&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textwrangler&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---ultraedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---vim&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---ftdetect&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---indent&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---plugin&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---syntax&lt;br /&gt;+---src&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I then went on to install the Scala msil extension (i.e. the scala .NET compiler and runtime) as follows:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\scala-2.8.0.final&amp;gt; bin/sbaz.bat install scala-msil&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Then, following the "official" instructions on running scala on .NET (http://www.scala-lang.org/node/168), I copied mscorlib.dll to the scala lib folder:&lt;br /&gt;&lt;div style="overflow: auto; width: 1200px;"&gt;&lt;pre&gt;PS C:\Scala-playground\scala-2.8.0.final&amp;gt; copy C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll .\lib&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;I was now ready to try to compile something. E.g. this very simple hello world program using a little bit of .NET, namely Console.WriteLine:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div style="overflow: auto; width: 900px;"&gt;import System.Console&lt;br /&gt;&lt;br /&gt;object test extends Application {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine("Hello world!")&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;I tried to compile it like this:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; ..\scala-2.8.0.final\bin\scalac.bat -target:msil .\test.scala&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;but got this error:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;scala.tools.nsc.MissingRequirementError: class scala.runtime.VolatileBooleanRef not found.&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:513)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.getClass(Definitions.scala:471)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.newValueClass(Definitions.scala:620)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.BooleanClass(Definitions.scala:92)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.initValueClasses(Definitions.scala:643)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:787)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Global$Run.&lt;init&gt;(Global.scala:597)&lt;/init&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main$.process(Main.scala:107)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main$.main(Main.scala:122)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main.main(Main.scala)&lt;br /&gt;error: fatal error: class scala.runtime.VolatileBooleanRef not found.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;I tried like this to point out where mscorlib and the scala runtime dlls are:&lt;br /&gt;&lt;div style="overflow: auto; width: 1500px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; ..\scala-2.8.0.final\bin\scalac.bat -target:msil -Xassem-extdirs ..\scala-2.8.0.final\lib .\test.scala&lt;br /&gt;scala.tools.nsc.MissingRequirementError: class scala.runtime.VolatileBooleanRef not found.&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:513)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.getClass(Definitions.scala:471)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.newValueClass(Definitions.scala:620)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.BooleanClass(Definitions.scala:92)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.initValueClasses(Definitions.scala:643)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:787)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Global$Run.&lt;init&gt;(Global.scala:597)&lt;/init&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main$.process(Main.scala:107)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main$.main(Main.scala:122)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;at scala.tools.nsc.Main.main(Main.scala)&lt;br /&gt;error: fatal error: class scala.runtime.VolatileBooleanRef not found.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;..same error.&lt;br /&gt;&lt;br /&gt;Then I resorted to frantic googling, but ended up deciding to downgrade the mscorlib.dll to 2.0, and to 1.1. But in both cases I got same depressing result.&lt;br /&gt;Finally I decided to downgrade to scala 2.7.7.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Scala 2.7.7&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I downloaded &lt;a href="http://www.scala-lang.org/sites/default/files/linuxsoft_archives/downloads/distrib/files/scala-2.7.7.final.zip"&gt;scala 2.7.7&lt;/a&gt; unzipped it and got:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\scala-2.7.7.final&amp;gt; tree&lt;br /&gt;Folder PATH listing for volume OSDisk&lt;br /&gt;Volume serial number is 00690066 6A5B:A532&lt;br /&gt;C:.&lt;br /&gt;+---bin&lt;br /&gt;+---doc&lt;br /&gt;¦ &amp;nbsp; +---sbaz&lt;br /&gt;¦ &amp;nbsp; +---sbaz-setup&lt;br /&gt;+---lib&lt;br /&gt;+---meta&lt;br /&gt;¦ &amp;nbsp; +---cache&lt;br /&gt;+---misc&lt;br /&gt;¦ &amp;nbsp; +---sbaz&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---descriptors&lt;br /&gt;¦ &amp;nbsp; +---sbaz-testall&lt;br /&gt;¦ &amp;nbsp; ¦ &amp;nbsp; +---tests&lt;br /&gt;¦ &amp;nbsp; +---scala-tool-support&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---a2ps&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---bluefish&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---context&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Highlighters&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Template&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---emacs&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---contrib&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---enscript&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---geshi&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---intellij&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---jedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---console&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; ¦ &amp;nbsp; +---commando&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---modes&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---latex&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---notepad-plus&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---scite&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---subethaedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---artwork&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Scala.mode&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Contents&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Resources&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---English.lproj&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---Scripts&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textmate&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; ¦ &amp;nbsp; +---Bundles&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textpad&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---textwrangler&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---ultraedit&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; +---vim&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---ftdetect&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---indent&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---plugin&lt;br /&gt;¦ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +---syntax&lt;br /&gt;+---src&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;The I went through copying mscorlib and installing scala-msil again:&lt;br /&gt;&lt;div style="overflow: auto; width: 1200px;"&gt;&lt;pre&gt;PS C:\Scala-playground\scala-2.7.7.final&amp;gt; copy C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll .\lib&lt;br /&gt;PS C:\Scala-playground\scala-2.7.7.final&amp;gt; .\bin\sbaz.bat install scala-msil&lt;br /&gt;planning to install: scala-msil/2.7.7.final&lt;br /&gt;Installing...&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Then I tried compilling again:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; ..\scala-2.7.7.final\bin\scalac-net.bat .\test.scala&lt;br /&gt;PS C:\Scala-playground\hello.net&amp;gt; ls&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Directory: C:\Scala-playground\hello.net&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mode &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;LastWriteTime &amp;nbsp; &amp;nbsp; Length Name&lt;br /&gt;---- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;------------- &amp;nbsp; &amp;nbsp; ------ ----&lt;br /&gt;d---- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 21:59 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;target&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:33 &amp;nbsp; &amp;nbsp; &amp;nbsp; 3863 test.msil&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 21:52 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;100 test.scala&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;which went well. The scala compiler made a .msil file. Yeah.&lt;br /&gt;&lt;br /&gt;Next step was turning that .msil into an .exe:&lt;br /&gt;&lt;div style="overflow: auto; width: 1200px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe .\test.msil&lt;br /&gt;&lt;br /&gt;Microsoft (R) .NET Framework IL Assembler. &amp;nbsp;Version 4.0.30319.1&lt;br /&gt;Copyright (c) Microsoft Corporation. &amp;nbsp;All rights reserved.&lt;br /&gt;Assembling '.\test.msil' &amp;nbsp;to EXE --&amp;gt; '.\test.exe'&lt;br /&gt;Source file is ANSI&lt;br /&gt;&lt;br /&gt;Assembled method test::$tag&lt;br /&gt;Assembled method test::main&lt;br /&gt;Assembled method test$::.ctor&lt;br /&gt;Assembled method test$::.cctor&lt;br /&gt;Assembled method test$::$tag&lt;br /&gt;Assembled method test$::main&lt;br /&gt;Assembled global method Main&lt;br /&gt;Creating PE file&lt;br /&gt;&lt;br /&gt;Emitting classes:&lt;br /&gt;Class 1: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;test&lt;br /&gt;Class 2: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;test$&lt;br /&gt;&lt;br /&gt;Emitting fields and methods:&lt;br /&gt;Global &amp;nbsp;Methods: 1;&lt;br /&gt;Class 1 Methods: 2;&lt;br /&gt;Class 2 Fields: 1; &amp;nbsp; &amp;nbsp; &amp;nbsp;Methods: 4;&lt;br /&gt;Resolving local member refs: 8 -&amp;gt; 8 defs, 0 refs, 0 unresolved&lt;br /&gt;&lt;br /&gt;Emitting events and properties:&lt;br /&gt;Global&lt;br /&gt;Class 1&lt;br /&gt;Class 2&lt;br /&gt;Resolving local member refs: 0 -&amp;gt; 0 defs, 0 refs, 0 unresolved&lt;br /&gt;Writing PE file&lt;br /&gt;Operation completed successfully&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Which gave:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; ls&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Directory: C:\Scala-playground\hello.net&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mode &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;LastWriteTime &amp;nbsp; &amp;nbsp; Length Name&lt;br /&gt;---- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;------------- &amp;nbsp; &amp;nbsp; ------ ----&lt;br /&gt;d---- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 21:59 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;target&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:35 &amp;nbsp; &amp;nbsp; &amp;nbsp; 2560 test.exe&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:33 &amp;nbsp; &amp;nbsp; &amp;nbsp; 3863 test.msil&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 21:52 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;100 test.scala&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;So I tried running the program:&lt;br /&gt;&lt;div style="overflow: auto; width: 1200px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; .\test.exe&lt;br /&gt;&lt;br /&gt;Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'predef, Version=0.0.0.0, Culture=&lt;br /&gt;neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.&lt;br /&gt;&amp;nbsp;&amp;nbsp; at Main(String[] args)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;but missed the predef assembly which is part of the scala-msil extension. To get passed that I simply copied all dlls from the Scala lib folder and ran again:&lt;br /&gt;&lt;div style="overflow: auto; width: 900px;"&gt;&lt;pre&gt;PS C:\Scala-playground\hello.net&amp;gt; mv .\test.exe .\target&lt;br /&gt;PS C:\Scala-playground\hello.net&amp;gt; cp ..\scala-2.7.7.final\lib/*.dll .\target&lt;br /&gt;PS C:\Scala-playground\hello.net&amp;gt; cd .\target&lt;br /&gt;PS C:\Scala-playground\hello.net\target&amp;gt; ls&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Directory: C:\Scala-playground\hello.net\target&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mode &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;LastWriteTime &amp;nbsp; &amp;nbsp; Length Name&lt;br /&gt;---- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;------------- &amp;nbsp; &amp;nbsp; ------ ----&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:30 &amp;nbsp; &amp;nbsp;2070528 mscorlib.dll&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:30 &amp;nbsp; &amp;nbsp;1180160 predef.dll&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:30 &amp;nbsp; &amp;nbsp; &amp;nbsp; 5632 scalaruntime.dll&lt;br /&gt;-a--- &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;30-09-2010 &amp;nbsp; &amp;nbsp; 22:35 &amp;nbsp; &amp;nbsp; &amp;nbsp; 2560 test.exe&lt;br /&gt;PS C:\Scala-playground\hello.net\target&amp;gt; .\test.exe&lt;br /&gt;Hello world!&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Success! but only on the next to newest Scala version. Either way I had fun :-)&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4507052334299020369?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4507052334299020369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/10/notes-from-getting-scala-running-on-net.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4507052334299020369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4507052334299020369'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/10/notes-from-getting-scala-running-on-net.html' title='Notes from getting Scala running on .NET'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-1569452002017150325</id><published>2010-09-25T17:15:00.000+02:00</published><updated>2010-09-25T17:15:39.411+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Spec Style Unit Tests in C#</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Spec style unit tests are unit tests that focus on making the specs clear, and then relating some test code to each part of the spec. The &lt;a href="http://code.google.com/p/specs/"&gt;Specs&lt;/a&gt; Scala unit test framework is really good at that (e.g. check this &lt;a href="http://horsdal.blogspot.com/2010/05/why-do-i-like-spec-style-unit-tests.html"&gt;earlier post&lt;/a&gt;), but I want to be able to do the same in C#.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Lets look at an example: A method for deciding whether a given year is a leap year. The rules for leap years are:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;A leap year should&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;be any year divisible by 400&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;but not other years divisible by 100&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;and all other years divisible by 4&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;In other words the above are the specs for the method. So I would like that to be clear from the unit test. I would also like the unit test to make it clear what test code corresponds to what part of the spec. Therefore I would like the spec to be part of the test, and the test code to be mixed right into that spec text. Something like:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;"A leap year" should&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;"be any year divisible by 400" asIn&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;// test code here&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;"but not other years divisible by 100" asIn&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;// test code here&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;"and all other years divisible by 4" asIn&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;// test code here&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;such that the spec is clearly visible as the strings, and such that the 'asIn' indicates that the code in the following scope tests the part of the spec right before the 'asIn'. To achieve something close to this I've made three simple extension methods on string: 'should', 'asIn' and 'andIn'. Each one of these extension methods take a delegate as an argument. That makes it possible to write this code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"A leap year"&lt;/span&gt;.should(() =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"be any year divisible by 400"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Test code here&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .andIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// More test code&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"but not other years divisible by 100"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Test code here&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"and all other years divisible by 4"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Test code here&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Because this is C# there I need to the dots and the arrows ( ()=&amp;gt; ) in there, but I still think the spec is pretty clearly visible. The extension methods themselves are very simple: They basically just execute the delegate passed to them, which means that all the test code snippets in the above will be executed. The complete code for the extension methods is:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Specs&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;{&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SpecExtensions&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; should(&lt;span style="color: blue;"&gt;this&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; unitUnderTest, &lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; executableSpecification)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Console&lt;/span&gt;.WriteLine(unitUnderTest + &lt;span style="color: #a31515;"&gt;" should"&lt;/span&gt;);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; executableSpecification();&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; asIn(&lt;span style="color: blue;"&gt;this&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; readableSpecification,&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; executableSpecification)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515;"&gt;@"&amp;nbsp;&amp;nbsp;&amp;nbsp; "&lt;/span&gt; + readableSpecification);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; RunExecutableSpecification(&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; readableSpecification, executableSpecification);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; andIn(&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; readableSpecification,&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; executableSpecification)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; RunExecutableSpecification(&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; readableSpecification, executableSpecification);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; RunExecutableSpecification(&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; readableSpecification,&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; executableSpecification)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; executableSpecification();&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; readableSpecification;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;}&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: Consolas; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Combining that with NUnit, the test for my leap year checker becomes:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;using&lt;/span&gt; NUnit.Framework;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Specs.Test&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;{&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;TestFixture&lt;/span&gt;]&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LeapYearTest&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; LeapYearSpec()&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"A leap year"&lt;/span&gt;.should(() =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"be any year divisible by 400"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(0),&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.True);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(400),&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.True);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(800),&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.True);&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .andIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(-400),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"but not other years divisible by 100"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(100),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(100),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(200),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(1000),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;"and all other years divisible by 4"&lt;/span&gt;.asIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 100; i += 4)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(i),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.True);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .andIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i = 1600; i &amp;lt; 1700; i += 4)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(i),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.True);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; })&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .andIn(() =&amp;gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i = 1601; i &amp;lt; 1700; i += 4)&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.That(&lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;.IsLeapYear(i),&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Is&lt;/span&gt;.False);&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;The specs are not as easily visible once all the code is there, but I still think its easy to find the specs. What do you think? Is there too much clutter of dots and arrows and stuff? Is the calling back and forth between the test and extension methods too strange? I'm on the fence. One part me really, really likes this. One part of me really, really doesn't.&lt;br /&gt;Oh, and for completeness the code under test is:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="color: #2b91af; font-family: Consolas; font-size: small;"&gt;&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LeapYearChecker&lt;/span&gt;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; IsLeapYear(&lt;span style="color: blue;"&gt;int&lt;/span&gt; year)&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; year &amp;gt;= 0 &amp;amp;&amp;amp;&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (year % 400 == 0 ||&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (year % 4 == 0 &amp;amp;&amp;amp; year % 100 != 0));&lt;/div&gt;&lt;div style="background: #ededed; margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial; font-size: small;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-1569452002017150325?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/1569452002017150325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/09/spec-style-unit-tests-in-c.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1569452002017150325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/1569452002017150325'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/09/spec-style-unit-tests-in-c.html' title='Spec Style Unit Tests in C#'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8336318365940619669.post-4693475816161809942</id><published>2010-09-09T11:46:00.000+02:00</published><updated>2010-09-09T11:46:50.769+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Don't Stay Stuck</title><content type='html'>&lt;div style="line-height: 1.5em; margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.4em;"&gt;&lt;a href="http://4.bp.blogspot.com/_xTffwjsbUDw/SwrqV2JtrTI/AAAAAAAADm8/tbysXovrm_c/s1600/Stuck.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_xTffwjsbUDw/SwrqV2JtrTI/AAAAAAAADm8/tbysXovrm_c/s320/Stuck.jpg" width="320" /&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;If you write code professionally, you will have days where you find yourself utterly stuck on a problem. In fact, some days coding feels like trying to wade through quicksand: The harder you struggle to get out the more stuck you find yourself. Getting into one of those situations where you are stuck and can't find a way out is perfectly normal. And it is perfectly acceptable for a professional programmer as well. Every programmer finds themselves in those situations from time to time. Getting stuck is a natural part of creative work like programming, and as such we must simply accept that we get utterly stuck now and then. The important part is what you do about it. As with quicksand the trick is to relax a bit, sit back, and realize that you need to seek help. Not all programmers realize this, but the best ones do.&lt;/span&gt;&lt;/div&gt;&lt;div style="line-height: 1.5em; margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.4em;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;When faced with an insurmountable problem some programmers just press on and try to work through it. That usually means they start thrashing; they run around in circles without getting anywhere. While this might keep them warm, and even make them seem really busy and hard working it doesn't help the project. Some programmers sort of lose interest and start surfing the web or drinking inordinate amounts of coffee. That doesn't help the project either. To get out the situation you're stuck in, you probably need help - I know, I always do. So seek help.&lt;/span&gt;&lt;/div&gt;&lt;div style="line-height: 1.5em; margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.4em;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;Seeking help can mean a number of things depending on the problem you're facing. If the problem is on the code level try asking a teammate to come and pair with you - or if you're already pairing, ask to switch pairing partner - that extra set of eyes usually helps. If the problem is a design issue, again ask a teammate to help you out, but get up from the keyboard and go to the white board. Again the extra set of eyes - or even just the process of explaining the problem - usually helps. If the problem isn't technical but has to do with say access to the right tools, the right level of support from third parties, or unrealistic deadlines, ask your project manager for help. And if he or she is not able or willing to help, don't be afraid to escalate the problem to his or her boss - it's the professional thing to do. As I said: Seeking help can mean a number of different things.&lt;/span&gt;&lt;/div&gt;&lt;div style="line-height: 1.5em; margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.4em;"&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif;"&gt;But whatever you do, don't just stay stuck. Do something about it.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8336318365940619669-4693475816161809942?l=horsdal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://horsdal.blogspot.com/feeds/4693475816161809942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://horsdal.blogspot.com/2010/09/dont-stay-stuck.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4693475816161809942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8336318365940619669/posts/default/4693475816161809942'/><link rel='alternate' type='text/html' href='http://horsdal.blogspot.com/2010/09/dont-stay-stuck.html' title='Don&apos;t Stay Stuck'/><author><name>Christian Horsdal Gammelgaard</name><uri>https://profiles.google.com/115620000225715026045</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-q1-vtBCezz0/AAAAAAAAAAI/AAAAAAAAEXM/Its0kTHbEAc/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.
