<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Developer Drain Brain</title>
	<atom:link href="http://drainbrain.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://drainbrain.wordpress.com</link>
	<description>The dregs leftover after development</description>
	<lastBuildDate>Sun, 27 Nov 2011 22:47:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='drainbrain.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Developer Drain Brain</title>
		<link>http://drainbrain.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://drainbrain.wordpress.com/osd.xml" title="Developer Drain Brain" />
	<atom:link rel='hub' href='http://drainbrain.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Is Exception Handling Broken on .Net?</title>
		<link>http://drainbrain.wordpress.com/2011/11/27/is-exception-handling-broken-on-net/</link>
		<comments>http://drainbrain.wordpress.com/2011/11/27/is-exception-handling-broken-on-net/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 22:47:51 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=207</guid>
		<description><![CDATA[Here&#8217;s a challenge for you. Take a .Net project of yours (a large one, preferably in c#) and look at how much exception handling is done. Now, for every try/catch statement, prove that you&#8217;re catching only the exceptions that you expect to be thrown. This is the challenge facing anyone who wants to correctly handle [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=207&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a challenge for you. Take a .Net project of yours (a large one, preferably in c#) and look at how much exception handling is done. Now, for every try/catch statement, <em>prove</em> that you&#8217;re catching only the exceptions that you expect to be thrown.</p>
<p>This is the challenge facing anyone who wants to correctly handle their error conditions. It&#8217;s also a challenge that you should be willing to step up to if you want to get your code windows logo certified.</p>
<p>There&#8217;s a problem if you miss exceptions that should be caught. If you do that, your application will simply crash, unceremoniously losing anything your customer hasn&#8217;t saved and possibly earning you an angry phone call. In terms of customer satisfaction, it&#8217;s clearly the #1 thing to avoid doing.</p>
<p>There&#8217;s also a problem if you catch exceptions that you shouldn&#8217;t. The worst case scenario there is that you&#8217;re corrupting user data. More likely, you&#8217;re hiding the place where an original problem occurred and saving the actual crash for later. If you&#8217;re really good at catching everything you shouldn&#8217;t, you might be limping along in a bad enough state where the user has to just stop and restart the application before things start working properly again. I know I&#8217;ve been there as a user many times.</p>
<p>If you&#8217;re signed up for Windows Error Reporting, catching too many exceptions means that you don&#8217;t get notified of real problems with your application, meaning there are a whole set of problems you don&#8217;t see, or end up manifesting in some unexpected and un-debuggable place.</p>
<p>So exception handling appears to be this wonderful balancing act, it&#8217;s essential that you get just enough and not too much. I assume you&#8217;d rather be pro-active and double check that you&#8217;ve got all the error cases correctly covered rather than let your customers find them with a crash.</p>
<p>Good luck.</p>
<p>Seriously, I find it hard to believe I&#8217;m writing this, but you can&#8217;t do it.</p>
<p>Sure, you can read the documentation for every method you call, check what you need to do for every documented exception and handle it. That&#8217;s actually quite a lot of work, especially if you&#8217;re doing it for an existing project. If you&#8217;re lucky all the exceptions will be documented, they&#8217;ll even be documented correctly and fully, including all the 3rd party libraries you use &#8230; and all the internal ones.</p>
<p>And once you&#8217;ve done all that, the only way you can verify that it&#8217;s correct in your next release is to do it again. Now what happens when you go to the next version of a 3rd party library or .Net. You need to examine every method you use to see if any new exceptions have been added, old ones removed, or the handling requirements of the others changed. Then check that your code handles them all correctly, in every location.</p>
<p>You&#8217;d think there would be a tool to help you with this. But there&#8217;s nothing in .Net or visual studio that offers any clue. One company, RedGate, did do this at one point. However, reading their website, they were having trouble keeping the list meaningful, and with .Net 4, they <a href="http://www.red-gate.com/products/dotnet-development/exception-hunter/"><em>gave up</em></a>.</p>
<p>So even if you catch only the exceptions that are actually thrown, you&#8217;re safe, right?<br />
Of course not. Because someone, somewhere will be throwing a raw &#8220;System.Exception&#8221;, and the only way to catch that is to catch &#8220;System.Exception&#8221; and that catches everything. So now you need to catch everything, then check to see if it&#8217;s what you really thought it was and re-throw everything else.</p>
<p>Of course, you&#8217;re re-throwing with just the &#8220;throw&#8221; statement, right? Not the &#8220;throw obj&#8221; version of the statement. Everywhere. Sure?</p>
<p>Lets assume you can change this code to throw something sensible instead of a raw System.Exception. How about a System.ApplicationException, that&#8217;s bound to be just the exception we were expecting to catch, right? If you answered &#8220;No&#8221;, you&#8217;re getting the hang of this. The .Net framework will happily throw its own exceptions which are derived from ApplicationException, even if you haven&#8217;t derived anything from it yourself. So you still need to check the actual exception type after you catch it just to make sure it&#8217;s something you expected. No, you need to ignore what Microsoft have given you and make your own exception hierarchy derived directly from System.Exception.</p>
<p>Ok, so we&#8217;ve done all that. We&#8217;ve manually gone through the latest documentation for every method we ever call and checked that we&#8217;re handling all the exceptions correctly. We&#8217;re not throwing any base-class exceptions that aren&#8217;t our own and we&#8217;re re-throwing everything correctly. We&#8217;re clear now, right?</p>
<p>Ah, you&#8217;re catching on, not yet. Let&#8217;s look at that web service you use, you&#8217;re catching a WebException, right? You&#8217;ve checked the inner exception as well, haven&#8217;t you? Why? Because although Microsoft will deny you a windows logo certification if you catch too many exceptions, they don&#8217;t follow their own advice. If something like AccessViolationException occurs whilst calling a web service, it will get wrapped up very nicely in a WebException and presented to you just like a timeout, or a connection failure, or a 500 error. So you might need to leak a WebException. </p>
<p>So what could InnerException be in these cases then? Surely that&#8217;s documented? Yeah, right.</p>
<p><strong>Why is this such a hard problem?</strong></p>
<p>It strikes me after much pain working through all this, that .Net&#8217;s exception handling is fundamentally flawed. </p>
<p>Firstly, we rely on documentation to work out what exceptions can be called. We don&#8217;t rely on documentation to work out what parameters to pass, or what return values we get, yet handling the error conditions is left to our discretion.</p>
<p>Secondly, there are some exceptions which could get thrown at any point and would probably never be thrown by your own code. The clearest cases are things like StackOverflowException and AccessViolationException. Perhaps NullReferenceException is in this list too. We would almost never want to catch these. These are genuine coding errors and never something to do with the state of our user&#8217;s workflow. Yet we have no way to determine what exceptions fall into this category.</p>
<p>The exception hierarchy is a joke. The knee-jerk reaction for how to categorize AccessViolationException is to say &#8220;It derives from System.SystemException, exceptions derived from here must be serious!&#8221;. And then you find yourself leaking when you parse a user&#8217;s badly formatted xml snippet, because XmlException is also derived from there. These aren&#8217;t isolated incidents, you can&#8217;t tell anything meaningful from the .Net exception hierarchy. The namespace usage is slightly better, but still useless.</p>
<p>If an exception is going to be a base class, it must never be thrown. There&#8217;s a built in mechanism for this, it&#8217;s called the abstract class. An abstract base class will never be thrown directly preventing a whole category of errors. And once an exception class is made concrete, it must never be subsequently derived from. We have a mechanism for this too &#8211; sealed classes can&#8217;t be derived from. Yet these mechanisms are not made use of in the built in exception hierarchy.</p>
<p><strong>So what can we do to mitigate these problems?</strong></p>
<p>Well, at the end of the day, your exception handling is your <em>best guess</em>. You can&#8217;t make it any better than that, so 90% is the way to go. Sign up to Windows Error Reporting and find what you&#8217;re leaking in the field. It&#8217;s a shame that as a top tier development company, that&#8217;s the best you can do, but it&#8217;s the best that <em>anyone</em> can do, so don&#8217;t feel bad.</p>
<p>In those cases where a leak would be a truly terrible thing, do what you did anyway.<br />
Let&#8217;s be honest, your windows form event handlers are all wrapped with &#8220;try {} catch (Exception e) {}&#8221; aren&#8217;t they. Because after years of pissed off customers that&#8217;s what you&#8217;ve resorted to. Yes, your deeper code all does proper exception handling as you want, but the lure of the safety net was too much for your bottom line to resist. Well, in those critical, high level places, keep doing that. But try to categorize the list of exceptions you <strong>don&#8217;t</strong> want to catch and make sure you leak them. Unless you&#8217;re doing something really funky, you don&#8217;t want to hide an AccessViolationException.</p>
<p>And of course, unit testing can help. It&#8217;s not 100%, firstly because your coverage won&#8217;t be 100%, also because you&#8217;re still relying on documentation to work out what exceptions you&#8217;re supposed to be emulating, and also because a lot of exceptions that happen in practice are environmental problems, like dropped connections.</p>
<p><strong>But the best way to handle your exceptions?</strong></p>
<p><em>Don&#8217;t.</em></p>
<p>At least, don&#8217;t if you can get away with it. Just crash. In many cases that&#8217;s the best thing to do. If you&#8217;re a service, it&#8217;s a no-brainer, assuming your service will be auto-restarted. A web page returning an error is a good thing for visibility of errors.<br />
They get logged, and you can find out about every single one of them as they happen.</p>
<p>Avoid getting in to situations where exceptions are possible. Always use &#8220;TryParse&#8221; instead of &#8220;Parse&#8221;, for example. Always check that the file exists before opening it. That sort of thing. If you&#8217;re thinking of throwing an exception, offer a way for people to find out what the situation is before you need to throw it.</p>
<p>Going 100% exception free isn&#8217;t possible. Some databases throw exceptions that demand the transaction be retried. That&#8217;s aggravating, but handle it and leak everything else.<br />
A web service call should be retried a couple of times if certain error codes get returned. But anything else, let it go.<br />
Keep it minimal.</p>
<p>The cost of crashing a windows application is higher. But why are you writing thick client applications in this day and age? Perhaps you can treat it as a container for applets that crash with impunity &#8211; I&#8217;m thinking of  Chrome&#8217;s &#8220;aw snap!&#8221; errors here.</p>
<p>Crash, seriously. It&#8217;s the future.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/207/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/207/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/207/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=207&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2011/11/27/is-exception-handling-broken-on-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>Playing with long polls</title>
		<link>http://drainbrain.wordpress.com/2011/04/05/playing-with-long-polls/</link>
		<comments>http://drainbrain.wordpress.com/2011/04/05/playing-with-long-polls/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 12:11:13 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=177</guid>
		<description><![CDATA[Server Push is a technique to get data down to a client as soon as it becomes available. It&#8217;s also got other names such as Long Poll and Comet. There&#8217;s nothing particularly fancy about the technique, it&#8217;s essentially a web request that takes a really long time. The request stays open until whatever data the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=177&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Server Push is a technique to get data down to a client as soon as it becomes available. It&#8217;s also got other names such as Long Poll and Comet.</p>
<p>There&#8217;s nothing particularly fancy about the technique, it&#8217;s essentially a web request that takes a really long time. The request stays open until whatever data the client&#8217;s interested in is available on the server.</p>
<p>Using it means that clients can get updates almost as soon as they happen on the server without polling. Polling is generally inefficient and wasteful of both network resources and server processing. It&#8217;s up to the client to work out when they poll and you can never really tell when or if a client is going to get the update.</p>
<p>Server push is really easy to configure &#8211; if your client can make a web request to your server, then you can use this technique without installing any fancy software or opening any unexpected ports, it just works.</p>
<p>The trick with Server Push is to have a very efficient server. Traditional web servers would start up a thread for each and every connection. Whilst this works when you&#8217;ve got very limited simultaneous requests, it doesn&#8217;t scale up very well when dealing with lots of requests that, for most of their lives, aren&#8217;t doing anything.</p>
<p>Frameworks like python&#8217;s <a href="http://twistedmatrix.com/trac/">Twisted</a>, ruby&#8217;s <a href="http://rubyeventmachine.com/">EventMachine</a> and javascript&#8217;s <a href="http://nodejs.org/">Node.Js</a> have shown a way where this can be really efficient &#8211; don&#8217;t spawn threads, just process them using events. So we know it&#8217;s possible &#8211; are there any other ways to do it?</p>
<p>I&#8217;ve been looking at the problem using .Net&#8217;s <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx">HttpListener</a>, which is actually quite efficient. It&#8217;s essentially the same as <a href="http://msdn.microsoft.com/en-us/library/aa364510%28v=vs.85%29.aspx">http.sys</a>, but in managed code. Web requests come in through a call to <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.getcontext.aspx">GetContext</a> &#8211; but no extra thread is created, you just get an <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistenercontext.aspx">object</a> representing the <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistenerrequest.aspx">request</a>, and you <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistenerresponse.aspx">respond</a> to it as you see fit.</p>
<p>It&#8217;s quite simple then, to put the requests that come in straight onto a list and wait for something to happen to your data. When that something happens, simply iterate over the list sending the updates to the clients. You don&#8217;t have to reply from the same thread that accepted the request &#8211; indeed there&#8217;s no need to reply immediately at all.</p>
<p>It&#8217;s a beautifully simple principle and works really well. I&#8217;ve had 135k active connections on my test machine and it doesn&#8217;t even break a sweat. Once the connections are made, the only resource used is RAM, and those 135k connections only used about 800mb. No handles, threads or cpu are consumed on the server, so there&#8217;s no fixed upper limit that I can find.</p>
<p>What&#8217;s even better, is that clients will appear to wait forever for the results. I&#8217;ve had tests running for &gt;12hrs, then receiving the response and carrying on like nothing was amiss.</p>
<p>It&#8217;s also worth noting that <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx">HttpListener</a> can be a really good server in it&#8217;s own right, by caching the replies sent down to each client, I&#8217;ve been able to consistently handle 150k requests a minute on a quad core server over 100mb/s network connection.</p>
<p>There&#8217;s a few things I&#8217;ve found that are worth noting:</p>
<h6>Server</h6>
<dl>
<dt>Accept connections as quickly as possible
<dt>
<dd>In essence this means getting to the next call to <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.getcontext.aspx">GetContext</a> as quickly as possible. There are two methods you can use for this &#8211; have a single loop that continuously calls <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.getcontext.aspx">GetContext</a> and farms out the actual work in some way, or use <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.begingetcontext.aspx">BeginGetContext</a>, and in the callback method, call <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.begingetcontext.aspx">BeginGetContext</a> again immediately, before you process your current request.</dd>
<dt>Remember that <a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx">List</a> is backed by an array.</dt>
<dd>If you&#8217;re adding hundreds of thousands of items to it in a time critical context (such as within a lock block) it gets <em>really</em> inefficient as it copies the data each time it grows the backing array. You can either pre-allocate if you know roughly how many items will be in it, or just use a <a href="http://msdn.microsoft.com/en-us/library/he2s3bh7.aspx">LinkedList</a> &#8211; which has constant time adds and removes &#8211; which is what you&#8217;ll likely be doing most of the time anyway. <a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx">List</a> is really bad if you start paging, since it&#8217;s essentially copying that data at disk speed.</dd>
<dt>Don&#8217;t block the list</dt>
<dd>The list is central to this processing, and every lock on it reduces your ability to service requests. An example is in sending out the replies &#8211; it may not take long to loop over 100k objects in a list and call BeginWrite on each one, but it takes a few seconds. It&#8217;s much better to take your lock (which isn&#8217;t on the list itself), copy the list reference and create a new list in its place. Then you can iterate through your list of subscribers at leisure without hampering the server&#8217;s ability to accept new requests. If you&#8217;ve got a lot of subscribers, those clients that you serviced at the beginning of the list will already be queueing up for the next update by the time you get through your list, so this is far from academic.</dd>
<dt>Don&#8217;t throw that exception</dt>
<dd>Time really is of the essence, whether you&#8217;re getting an entry onto a list or sending the data out, it needs to be quick. Throwing exceptions is slow. So even though it&#8217;s more clunky, use that TryParse instead of Parse and structure your logic so that you&#8217;re not throwing trivial failures into the exception handler for mere coding convenience.</dd>
<dt>Cache <em>Everything</em></dt>
<dd>This setup can be really efficient if the same data is being sent to everyone. In this case, you can render the data you send to one client into a byte array and keep it, so that every subsequent client receives a copy of that same byte array.</dd>
<dt>Use a versioned REST style interface</dt>
<dd>This is just a suggestion, but use the url to locate what resource you want, and have the client send a query string stating what version they&#8217;ve got. If your current version doesn&#8217;t match or the client doesn&#8217;t provide a version, just send back the latest version to the client without queueing anything. If the version does match, add it to the subscriber list for when the next version becomes available. It goes without saying that you need to synchronise this so that no-one gets left behind.</dd>
<dt>Use the background threads</dt>
<dd>I&#8217;m a little more cautious about this advice, but it&#8217;s worked for me in my testing &#8211; using the asynchronous calls for everything does appear to work really nicely. One note of caution &#8211; the thread count can go up alarmingly once things start going wrong (actually, I&#8217;ve only seen this on the client, not the server). It&#8217;s only a temporary situation, however, once the issue is resolved the threadpool sorts itself out nicely.</dd>
<dt>Have a plan for dropped subscribers</dt>
<dd>In my proof of concept I didn&#8217;t really care, but in reality, the subscribers can disconnect. Clearly, you don&#8217;t want to keep these in your list any longer than necessary. I haven&#8217;t yet found a way of cleanly and reliably detecting a failed connection using the <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx">HttpListener</a> classes, although I haven&#8217;t looked too hard. It might be the case that the best you can do is return an empty response and ask them to reconnect. Whilst this might not sound any better than polling, it&#8217;s still fairly lightweight, responsive, and the server can dynamically determine what it needs to do, modifying these &#8216;poll periods&#8217; according to load.</dd>
</dl>
<h6>Client</h6>
<p>I&#8217;ve actually found it much harder to write a client that makes 50k requests than a server that accepts 100k requests.</p>
<dl>
<dt>Know your http limits</dt>
<dd>By default, only 2 http concurrent connections are made &#8211; per <em>machine</em> to any particular server. Use <a href="http://support.microsoft.com/kb/282402">kb282402</a> to fix this if you&#8217;re using a wininet based client, and set <a href="http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx">ServicePointManager.DefaultConnectionLimit</a> if you&#8217;re using .Net&#8217;s <a href="http://msdn.microsoft.com/en-us/library/system.net.webrequest.aspx">WebRequest</a> class</dd>
<dt>Know your ports</dt>
<dd>Each request to the server requires an open, bound port on the client. There are only ~65k available for each ip-address. So if you want &gt;65k connections from one machine, you&#8217;ll have to have multiple ip addresses on the network and bind your requests to them explicitly. Also, windows varies how many ports are available for this use. My developer machine allowed everything &gt;1024 for this, whereas Vista/2008 and above only use ports &gt;49124. This limits you to about 16k outbound connections of any kind. Use <a href="http://support.microsoft.com/kb/929851">kb929851</a> to configure this. Also keep in mind that ports don&#8217;t become available just because the connection closed. Ports can stay unavailable for 4 minutes whilst they mop-up any late server packets. This can be reduced by the OS if there are a lot of ports in this state, but it can bite you if you&#8217;re trying to recycle your 50,000 connections.</dd>
<dt>Know your handles</dt>
<dd>With .Net&#8217;s <a href="http://msdn.microsoft.com/en-us/library/system.net.webrequest.aspx">WebRequest</a> class, and probably with any outbound network connection, a handle is created for each one. Windows XP limited the number of open user handles to <a href="http://support.microsoft.com/kb/327699">10,000</a>, in windows 2008R2 I&#8217;ve not had any trouble when running 50,000 connections, but it&#8217;s something else to be aware of.</dd>
<dt>Any server can be flooded, live with it</dt>
<dd>A server can only accept so many connections a second. The network stack can itself queue up the backlog of connections, but the size of the backlog is limited (the <a href="http://support.microsoft.com/kb/154628">best documentation</a> I can find says between 5 &amp; 200). Beyond this, the network stack will reject the connections without your server code ever knowing that they were there. This is the main reason why it&#8217;s so important to accept those connections quickly. But even so, if you&#8217;re making 50,000 asynchronous connections to a server, from 4 clients, at the same time for a total of 200k connections, that could all take place in a few seconds. No server can handle that, you will get errors, and you must have a way of recognizing them, handling them gracefully and re-trying them.</dd>
</dl>
<p>I wonder how many people can make use of this technique, how many people are using this, and what other issues there are with this. Has anyone found a different solution for the problem?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/177/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/177/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/177/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=177&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2011/04/05/playing-with-long-polls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>std::vector indexes have a type &#8211; and it&#8217;s not &#8220;int&#8221;</title>
		<link>http://drainbrain.wordpress.com/2010/12/02/stdvector-indexes-have-a-type-and-its-not-int/</link>
		<comments>http://drainbrain.wordpress.com/2010/12/02/stdvector-indexes-have-a-type-and-its-not-int/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 12:51:49 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Coding Standards]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=163</guid>
		<description><![CDATA[Just a quick aside, I&#8217;ve seen a fair bit of code recently of this kind: std::vector&#60;int&#62; myvector = &#8230; for (int i = 0; i &#60; myvector.size(); ++i) &#8230; This code produces a warning when compiled, and it&#8217;s right to do so. Vectors are awkward beasts &#8211; this means that they fit in with the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=163&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Just a quick aside, I&#8217;ve seen a fair bit of code recently of this kind:</p>
<p>std::vector&lt;int&gt; myvector = &#8230;<br />
for (int i = 0; i &lt; myvector.size(); ++i)<br />
&#8230;</p>
<p>This code produces a warning when compiled, and it&#8217;s right to do so.</p>
<p>Vectors are awkward beasts &#8211; this means that they fit in with the rest of c++. In particular, the type of the variable &#8220;i&#8221; above, is not an int, unsigned int or a dword, it&#8217;s std::vector&lt;int&gt;::size_type.</p>
<p>This size type is also the numeric value accepted by the [] operator. Int will pass into this operator without warning, but it&#8217;s not correct. And going the other way &#8211; especially via myvector.size(), is a potential issue.</p>
<p>So the for loop above should be written:<br />
std::vector&lt;int&gt; myvector = &#8230;<br />
for (std::vector&lt;int&gt;::size_type i = 0; i &lt; myvector.size(); ++i)<br />
&#8230;</p>
<p>Or, even better, use iterators!</p>
<p>See also:</p>
<p>http://www.cplusplus.com/reference/stl/vector/</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/163/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=163&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/12/02/stdvector-indexes-have-a-type-and-its-not-int/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>A Journey Through Source Control. Part 3. Thinking the Wrong Way Round</title>
		<link>http://drainbrain.wordpress.com/2010/11/18/a-journey-through-source-control-part-3-thinking-the-wrong-way-round/</link>
		<comments>http://drainbrain.wordpress.com/2010/11/18/a-journey-through-source-control-part-3-thinking-the-wrong-way-round/#comments</comments>
		<pubDate>Thu, 18 Nov 2010 13:32:19 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=157</guid>
		<description><![CDATA[It&#8217;s time for a short rant. ﻿﻿﻿﻿Something I&#8217;ve seen a lot when working with fellow developers who haven&#8217;t been formally introduced to a tool from the 3rd generation is a set of practices that just leave a bad taste in my mouth. First off, a 2nd generation tool would generally make mapping the repository to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=157&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s time for a short rant. ﻿﻿﻿﻿Something I&#8217;ve seen a lot when working with fellow developers who haven&#8217;t been formally introduced to a tool from the 3rd generation is a set of practices that just leave a bad taste in my mouth.</p>
<p>First off, a 2nd generation tool would generally make mapping the repository to the hard-disk very difficult, so people would check out the entire repository onto their disks to work on. This was fine at the time, but lead to a lot of problems. One of them was that no-one was ever isolated from each other&#8217;s changes &#8211; if you &#8216;got latest&#8217; there was a very good chance that some of the shared code would be broken in some subtle way. Do that a few times and you quickly get wary of the practice, and end up just getting the minimum you can get away with at any point in time.</p>
<p>But if we look at the 3rd generation, things are a bit different. We&#8217;ve got specific, well defined versions that cut across all our files. Now, I don&#8217;t know about you, but to me, it feels much better to pull out a single card from a deck (hopefully the top one), work on it, then put the changes back as a new card on the top of the deck again.</p>
<p>If someone was to take that card, then build it, assuming that the build works we *know* that that version is good &#8230; and it will be forever. If I want to make another change, I can take that card, in its entirety, with impunity, and *know* &#8211; with 100% certainty that it will work. This means that when I make changes, if they work, then the card I put back on the pile will work as well. And we can guarantee that by having an automated system take that card and test it, giving it a green tick if it&#8217;s ok.</p>
<p>Unfortunately, most 3rd generation tools let you mix and match cards, so the practice of getting the least you can get away with still kind of works with them. But look &#8211; I&#8217;ve got a stack of shiny cards here, and each card has been carefully crafted to guarantee that it&#8217;s good and has been verified by automatic tools that this is the case. But if you have half of your files from one card, a third from another and the rest from a half a dozen other cards &#8211; exactly what are you working with? How can you guarantee anything at all? How can you be sure that the card you&#8217;re about to put on the top of the pile will work with everyone else, when you&#8217;ve never tried it yourself? (You can&#8217;t have tried it &#8211; you don&#8217;t <em>have</em> it). It feels about as messy and taking a dozen playing cards and making a new card out of them by cutting them up and taping them together.</p>
<p>Of course, no-one&#8217;s perfect. Mistakes will get into the system. But if I take a bad card, and make my changes to it, the card I put back will also be bad &#8211; and I won&#8217;t know if it&#8217;s my fault or something that was already there. This means that we need to identify bad cards as soon as possible, and fix them immediately, so that we can be sure if we find a bad card with our name against it, the problem really was ours. The fix is just a new card, (since we can&#8217;t change the old cards), but the fact that we&#8217;ve spotted a bad card and fixed it quickly means that the next cards that get added to the system can be sure of a good stable base to work from.</p>
<p>One of the things I like most about this system is that if the worst comes to the worst, we can always scrap what we&#8217;ve got, get the latest known good card, and work with that. Instant cleanup is always available. We can also pull any particular card out and see if it had a particular problem, and if it did (and the previous card didn&#8217;t) we have a good start at working out exactly what went wrong and a shortlist of what files might be involved.</p>
<p>So we&#8217;ve not a got a mental model of what our 3rd generation system is doing. We&#8217;re working on a single card at a time and building up our stack of changes, verifying each one as we go. Next we&#8217;ll look in a bit more depth at how branches work, what they mean and how to work with them.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/157/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/157/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/157/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=157&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/11/18/a-journey-through-source-control-part-3-thinking-the-wrong-way-round/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>A Journey Through Source Control. Part 2. Jumping to the 3rd Generation</title>
		<link>http://drainbrain.wordpress.com/2010/11/17/a-journey-through-source-control-part-2-jumping-to-the-3rd-generation/</link>
		<comments>http://drainbrain.wordpress.com/2010/11/17/a-journey-through-source-control-part-2-jumping-to-the-3rd-generation/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 13:27:41 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=153</guid>
		<description><![CDATA[Ok, I admit it, most people just don&#8217;t care about source control, and why should they? It&#8217;s a tool that they use to get things done, and so long as they don&#8217;t lose their work, who cares about anything else? I think it&#8217;s because of this disinterested mindset that a lot of people completely missed [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=153&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ok, I admit it, most people just don&#8217;t care about source control, and why should they? It&#8217;s a tool that they use to get things done, and so long as they don&#8217;t lose their work, who cares about anything else?</p>
<p>I think it&#8217;s because of this disinterested mindset that a lot of people completely missed what the 3rd generation of tools were about. And it&#8217;s not too suprising, advertising like &#8220;ACID compliant transactions &#8211; never partially commit a set of changes again!&#8221; aren&#8217;t exactly hinting at the revolutionary upheaval that had happened on the server side, it just sounds like CVS in a database.</p>
<p>But what happened was that the history in the repositories was completely pivoted around. CVS, VSS, et al would keep a single tree of files, and each file would have it&#8217;s own history. SVN, TFS, etc, don&#8217;t keep a set of files, they keep a set of <em>trees</em>. Each revision in the repository represents the state of every file in the entire source control tree at that point in time. Think of a stack of playing cards, each with the entire source control tree drawn on it. Each time you commit a change to any file in the repository, an new card is drawn up with the previous tree + your changes and put on the top of the pile. This means that the entire source control in the repository can be reliably retrieved by giving just one number &#8211; just tell the system what card you want and you can get it.</p>
<p>No longer do we need hacks like &#8216;labels&#8217; to make sure that everything is kosher and retrievable, everything is labelled with each and every change as an automatic by-product of how the repository works. Of course, we don&#8217;t lose the ability to view the changes that were made to a particular file: given a path, we can diff the contents of the file in one revision with the contents in the next and get the changes just like we could before. But we also get a brand new ability &#8211; by getting the difference between one tree and the previous tree, we can see all the files that were changed at the same time &#8211; and it&#8217;s this set of diffs that makes up a &#8216;changeset&#8217;.</p>
<p>It&#8217;s this natural creation and handling of changesets that gives us a much better ability to migrate changes around the repository. Say I have two identical copies of a file in two places in the repository. If I make a change to file A, I can retrieve the changeset at any time I like, this results in a diff, and I can apply this diff to file B whenever I feel like it. Expand this concept to directories and work with changesets instead of individual diffs, and we&#8217;ve got the basis for a very flexible and simple branching and merging system. Branching is simply making a copy of a directory in another location, merging is simply getting the changesets that were applied to one directory, and applying them to the other. This branching and merging can all be tracked within the repository itself and voila, we have a modern 3rd generation system with full branching support.</p>
<p>So now we know what the differences between the 2nd &amp; 3rd generation are, we&#8217;ll address in the next post some of the pitfalls that we fall into when we try to think of a 3rd generation system in terms of a 2nd generation system.</p>
<p>And don&#8217;t worry, I&#8217;ve not forgotten about the 4th generation, that&#8217;s coming, but since it builds on what the 3rd generation gives us, I think it&#8217;s important to square that away first.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/153/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=153&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/11/17/a-journey-through-source-control-part-2-jumping-to-the-3rd-generation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>A Journey Through Source Control. Part 1. Generations of Source Control</title>
		<link>http://drainbrain.wordpress.com/2010/11/16/a-journey-through-source-control-part-1-generations-of-source-control/</link>
		<comments>http://drainbrain.wordpress.com/2010/11/16/a-journey-through-source-control-part-1-generations-of-source-control/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 13:27:32 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=141</guid>
		<description><![CDATA[In this series I&#8217;m going to be looking at some of the key concepts available in source control, and how they can be applied to gain full control over your source code. Now, in all fairness, I don&#8217;t make my living by telling people how to use source control, but it&#8217;s one of the things [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=141&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In this series I&#8217;m going to be looking at some of the key concepts available in source control, and how they can be applied to gain full control over your source code.</p>
<p>Now, in all fairness, I don&#8217;t make my living by telling people how to use source control, but it&#8217;s one of the things that fascinate me about software development, purely because it&#8217;s so underused and misunderstood by a large percentage of my fellow developers.</p>
<p>The first thing that I think is important to grasp is that we&#8217;ve already churned through several generations of source control tools. I can easily identify 4 generations based on just the surface architectures involved, and each one represents a significant advantage over the previous generations.</p>
<table border="”1″" cellspacing="”0″" cellpadding="”0″" width="390">
<caption>Source Control Generations</caption>
<tbody>
<tr>
<td><strong>Generation</strong></td>
<td><strong>Feature</strong></td>
<td><strong>Example</strong></td>
</tr>
<tr>
<td>1</td>
<td>History of individual files</td>
<td>SCCS/RCS</td>
</tr>
<tr>
<td>2</td>
<td>Networked server</td>
<td>CVS/VSS</td>
</tr>
<tr>
<td>3</td>
<td>History of whole trees</td>
<td>SVN/TFS</td>
</tr>
<tr>
<td>4</td>
<td>Distributed repositories</td>
<td>Git/Hg</td>
</tr>
</tbody>
</table>
<p>So with the first generation of tools such as RCS, we had the ability to keep the history of the files we were working on. That was pretty much it, really. Working with multiple files was tricky at best, and sharing wasn&#8217;t exactly safe, as everyone would work in the same shared folder.</p>
<p>CVS &amp; VSS came along and rescued us from this situation by wrapping RCS and keeping all it&#8217;s files in a repository, which could be accessed through a server on the network. This meant that all developers could have their own copy of their files on their machines, isolated from everyone else. Then when work was complete, the changes could be sent up to the server and new changes brought down.</p>
<p>This CVS style working is all very well, but it still has problems &#8211; namely that files are still versioned individually and that it can be very hard to reliably isolate changes that happened together across a range of files after the fact. SVN and others came on to the scene to rectify this by keeping all the revisions in a single stack of changes, numbered sequentially. Changes to multiple files could be kept within a single revision, or changeset, and you could see not only what changes were made to a particular file, but drill down into each change to find out what the full story was each time. This also makes branching and merging a far more tenable idea since a complete &#8216;changeset&#8217; could be reliably migrated in full across different branches.</p>
<p>And most recently, after having 3 generations of centralised repositories, Git, Hg and others threw away the need for an enforced central repository. The effect of this is that it no-longer matters exactly where source code is located &#8211; what matters is the actual content itself, which could come from anywhere. Whether I pulled revision &#8217;24g4g2&#8242; out of the main company server, a junior developer&#8217;s laptop, a pirate website or the smoking remains of a tape in the server room, I would be guaranteed that the code was exactly what I was after, including all the history up to that point. Central servers are now used at your team&#8217;s convenience, not just because the tool demands one.</p>
<p>So there we go, a very short, and incomplete, potted history of source control tools.</p>
<p>Next we&#8217;ll look in more detail at the jump from 2nd generation to 3rd generation &#8211; and how so many people are thinking of it the wrong way round.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/141/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=141&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/11/16/a-journey-through-source-control-part-1-generations-of-source-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>Straightening out the development cycle</title>
		<link>http://drainbrain.wordpress.com/2010/04/07/straightening-out-the-development-cycle/</link>
		<comments>http://drainbrain.wordpress.com/2010/04/07/straightening-out-the-development-cycle/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 12:04:03 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[UnitTest]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=123</guid>
		<description><![CDATA[This is me trying to get things sorted in my head. Know your features Features are your lifeblood. Organise them, manage them, combine them into stories. Process them with great care. Tuck them in and sing them to sleep at night. All features are great. It&#8217;s the organisation of them that gives you the edge. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=123&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>This is me trying to get things sorted in my head.</em></p>
<h2>Know your features</h2>
<p>Features are your lifeblood. Organise them, manage them, combine them into stories. Process them with great care. Tuck them in and sing them to sleep at night.</p>
<p>All features are great. It&#8217;s the organisation of them that gives you the edge. A small set of coherent stories that each stand on their own will be far more useful than a complex network of micro abilities. A well managed, complex set of micro-abilities will be far more use than a vague idea that something might be good.</p>
<h2>Don&#8217;t go mapless</h2>
<p>It&#8217;s usually a good idea to have a high level idea of what the overall solution can look like. This lets you communicate the overall idea, discuss how things can be done and ensure that the whole idea is indeed possible. This map may include all the normal good things, asynchronous message manipulation manifolds, distributed data denegrators, partial parallel processors et al.</p>
<h2>Keep the map light</h2>
<p>Rather than follow the waterfall model of expanding this map until it&#8217;s a thousand page document, use a lightweight method to convey the idea. If that&#8217;s a block diagram on the back of an envelope scrawled in a coffee shop, or a powerpoint presentation, that&#8217;s fine, but convey the whole idea.</p>
<h2>Implement features, not the map</h2>
<p>Ignore the map. Pluck a single feature from your carefully tended garden. Build the feature as if it was the only thing that existed in the world. Don&#8217;t look to the other features to see what they need, look just at what you&#8217;re working on right now. Don&#8217;t look at the map and decide that you need the main message manipulation manifold if a simple web service will be more than sufficient for this feature. If you&#8217;re working with a single, simple document, save it in a file. Don&#8217;t add that database just because it&#8217;s on the map, follow what the feature needs.</p>
<h2>Finish the feature</h2>
<p>When a feature is complete, it looks like you knew what you were doing when you started writing it. It looks like you had the same thing in mind all the way through, and weren&#8217;t flip flopping from one way of doing things to another. Of course, you didn&#8217;t know what you were doing when you started, and you did flip flop all over the place. But don&#8217;t let that show on the finished product.</p>
<h2>Lock in the feature</h2>
<p>Have a way to automatically confirm that the feature works. Confirm this on many levels, from the outside (feature tests) to the actual code (unit tests) and inbetween (integration tests). Once a feature is locked in place, you can rest in a comfort that you know it&#8217;s not going anywhere, it&#8217;s not going to be broken and you can leave it alone and work on other things. It&#8217;s very hard to properly lock in a feature after it&#8217;s finished, so start locking it in before you start the feature. Put a lock in place for each part of the feature, then put that part in place.</p>
<p>The locks are part of your feature too, shoddy locks do a shoddy job of locking your feature in place.</p>
<h2>Check your locks</h2>
<p>Make sure you know when locks are broken. Run continuous builds on all branches of your code. Keep stats: build time, unit test code coverage, static analysis, build warnings, anything that lets you see trends in how the software is progressing. Check them.</p>
<h2>Rearrange from the ground up</h2>
<p>After you&#8217;ve added a new feature, the whole solution should look finished. As you add new features, don&#8217;t just bolt new code on top of the old, but make it look like the whole solution was written with the intention to have all the features that are available from the start. No code is sacred, no code is untouchable.</p>
<p>Lean on your locks to ensure that you&#8217;re not losing functionality or breaking a feature. Lose any locks that aren&#8217;t needed any more.</p>
<h2>Keep learning</h2>
<p>Use what works, find what doesn&#8217;t. This doesn&#8217;t need any special discipline, it&#8217;s what you&#8217;re bitching about as you&#8217;re writing your code. Your product has a lot to teach you. Learn it. Change things.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/123/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=123&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/04/07/straightening-out-the-development-cycle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>Normalised XML</title>
		<link>http://drainbrain.wordpress.com/2010/03/09/normalised-xml/</link>
		<comments>http://drainbrain.wordpress.com/2010/03/09/normalised-xml/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 09:09:13 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Xml]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=118</guid>
		<description><![CDATA[Compound data in Xml is a problem that&#8217;s been highlighted many times before by others, but it&#8217;s something that still occasionally trips developers up. Every now and then you&#8217;ll come across an Xml document that stores multiple data items in a single location. A good example is the settings* or vsprops** file for visual studio [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=118&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Compound data in Xml is a problem that&#8217;s been highlighted many times before by others, but it&#8217;s something that still occasionally trips developers up.</p>
<p>Every now and then you&#8217;ll come across an Xml document that stores multiple data items in a single location. A good example is the settings* or vsprops** file for visual studio 9, which stores C++ search paths inside a single element &#8211; go look, it&#8217;s fun***. You usually find these when you&#8217;re trying to take advantage of one of the main strengths of Xml &#8211; ie, tool support like XPath or Xslt. In general, things that mean you don&#8217;t have to write or import specialised parsing libraries to manipulate and use the data.</p>
<p>Coming across one of these compound formats when using a generic tool means that work inevitably grinds to a halt. As if XPath and Xslt aren&#8217;t hard enough, now you&#8217;re thinking of using regex, or getting the values into variables and writing some procedural code, which incidentally, doesn&#8217;t fit at all inside your xslt, so now you have to completely change your approach to the problem. A simple tool that was to being scripted from a commandline has become a real development effort.</p>
<p>And it&#8217;s not just for scripting languages, even making use of these values in normal code can be odd. There you are with your document object, just extracting and using the values in a single operation as and when you need, then all of a sudden, you&#8217;re calling &#8216;split&#8217; and iterating over the results. Of course you&#8217;re also throwing away the empty results at the end of split &#8211; because whatever formats the data for that value always puts a delimter on the end of every string. But you&#8217;re not throwing away all empty results though, are you, because an empty value in the middle of the sequence is fine, it&#8217;s just the last one that gets ignored.</p>
<p>And the Xml gets very hard to read very quickly when we&#8217;re using compound data. Do your individual values need quoting? Ok, now your document contains a load of unnecesary &amp;quot; values well. And exactly when is that ; the end of an entity, and when is it a delimiter?</p>
<p>There are many really subtle complexities like this that can come up when  you&#8217;re storing data in your own format. The more you&#8217;re stuffing into that value, the more likely you are to come across the awkward edge cases.</p>
<p>If you&#8217;re anything like me, when you&#8217;re writing this complex split logic, or trying to visually parse out the quotes from the semi-colons, you&#8217;re thinking: But formatting data like this is what Xml is for &#8211; why am I having to write this code?</p>
<p>There&#8217;s many possible causes of this stuffing. Xml does look very inefficient, a single character delimeter takes a lot less space than the bracketing of element names. But if you&#8217;re using Xml at all, is that really a concern? And if it is, would zipping the results give you similar gains? Xml compresses extremely well, and the various zips are all fairly ubiquitous tools that won&#8217;t trip up too many situations.</p>
<p>The other main reason, is of course, the one size fits all schema that doesn&#8217;t extend. But if that&#8217;s your schema, shouldn&#8217;t you be designing something thats flexible enough to at least store multiple values? Name-value pairs are great, but an Xml document that&#8217;s a glorified name value pair system is a bit weak.</p>
<p>Most people are pretty good at designing reasonably normalised databases, so why are we still stuffing so many values into a single column when it comes to Xml?</p>
<p>* In the case of the settings file, it&#8217;s not just an array, but an array of arrays. The outer array consists of the pattern: Platform1|Paths1|Platform2|Paths2. The paths themselves are stored as semi colon delimited paths: path1;path2. Good luck pulling the first search path for Win32 out of that with XPath, or even regex.</p>
<p>** VSprops is a single array of semi-colon separated paths, but often stores them quoted, for some reason. So you literally get the construct: &amp;quot;path1&amp;quot;;&amp;quot;path2&amp;quot;;.</p>
<p>*** For some definition of fun.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/118/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=118&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/03/09/normalised-xml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>Commit Comments</title>
		<link>http://drainbrain.wordpress.com/2010/02/26/commit-comments/</link>
		<comments>http://drainbrain.wordpress.com/2010/02/26/commit-comments/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 09:06:00 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[AS Dev SCM]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[SCM]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=108</guid>
		<description><![CDATA[There&#8217;s been a few blog posts recently about commit comments. James Lorenzen: http://jlorenzen.blogspot.com/2010/02/commit-comments-conversation-with-your.html A followup from Kohsuke: http://weblogs.java.net/blog/kohsuke/archive/2010/02/25/what-do-you-try-leave-your-commit-messages I know that comments can often be treated as one of those horrible tick box enforcements from on-high. However, I&#8217;ve eventually come around to a massive appreciation of them, and try to include as much detail as [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=108&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a few blog posts recently about commit comments.</p>
<p>James Lorenzen: <a href="http://jlorenzen.blogspot.com/2010/02/commit-comments-conversation-with-your.html">http://jlorenzen.blogspot.com/2010/02/commit-comments-conversation-with-your.html</a></p>
<p>A followup from Kohsuke: <a href="http://weblogs.java.net/blog/kohsuke/archive/2010/02/25/what-do-you-try-leave-your-commit-messages">http://weblogs.java.net/blog/kohsuke/archive/2010/02/25/what-do-you-try-leave-your-commit-messages</a></p>
<p>I know that comments can often be treated as one of those horrible tick box enforcements from on-high. However, I&#8217;ve eventually come around to a massive appreciation of them, and try to include as much detail as is sensible in my comments. For one thing, it confirms to me that I&#8217;ve made a specific change for a specific reason, and not just &#8216;done some stuff&#8217;.</p>
<p>Like eveyone else, I&#8217;m curious on how other people view commit comments? Are they unnecessary? (after all, we have diffs). Is just a bugId enough? Should they be short one liners or mini release notes?</p>
<p>Is there scope for bringing commit comments into other parts of the documentation, ie, on the bug reports, release notes, etc.</p>
<p>What, if any, resistance do have to writing a comment when it comes time to checkin?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/108/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=108&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/02/26/commit-comments/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
		<item>
		<title>Unit Testing Primer</title>
		<link>http://drainbrain.wordpress.com/2010/01/04/unit-testing-primer/</link>
		<comments>http://drainbrain.wordpress.com/2010/01/04/unit-testing-primer/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 11:24:46 +0000</pubDate>
		<dc:creator>rcomian</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[AS]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[TechEd]]></category>
		<category><![CDATA[UnitTest]]></category>

		<guid isPermaLink="false">http://drainbrain.wordpress.com/?p=24</guid>
		<description><![CDATA[At the TechEd conference I was able to listen to Roy Osherove give his talk on unit testing. Osherove is, as far as I can tell, one of the leading figures in unit testing and test driven development and his talks give the impression of someone who&#8217;s come to a very deep understanding of the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=24&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>At the TechEd conference I was able to listen to Roy Osherove give his talk on unit testing. Osherove is, as far as I can tell, one of the leading figures in unit testing and test driven development and his talks give the impression of someone who&#8217;s come to a very deep understanding of the subject, born through a great deal of experience and insight.</p>
<p>I&#8217;m going to try to cover the main points that Osherove gave in his talk, and the video will be available to those who wish to see it. In this post I&#8217;ll lay out the primers that are needed to understand how to write good unit tests. I don&#8217;t count myself as a unit testing guru, but I have made enough mistakes in this area to feel that I get where Osherove is coming from.</p>
<p>The first thing to understand is what a unit test is. A unit test does not rely on any environmental factor of any kind. This means no filesystem, database, network, specific user accounts or other tests. Anything that is relied on by the test is explicitly setup within the test. This also includes any functions that don&#8217;t return the same values each time they&#8217;re called &#8211; think DateTime.Now or Rand(). Any environmental dependance such as this means that the test must be classified as an integration test. Integration tests are a different kind of beast, and although still vital to the health of your software, are not the unit tests that we&#8217;re talking about here. It turns out that I&#8217;ve only ever written very few unit tests, the vast majority have been inadvertant integration tests.</p>
<p>The second thing to understand are the three pillars of unit testing: &#8220;Readability&#8221;, &#8220;Maintainability&#8221;, &#8220;Trustworthiness&#8221;. Each pillar holds up the other two pillars, you cannot have a maintainable test that isn&#8217;t readable. You cannot understand a test, you&#8217;re not likely to trust it. So if you find yourself criticizing a test based on any of these three pillars, then it&#8217;s likely that the test is not a good test and isn&#8217;t helping your software.</p>
<p>This leads on to the third fundamental point. A test suite filled with tests that aren&#8217;t good will not help us develop good software. In fact a bad test suite can be detrimental by forcing us to pay ever increasing testing taxes without them paying any dividends.</p>
<p>It turns out that there is a very clear pattern to good tests. They&#8217;re not really like normal code, so much, more like recipes. An template might be:</p>
<pre>void &lt;method under test&gt;_&lt;condition of test&gt;_&lt;result of action&gt;()
{
    &lt;initialise test items and condition&gt;

    &lt;perform tested actions&gt;

    &lt;assert on result&gt;
}
</pre>
<p>In addition to this template, there are a few other fairly unexpected guidelines:</p>
<ol>
<li>Do not use conditional logic in the test (no IF&#8217;s or SWITCHes). Each branch of the logic is a separate test condition &#8211; split out to separate tests.</li>
<li>Don&#8217;t assert in loops. Each loop is a separate test condition, split them out or recognise that they&#8217;re duplicates and remove them.</li>
<li>Assert only 1 thing per test. Multiple asserts are generally testing for different results or conditions, so they&#8217;re separate tests.</li>
<li>Give context-relevant names to the values being used. For example, calling doSplit(INVALID_LIST, UNUSED_FLAG) says more than doSplit(&#8220;here there&#8221;, false)</li>
<li>Separate out each step. Whilst you might find that you can initialise, act and assert all on one line, it doesn&#8217;t mean that it&#8217;s readable.</li>
<li>Do use standard refactoring techniques to re-use common code parts, but all the above advice still holds for these refactored methods.</li>
</ol>
<p>He also gives some suggestions for the lifecycle of tests:</p>
<ol>
<li>Add new tests when new methods, conditions or results become relevant.</li>
<li>Remove tests when they become irrelevant.</li>
<li>Only modify tests if the API changes or they need refactoring.</li>
</ol>
<p>This is a very quick distillation of the advice given. Osherove himself provides a lot more detail and justification for each point here.</p>
<p>See his site and other links at <a href="http://osherove.com/">http://osherove.com/</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/drainbrain.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/drainbrain.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/drainbrain.wordpress.com/24/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=drainbrain.wordpress.com&amp;blog=10635612&amp;post=24&amp;subd=drainbrain&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://drainbrain.wordpress.com/2010/01/04/unit-testing-primer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b2f87dffd56646d64733387543e2c729?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">rcomian</media:title>
		</media:content>
	</item>
	</channel>
</rss>
