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

<channel>
	<title>Humblecoder</title>
	<atom:link href="http://humblecoder.co.uk/feed" rel="self" type="application/rss+xml" />
	<link>http://humblecoder.co.uk</link>
	<description>Apprentice unit tester, expert rambler</description>
	<lastBuildDate>Sat, 07 Jan 2012 00:06:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Hosting Nancy on Debian with Nginx</title>
		<link>http://humblecoder.co.uk/nancy/hosting-nancy-on-debian-with-nginx</link>
		<comments>http://humblecoder.co.uk/nancy/hosting-nancy-on-debian-with-nginx#comments</comments>
		<pubDate>Sat, 07 Jan 2012 00:06:08 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Nancy]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[LEB]]></category>
		<category><![CDATA[Mono]]></category>
		<category><![CDATA[Nginx]]></category>

		<guid isPermaLink="false">http://humblecoder.co.uk/?p=231</guid>
		<description><![CDATA[Over the Christmas break I found myself with a bit of free time to play with Nancy.  For a long time I&#8217;ve fancied writing a link shortener, I even bought the domain vfy.be to serve shortened links from.  I originally had grand plans, it was going to be a social link shortener where links &#8220;trusted&#8221;/visited by your friends [...]]]></description>
			<content:encoded><![CDATA[<p>Over the Christmas break I found myself with a bit of free time to play with Nancy.  For a long time I&#8217;ve fancied writing a link shortener, I even bought the domain <a href="http://vfy.be">vfy.be</a> to serve shortened links from.  I originally had grand plans, it was going to be a social link shortener where links &#8220;trusted&#8221;/visited by your friends took you straight to them, otherwise you hit a landing page with the amount of hits, the real url and what Google thinks about it or I was going to iframe the page in with a toolbar.  Anyway, twitter got in the link shortening business and I got another idea and decided to move on.  But still how they worked intrigued me.</p>
<p>So I wrote one for fun using C#, mono 2.10 and <a href="https://github.com/NancyFx/Nancy">Nancy</a>.  When looking at the Nancy docs, it is slightly lacking in how to host on Linux so I thought I&#8217;d do my bit by writing a quick overview.</p>
<h3>Options</h3>
<p>There is a couple of options when hosting on Linux, one is to create your Nancy project as a mono ASP.NET project then serve it using xsp (the mono ASP.NET server) and proxying to it or using FastCGI.  This is fairly well documented at the mono site and writing a Nancy app using ASP.NET for hosting is also well documented.  However, I wanted to take a different approach to try and host it in the minimum amount of RAM on an LEB (<a href="http://www.lowendbox.com">LowEndBox</a>), because I have a 256MB Xen Debian VPS just sat around doing nothing.</p>
<p>So to minimise RAM I went for self hosting, using pretty much the stock sample with a slight mod (see below). When self hosting the Nancy app will listen on the loopback address at a specified port so we are going to use Nginx to serve static content and forward all requests to our mono process and use Supervisord to monitor the process.</p>
<h3>Pull it all together</h3>
<p>For this you&#8217;ll need the following installed on the Linux machine:</p>
<ul>
<li>Mono 2.10</li>
<li><a href="http://supervisord.org/">Supervisord</a></li>
<li><a href="http://nginx.org/">Nginx</a></li>
</ul>
<p>The first we&#8217;re going to do is configure Supervisord.  Supervisord is a process monitoring application that can run any normal process as a daemon and automatically restart it if it crashes.  I first came across this when working with Python sites to keep FastCGI processes running.   The configuration should look something like:<br />
<script type="text/javascript" src="https://gist.github.com/1572767.js">// <![CDATA[</p>
<p>// ]]&gt;</script></p>
<p>The important bits are:</p>
<ul>
<li>command &#8211; this specifies the command believe it or not,</li>
<li>user &#8211; by default supervisord runs all processes as root, this is bad for webapps.</li>
<li>directory &#8211; this sets the working directory, so if you&#8217;re app needs anything off disc this needs to be correct.</li>
</ul>
<p>As I said above I needed to make a tweak to the sample self hosting project.  The sample uses Console.ReadLine() to stop the process from exiting, but under Mono when running as a daemon this returns EOF and causes the application to close.  So I updated it to sleep (shamelessly stolen from xsp source <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ):</p>
<p><script type="text/javascript" src="https://gist.github.com/1572840.js">// <![CDATA[</p>
<p>// ]]&gt;</script></p>
<p>Moving on we need to configure Nginx. The strength of Nginx is serving up static content quickly so we&#8217;re going to intercept all requests for static files and then forward the rest to our Nancy app. The configuration below defines an &#8216;upstream&#8217; which is typically used for load balancing we can use it here for just forwarding requests. Also note we are intercepting and serving requests for /Content using Nginx.  At debug time the default conventions in Nancy will serve this up correctly so we get best of both worlds <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><script type="text/javascript" src="https://gist.github.com/1572876.js">// <![CDATA[</p>
<p>// ]]&gt;</script></p>
<h3>How well does it do on our LEB?</h3>
<p>Impressively, idle the combination of Debian Sid, Supervisord, Nginx and the Mono process takes up just 37MB of RAM, but the most important question is can it handle load?  ***<strong>Beware completely unscientific results below</strong> <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ***</p>
<p>Lets take a look at hitting one of the json API methods* using <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">ApacheBench</a> (that is bundled with OSX <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ):</p>
<ul>
<li>1000 continuos requests with a max of 10 concurrent connections peaks memory at 53MB</li>
<li>1000 continuos requests with a max of 25 concurrent connections peaks memory at 54MB but 18 out of the 1000 failed with connection reset by peer, which is more the box failing than the app</li>
<li>1000 continuos requests with a max of 50 concurrent connections peaks memory at 55MB but my own boardband gave up after 700 connection, clearly not enough upspeed <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<div>*It&#8217;s important to note that this app is one static html page with ajax queries back to a JSON api served by Nancy</div>
<h3>Wrapping Up</h3>
<p>I hope someone finds my configuration snippets useful and it is worth noting that my LEB (£2.20 a month for 256MB Xen) failed before the my app did, so I find this very encouraging for it&#8217;s performance under Mono and Linux.</p>
<p>Source for the link shortener and conf files can be found at <a href="https://github.com/Dotnetwill/vfy.be">https://github.com/Dotnetwill/vfy.be</a><br />
The shortener running on Mono <a href="http://vfy.be">http://vfy.be</a></p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/nancy/hosting-nancy-on-debian-with-nginx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TFS From the Trenches</title>
		<link>http://humblecoder.co.uk/tfs/tfs-from-the-trenches</link>
		<comments>http://humblecoder.co.uk/tfs/tfs-from-the-trenches#comments</comments>
		<pubDate>Sun, 04 Dec 2011 10:57:30 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://humblecoder.co.uk/?p=198</guid>
		<description><![CDATA[It seems I whenever I see TFS mentioned on twitter/HN/Reddit it is usually closely followed by mocking or derisive comments. But all these comments lack any real explanation or reasoning, outside of generally hating on MS, from the author. So as someone who works with, and has worked with for the past 3 or so [...]]]></description>
			<content:encoded><![CDATA[<p>It seems I whenever I see TFS mentioned on twitter/HN/Reddit it is usually closely followed by mocking or derisive comments. But all these comments lack any real explanation or reasoning, outside of generally hating on MS, from the author. So as someone who works with, and has worked with for the past 3 or so years, TFS on a daily basis I&#8217;d like to add on my two cents on how TFS works and what my pain points are.</p>
<p>Bear in mind I&#8217;m not an VCS geek, I&#8217;m not going to start talking about how the extensionalist index metabear does not quite model that of the intrinsically 4D nature of time and application architecture. This is just how I get on with it while trying to get shit done.</p>
<p>I&#8217;m only going to cover the two parts we use, source control and build management.</p>
<p>TL;DR; It has lots promise but sadly missing features and poorly thought functionality severely hamper it.</p>
<h3>Editing Files</h3>
<p>Let&#8217;s cut the crap, working on a file and checking it in is the same in virtually every VCS. And TFS is not exception here, you work away, see your changes, check them in and if there is a conflict you get a diff. Not rocket science and works well enough.</p>
<p>However, this does quickly breakdown if you want edit files outside of Visual Studio (VS). The problem is files need to be &#8220;checked out&#8221; before you can make edits. If it didn&#8217;t happen while it was checked out it, it didn&#8217;t happen. I&#8217;ve lost count of the number of times I&#8217;ve tweaked an XML file, build file, none cs file and done it in Programmers Notepad only to check in and break the CI build because the tweaks have been missed.</p>
<p>Editing and merging csproj or sln files is a complete and utter nightmare and I&#8217;ve never understood why.  Let&#8217;s face it if you&#8217;re using TFS you&#8217;re fairly invested in the MS ecosystem so you&#8217;re using VS and one of TFS&#8217;s big features is integration into VS so why oh why, for the love of God why, can&#8217;t TFS parse and merge sln and csproj files? They are MS formats, produced by an MS tool and managed in an MS tool W. T. F.</p>
<h3>Merging And Branching</h3>
<p>Personally I&#8217;ve been completely spoilt by local branching in DVCS (Distributed Version Control System) and I sometimes get lost in what branching means in a more centralised context. In TFS and svn branching can only be done on the server allowing multiple people to work on the same branch. Whereas with DVCS and local branching only you can make edits and commits then when you&#8217;re ready to integrate your work with your team you pull the upstream, merge it and push it. So it&#8217;s in your best interest to keep the two as close as possible to minimise your own pain.</p>
<p>The more centralised models put the onus on nobody to sync the branch with upstream because somebody, IE not you, will have to do the merge. Many teams will try to manage this through policy to varying degrees of success and lets not forget that it is entirely possible to get into the same mess with DVCS.</p>
<p>For me the secret sauce of branching with DVCS is that it moves the emphasis of the responsibility and management of the branch on to the individual developer. No amount of nifty features or tooling can make up for the fact that a branch that hasn&#8217;t been synced with its parent for 3 weeks and has lots of code churn is going to be a nightmare to merge.</p>
<p>So I don&#8217;t think it&#8217;s fair to pick on TFS over branching, yes it doesn&#8217;t support local branching but at the same time that has the same issues of good branching requiring proactive syncing, thought about management and discipline.</p>
<p>One area where TFS has massively improved recently is in history across branch. Pre-2010 there was no easy way to follow the history of an item cross branch but thankfully this has now been added.</p>
<h3>Checking Out, Moving Files and IDE integration</h3>
<p>For those that don&#8217;t know when you do a pull in TFS every file is readonly by default if you want to edit a file you have to go source control explorer, find it and check it out.  If you have VS integration turned on (and if you don&#8217;t you&#8217;re a mentalist) it is all quickly taken care of for you when working inside of VS.  There is, of course, an option to make files readable on pull but that only introduces a whole new, more annoying, problem, working out what has actually changed.  There is no &#8220;Hey TFS, I&#8217;ve change some things figure out what&#8217;s different and list them as pending changes for this checkin&#8221;, I&#8217;ll run that by you again if you don&#8217;t check it out TFS doesn&#8217;t know what has changed.  This is complete lunacy and is a significant barrier when trying to get shit done.  To be fair, it does have this functionality when your connect goes offline and when coming back online it will look for changes and generally find them.  But there is no way to do this from the IDE normally.</p>
<p><strong>Checking out files is a completely moronic concept.</strong></p>
<p>I said earlier that if it wasn&#8217;t checked out it didn&#8217;t happen, let me amend that to if didn&#8217;t happen inside source control explorer with the correct verb then it didn&#8217;t happen.  This is most frustrating with file moves, recently I restructured one of our main solutions splitting several new projects from one monster. I created the new projects then cut and paste the required files via Solution Explorer with TFS integration enabled, expecting TFS to pick up the moves but it did delete/adds and completely f&#8217;ed up the merges for everyone else and the history.</p>
<p>For me all this TFS having to be explicitly told what you&#8217;re doing shouldn&#8217;t be a problem when working in VS, this should be it&#8217;s killer feature.  It should be don&#8217;t worry just work as normal, TFS is watching and will know what to do but nothing could be further from the truth.</p>
<p>Oh and on moving, you can&#8217;t multi select files to move them in source control explorer you either do the whole folder or the files one by one :-/ (I think it&#8217;s because &#8220;moves&#8221; are actually &#8220;renames&#8221; so it needs to know the filename but WTF)</p>
<h3><span class="Apple-style-span" style="font-size: 15px; font-weight: bold;">Shelvesets</span></h3>
<p>Shelvesets on the surface seem a pretty nice feature, it allows you save a copy of your current changes without checking them in.  They get stored centrally so can move between machines and even users, handy if you want a code review or you want to quickly spike something out then share it without checking it in or branching.</p>
<p>Over time I have found the omission of features deeply frustrating.  Shelvesets themselves do not have any history, I find this fustrating because the first time I seen them I thought great, I can make changes and have lots and lots of small checkpoints before checking in the finished bits and it doesn&#8217;t matter if they don&#8217;t build or cause tests to fail.  But nope, shelvesets overwrite each other if they have the same name.</p>
<p>The other use case is using them as a stash, so you&#8217;re working away on a feature or a bug and you discover you&#8217;re working on the wrong branch or something else high priority comes in so you shelve your current changes.  Later you go to unshelve them on another branch so you can finish up, nope can&#8217;t do that shelves can&#8217;t move cross branch for reasons known only to MS.</p>
<p>Again another should be a killer feature but so widely misses the mark.</p>
<h3>Builds</h3>
<p>I work for an MS shop so we use MSBuild for builds and TFS build is all MSBuild based so it integrates nicely.  It can schedule builds, run the CI, the build machine setup is a little clunky but it makes sense.  Overall running and managing builds it does a good job.  The only major frustration is notifications.</p>
<p>Not only is it really difficult to set up a notification, the UI is horrendous and none obvious, but if someone has setup a notification on your behalf then you can&#8217;t delete it, see it or see who created it.  So if you want to piss someone off you can setup for them to be notified on every build that is done ever and there is nothing they can do about it.  Yes, you can go to the TFS database and remove them but that&#8217;s a bit extreme and not many developers have that kind of access.</p>
<h3>Overall</h3>
<p>TFS has so much promise but the combination of idiotic concepts, poor integration and lacklustre features really harms productive.  A sign of a good tool should be one that doesn&#8217;t get in the way and in this respect TFS fails massively.  I would even go as far to say it actively promotes bad VCS habits from individual developers.</p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/tfs/tfs-from-the-trenches/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DDD North Sessions Android App</title>
		<link>http://humblecoder.co.uk/uncategorized/ddd-north-sessions-android-app</link>
		<comments>http://humblecoder.co.uk/uncategorized/ddd-north-sessions-android-app#comments</comments>
		<pubDate>Sat, 24 Sep 2011 17:50:35 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[DDDNorth]]></category>

		<guid isPermaLink="false">http://humblecoder.co.uk/?p=179</guid>
		<description><![CDATA[I was massively honoured to have my session on Android development voted into DDD North and I&#8217;ve spent the last couple of weeks thinking about and planing my content to do the honour justice.  While doing this I&#8217;ve created a small application that lists all the available sessions at DDD North and lets you keep track of [...]]]></description>
			<content:encoded><![CDATA[<p>I was massively honoured to have my session on Android development voted into DDD North and I&#8217;ve spent the last couple of weeks thinking about and planing my content to do the honour justice.  While doing this I&#8217;ve created a small application that lists all the available sessions at DDD North and lets you keep track of what you&#8217;re planning to attend.  Partly to help recentre my Android zen and partly to give something back.  So here it is:</p>
<p><a href="http://humblecoder.co.uk/wp-content/uploads/2011/09/ddd_screen2.png"><img class="size-medium wp-image-185 aligncenter" title="ddd_screen2" src="http://humblecoder.co.uk/wp-content/uploads/2011/09/ddd_screen2-180x300.png" alt="" width="180" height="300" /></a><br />
<strong>Features:</strong></p>
<ul>
<li>Full session list stored locally, so it will work when you have no wifi or signal</li>
<li>Includes the title, full description, room, time and presenter of every session</li>
<li>The welcome screen gives you a heads up of your next session</li>
<li>A &#8220;My Schedule&#8221; view, once you&#8217;ve selected the sessions you want to attend you can see them all at a glance.</li>
</ul>
<div>It&#8217;s nothing ground breaking, or pretty <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , but I hope you find it useful.  You can download it from:</div>
<div style="text-align: center;"><a title="Market Link" href="https://market.android.com/details?id=com.havedroid.dddsched" target="_blank">Market Link</a></div>
<div style="text-align: left;">And the source is up at <a href="https://github.com/Dotnetwill/DDDNorth-Schedule-Android">https://github.com/Dotnetwill/DDDNorth-Schedule-Android</a> so if you want to add features you&#8217;re more than welcome just send me a pull request!</div>
<p>&nbsp;<br />
</p>
<div style="text-align: left;"><strong>**Disclaimer** </strong>Although I use the official DDDNorth logo and colours this is 100% unoffical so please direct all complaints and issues to me, not the wonder DDDNorth team <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </div>
<p>&nbsp;</p>
<h2 style="text-align: left;">My Session</h2>
<p>My session is an introduction to Android development from my .Net perspective, I&#8217;m going to go over the basics you need to get an internet facing application up and running using Java and the Android SDK.  I&#8217;ll cover, roughly, Activities, basic XML layout, AsyncTask, Intents, permissions, list adapters and, of course you can&#8217;t miss, context.  Along the way I&#8217;ll share with you bits of Java that have caught me out or are relevent to help get these things done.</p>
<p>If you&#8217;ve written an Android application I doubt there is going to be much there for you.  If you&#8217;re an experience Java developer I&#8217;ll probably just make you angry as I butcher the language.  But if you&#8217;ve got experience with .NET and would like to learn about Android native dev and bare in mind that this isn&#8217;t best practice or even particular wonderful code then please come and long and enjoy it.</p>
<p>Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/ddd-north-sessions-android-app/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Update: DirLinker 2.1.1.0</title>
		<link>http://humblecoder.co.uk/uncategorized/update-dirlinker-2-1-1-0</link>
		<comments>http://humblecoder.co.uk/uncategorized/update-dirlinker-2-1-1-0#comments</comments>
		<pubDate>Mon, 20 Dec 2010 08:50:00 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=169</guid>
		<description><![CDATA[This morning I have pushed a new version of DirLinker to Codeplex.&#160; The only change, a response to a bug raised on codeplex, is to allow the entry of network paths in DirLinker’s UI because it possible to create symbolic links to network locations on Vista (or later) but the strict validation used would not [...]]]></description>
			<content:encoded><![CDATA[<p>This morning I have pushed a new version of <a href="http://dirlinker.codeplex.com/releases/view/57839" target="_blank">DirLinker to Codeplex</a>.&#160; The only change, a response to <a href="http://dirlinker.codeplex.com/workitem/3" target="_blank">a bug raised on codeplex</a>, is to allow the entry of network paths in DirLinker’s UI because it possible to create symbolic links to network locations on Vista (or later) but the strict validation used would not allow it.&#160; There is a couple of things to be aware of when creating them:</p>
<ul>
<li>It only works on Vista or later</li>
<li>It can be used for file and folder links</li>
<li>You can not create a link on a network location back to your local machine</li>
<li>If a sym link created on Vista/Server 2008 (or later) is in a shared folder, XP machines will not be able to use it.&#160; As they don’t support sym links, only junction points.</li>
</ul>
<p>As usual don’t hesitate to raise any bugs or give any feedback <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://www.humblecoder.co.uk.gridhosted.co.uk/wp-content/uploads/2010/12/wlEmoticon-smile.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/update-dirlinker-2-1-1-0/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What Makes a Good Code Review?</title>
		<link>http://humblecoder.co.uk/uncategorized/what-makes-a-good-code-review</link>
		<comments>http://humblecoder.co.uk/uncategorized/what-makes-a-good-code-review#comments</comments>
		<pubDate>Wed, 13 Oct 2010 06:14:00 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Best Pratice]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Review]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=165</guid>
		<description><![CDATA[I love code reviews, I really do.  I like having my code looked at and receiving feedback and I like to look at other peoples to see differing styles, techniques and library functions I might not be aware of.  But I always struggle to find the best way to do code reviews.  So I want [...]]]></description>
			<content:encoded><![CDATA[<p>I love code reviews, I really do.  I like having my code looked at and receiving feedback and I like to look at other peoples to see differing styles, techniques and library functions I might not be aware of.  But I always struggle to find the best way to do code reviews.  So I want to take a look what you need to perform a code review and how to review the code.</p>
<h4>Prerequisites</h4>
<p>Some people are just really bad at writing bug reports and work items (I&#8217;m looking at you developers) but this is the most important thing you need when reviewing the code, apart from the code.  You need to able to read the original bug report and understand it then see the developers analysis and proposed solution so you know what you&#8217;re looking at when you review it.  Without this it becomes extremely difficult and time consuming to redo all the work that has already been done to identify the problem.</p>
<p>Leave your style at the door, at the office we don&#8217;t have one complete standard, we have general rules about casing, and what not, but there isn&#8217;t one enforced style. I find it really helps to tune out to subtle differences in style, so long as it&#8217;s readable it really doesn&#8217;t matter.</p>
<h4>The Review</h4>
<p>I like to start with some simple things:</p>
<ul>
<li><strong>Run it &#8211; </strong>Check that the bug has been fixed or the work item has been implemented.  Take it through some basic sanity checks with the debugger attached, if possible, with stop on EVERYTHING enabled and see what it does.  No point in reviewing code that doesn&#8217;t do what it&#8217;s meant to do.  If it has unit tests run them, step through a few with the debugger to get a feel for how it&#8217;s meant to work.</li>
<li><strong>Check for build warnings &#8211; </strong>Ok that might sound petty, but I generally think warning should be treated as errors.</li>
<li><strong>Is it readable – </strong>This is the most important, if you can’t read it how do you expect it to be maintained?  Or you don’t understand the change enough to give it a good review.</li>
</ul>
<p>By this point we have checked that the code is working and that we understand it. Now for the hard part, looking at it.  At the business end of a code review I generally look for the following things (C# specific):</p>
<ul>
<li><strong>Delegate Registration – </strong>Whenever I see a delegate being registered I always look for a corresponding deregistration.</li>
<li><strong>Resources Being Release – </strong>If a resource (file, db, etc) is opened, make sure it is released again at some point.</li>
<li><strong>General Exception Handling – </strong>I always look for things I know, from experience, are likely to throw and see if there is exception handling around it.  Whenever there is a catch block, I look at how it is dealt with and what is caught.</li>
<li><strong>TryParse v Parse – </strong>Parsing values is always error prone, and we do a lot of it in our codebase, so I’m a stickler for correct exception handling or using the TryParse methods.</li>
<li><strong>Null Checking (or Use of a Null Pattern) – </strong>Defensive coding should be our bread and butter so this should always be present</li>
<li><strong>General WTF-ery – </strong>Anything that makes me utter those three little letters.</li>
</ul>
<p>I think this covers most points, it’s not an exhaustive list but I think code reviews are more about checking maintainability than quality, although it definitely helps with it.</p>
<p>When giving feedback I like to try and speak to the person first and ask them about it, remember one person’s WTF is another person’s complex issue. Alternatively, I jot a few points down in an email.  I don’t see the need for a separate code review tool when other forms of communication are effective and flexible.  Finally, always be constructive, it’s hard to get people to listen if your just being negative so state your reasons clearly, ask them why it’s like that and always resist the urge to say “W.T.F is going on here dude”.</p>
<p>I started off this blog post with a view to clarifying in my own mind how best to do code reviews, but looking back and rereading my approach I feel there is room for improvement.  So I ask you my dear readers:  <strong>What do you think makes a good code review?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/what-makes-a-good-code-review/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My Gateway Drug to Professionalism</title>
		<link>http://humblecoder.co.uk/uncategorized/my-gateway-drug-to-professionalism</link>
		<comments>http://humblecoder.co.uk/uncategorized/my-gateway-drug-to-professionalism#comments</comments>
		<pubDate>Mon, 11 Oct 2010 19:35:48 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Unit testing]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=152</guid>
		<description><![CDATA[“Have you considered working in another area in software, you don’t seem to have the right personality type to be a developer”…Said the head of development sat across the table from me.&#160; I sat, head down, a mere 18 months out of university having just delivered my first major product release being told that I [...]]]></description>
			<content:encoded><![CDATA[<p>“Have you considered working in another area in software, you don’t seem to have the right personality type to be a developer”…Said the head of development sat across the table from me.&#160; I sat, head down, a mere 18 months out of university having just delivered my first major product release being told that I was no good at what I do.&#160; I love programming, it has been my hobby since I got my first computer and it was the only job I’d ever wanted to do.</p>
<p>As I’m sure you can imagine, I was devastated but not entirely shocked.&#160; You see I used to rush through a task or bug to get to the next one or get distracted by something shiny.&#160; The best way I can describe it, is as a Magpie effect and, as I was being made aware of at that moment in time, developers are expected to be completer finishers and meticulous to a fault.</p>
<p>I was aware of TDD and I had tried to write some tests but I really struggled with how to make code testable and good unit tests that didn’t just test “stuff”.&#160; But this time I was determined to learn more and put it in to practice, it seemed like the perfect answer.</p>
<h4>Present Day…</h4>
<p>That was nearly two years ago now, I’ve grown massively as a developer since that day and TDD has been <em>my gateway drug to professionalism</em>. When I started off with TDD I thought it was about testing but when I look back at my journey thus far, it&#8217;s about anything but.</p>
<p>One of my biggest problems was rushing, I was always desperate to finish and I missed things or didn&#8217;t think them through properly.&#160; The first thing that writing unit tests helped me to do was slow down and break problems into much smaller chunks.&#160; Just taking a few minutes to consider how best to write the test normally exposes any concerns that need to be separated, edge cases and how the class or function will be interacted with.&#160; If I&#8217;m ever struggling to make a test pass, write a test or if I can&#8217;t make all the tests pass, it normally means I need to go back and look at the tests to see if I&#8217;m trying to solve too much in one go or if it has contradictory responsibilities.</p>
<p>The tests provide excellent documentation that is hard to argue with and stays in step with the code.&#160; This is key because it gives me an insight in to what I was thinking and how I intended on it being consumed.&#160; It&#8217;s, also, the closest to an interactive interrupter for C# I have used, which is great for rapidly checking assumptions and questioning your own code.</p>
<p>Overall it has taught me so much about architecture, design, good practice and maintainability of code.&#160; One conclusion I have to come is that unit testing has a very low regression value.&#160; At this moment in time I rarely, if ever, find bugs using unit tests.&#160; Yes they help to identify failure points but it&#8217;s not very often I find regressions using them.&#160; All they have done is shifted the pain point from if the logic works to if it all works together.&#160; My next challenge is step deeper into the world of the integration testing.</p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/my-gateway-drug-to-professionalism/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stop TFS From Telling You &#8220;Windows Live Messenger is not running&#8221;</title>
		<link>http://humblecoder.co.uk/uncategorized/stop-tfs-from-telling-you-windows-live-messenger-is-not-running</link>
		<comments>http://humblecoder.co.uk/uncategorized/stop-tfs-from-telling-you-windows-live-messenger-is-not-running#comments</comments>
		<pubDate>Mon, 09 Aug 2010 10:51:23 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=148</guid>
		<description><![CDATA[I’ve recently stopped using Live Messenger (moved to Pidgin) and one unexpected side effect of switching was TFS reminding me every time I went to Team Explorer that Messenger isn’t running with this lovely error message: For the past few weeks I’ve been living with it, but it’s becoming increasingly annoying.&#160; So today I finally [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve recently stopped using Live Messenger (moved to Pidgin) and one unexpected side effect of switching was TFS reminding me every time I went to Team Explorer that Messenger isn’t running with this lovely error message:</p>
<p><a href="http://www.humblecoder.co.uk.gridhosted.co.uk/wp-content/uploads/2010/08/image.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://www.humblecoder.co.uk.gridhosted.co.uk/wp-content/uploads/2010/08/image_thumb.png" width="357" height="198" /></a></p>
<p>For the past few weeks I’ve been living with it, but it’s becoming increasingly annoying.&#160; So today I finally worked out how to stop it:</p>
<ol>
<li>Go to the Team Members item in Team Explorer and right click on it</li>
<li>Select <em>Personal Settings </em></li>
<li>On the dialog there is a Collaboration setting, change the provider to <em>None</em></li>
<li>Be free of annoying dialog.</li>
</ol>
<p>Hope this helps some else regain their sanity <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://www.humblecoder.co.uk.gridhosted.co.uk/wp-content/uploads/2010/08/wlEmoticonsmile.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/stop-tfs-from-telling-you-windows-live-messenger-is-not-running/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Multiple Asserts</title>
		<link>http://humblecoder.co.uk/uncategorized/multiple-asserts</link>
		<comments>http://humblecoder.co.uk/uncategorized/multiple-asserts#comments</comments>
		<pubDate>Tue, 01 Jun 2010 16:31:09 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[nUnit]]></category>
		<category><![CDATA[OAPT]]></category>
		<category><![CDATA[Unit testing]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=143</guid>
		<description><![CDATA[I’ve read many books and blogs that advocate only having one assert in a unit test and lots of people take that to mean literally assert statement.&#160; I’ve always disagreed with taking it literally, I’ve always thought of it as one logical assert, as in you assert one concept at a time which could lead [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve read many books and blogs that advocate only having one assert in a unit test and lots of people take that to mean literally assert statement.&#160; I’ve always disagreed with taking it literally, I’ve always thought of it as one logical assert, as in you assert one concept at a time which could lead to multiple assert statements. </p>
<p>The main arguments against having more than one assert statement seems to be it’s not as readable and it’s sometimes difficult to understand what is failing because of it.&#160; My normal response is to create my own asserts that accurately describe what the multiple asserts do and hide the real asserts in there.&#160; For example: </p>
<div id="codeSnippetWrapper">&#160;</div>
<div>
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> AssertIsValidClone(Customer oldCustomer, Customer actualCustomer)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     Assert.AreNotSame(oldCustomer, actualCustomer);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     StringAssert.AreEqual(oldCustomer.Name, actualCustomer.Name);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>     StringAssert.AreEqual(oldCustomer.Address, actualCustomer.Address);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> [Test]</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Clone_ValidCustomer_ValuesAreTheSameReferenceIsDifferent()</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">//Some setup</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     var result = aCustomer.Clone();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     AssertIsValidClone(aCustomer, result);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>&#160;</p>
<p>Ok so this is a very contrived example but we can clearly see what the intent of the assert is rather than having several making it harder to understand.&#160; But what this doesn’t do is address the second concern. IE anyone of those three asserts could fail, so we fix it then the next fails, etc.</p>
<p>Enter an nUnit plug in called <a href="http://rauchy.net/oapt/" target="_blank">OAPT</a>, this allows you to have multi asserts that generate multi unit tests in the runner so you can see exactly what is failing.&#160; I won’t warble on too much about the details because it’s all in the link But let’s just rewrite our unit test:</p>
<p>&#160;</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> [Test, ForEachAssert]</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Clone_ValidCustomer_CloneIsNewItemWithValidData()</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     <span style="color: #008000">//some setup</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>     </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     var newCustomer = originalCustomer.Clone();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     AssertOne.From(</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>         () =&gt; Assert.AreNotSame(originalCustomer, newCustomer)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>         () =&gt; StringAssert.AreEqual(originalCustomer.Name, newCustomer.Name)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>         () =&gt; StringAssert.AreEqual(originalCustomer.Address, newCustomer.Address));</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>&#160;</p>
<p>Much more concise and it will run as three separate tests.&#160; I still do have an issue with it though, each test uses the test name with an appended number. It would be nice if you could pass in some text for it to append.&#160; But then again it is open source so maybe I could add that feature myself <img src='http://humblecoder.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/multiple-asserts/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Directory Linker 2.1 &#8211; XP Support</title>
		<link>http://humblecoder.co.uk/uncategorized/directory-linker-2-1-xp-support</link>
		<comments>http://humblecoder.co.uk/uncategorized/directory-linker-2-1-xp-support#comments</comments>
		<pubDate>Wed, 05 May 2010 06:23:13 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Directory Linker]]></category>
		<category><![CDATA[DirLinker]]></category>
		<category><![CDATA[Reparse points]]></category>
		<category><![CDATA[Symbolic Links]]></category>
		<category><![CDATA[XP]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=142</guid>
		<description><![CDATA[Today I have pushed new binaries to CodePlex for DirLinker.&#160; This new release brings support for folder links in Windows XP/2003.&#160; It is not able to create file links, this is because of the limitations in reparse points in earlier versions of Windows. This is something I didn’t think I would do but after releasing [...]]]></description>
			<content:encoded><![CDATA[<p>Today I have pushed new binaries to <a href="http://dirlinker.codeplex.com">CodePlex for DirLinker</a>.&#160; This new release brings support for folder links in Windows XP/2003.&#160; It is not able to create file links, this is because of the limitations in reparse points in earlier versions of Windows.</p>
<p>This is something I didn’t think I would do but after releasing Dirlinker 2 on Codeplex, a ticket was raised in the bug tracker because it was failing on XP and I was chatting to a friend on IM about it who basically said “Well why doesn’t it?”.&#160; The main reason was because the API call for creating symbolic links is only available in Vista and later.&#160; XP does have an equivalent but the behaviour of the links they create is subtly different.&#160; In XP they are Reparse Points where as in Vista+ they are hard links (similar to *nix), I will go in to the difference in a future post.</p>
<p>It turns out that with a little help from <a href="http://www.codeproject.com/KB/files/JunctionPointsNet.aspx">a CodeProject article</a>, it took less than an hour to put in and test, so it made it in.&#160; I am definitely parking this to new features now.&#160; Only bug fixes will be added from now on.</p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/directory-linker-2-1-xp-support/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Directory Linker 2</title>
		<link>http://humblecoder.co.uk/uncategorized/directory-linker-2</link>
		<comments>http://humblecoder.co.uk/uncategorized/directory-linker-2#comments</comments>
		<pubDate>Mon, 03 May 2010 07:14:50 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CodePlex]]></category>
		<category><![CDATA[Directory Linker]]></category>
		<category><![CDATA[DirLinker]]></category>

		<guid isPermaLink="false">http://www.humblecoder.co.uk/?p=141</guid>
		<description><![CDATA[After literally months of procrastination Directory Linker 2 is finally in state that I’m not too ashamed of.&#160; So today I have posted up new binaries on Codeplex. What’s New? Undo Support&#160;– If the process of moving and deleting a folder before creating a link at the same location failed, you could end up with [...]]]></description>
			<content:encoded><![CDATA[<p>After literally months of procrastination Directory Linker 2 is finally in state that I’m not too ashamed of.&#160; So today I have posted up <a href="http://dirlinker.codeplex.com">new binaries on Codeplex</a>.</p>
<h3><strong>What’s New?</strong></h3>
<ul>
<li><strong>Undo Support</strong>&#160;<strong>–</strong> If the process of moving and deleting a folder before creating a link at the same location failed, you could end up with some files in the new location, some in old and two partial directory structures.&#160; If this happens now DirLinker will offer to put the original folder back how it was.      </p>
<p>If you’re using the just delete option and it fails, undo <strong>can not</strong> undelete any files but it will put back any folders it deleted.</li>
<li><strong>File Links</strong> – It can now create symbolic links for files as well as directories.&#160; You don’t have to do anything different, just select a file in the link location or the link to field.&#160; There has been a small change to the UI to allow you to browse for files aswell as folders.
<p>In a future post I’m going to talk about the difference between symbolic links and shortcuts.&#160; But for now the important difference is the application opening file doesn’t know the file is only a link when using symbolic links. </li>
<li><strong>Progress Window Changes – </strong>The progress window has been slightly overhaul and now keeps a list of everything it has done.&#160; So if it does fail or something goes wrong, you can work out exactly what it’s done.</li>
</ul>
<p><a href="http://www.humblecoder.co.uk/wp-content/DirectoryLinker2_AE58/progressWindow.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="Progress Window" border="0" alt="Progress Window" src="http://www.humblecoder.co.uk/wp-content/DirectoryLinker2_AE58/progressWindow_thumb.png" width="616" height="299" /></a></p>
<p>With these features I’m planning on parking Directory Linker development, I will of course fix any bugs that may come up but I can’t see any new features being added.</p>
<p>Enjoy!</p>
<p>PS, If you have no idea what Directory Linker is, <a href="http://www.humblecoder.co.uk/?p=50">this is</a> a good place to start.</p>
]]></content:encoded>
			<wfw:commentRss>http://humblecoder.co.uk/uncategorized/directory-linker-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

