<?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>Crafting software&#187; HOWTO</title>
	<atom:link href="http://davidlaing.com/category/howto/feed/" rel="self" type="application/rss+xml" />
	<link>http://davidlaing.com</link>
	<description>David Laing&#039;s thoughts on software development</description>
	<lastBuildDate>Wed, 01 Feb 2012 11:02:25 +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>Implementing the strategy pattern without an explosion of classes &#8211; part 3 of ??</title>
		<link>http://davidlaing.com/2011/04/16/implementing-the-strategy-pattern-without-an-explosion-of-classes-part-3-of/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=implementing-the-strategy-pattern-without-an-explosion-of-classes-part-3-of</link>
		<comments>http://davidlaing.com/2011/04/16/implementing-the-strategy-pattern-without-an-explosion-of-classes-part-3-of/#comments</comments>
		<pubDate>Sat, 16 Apr 2011 21:51:25 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[Code smells]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Refactoring]]></category>

		<guid isPermaLink="false">http://davidlaing.radweb.co.za/?p=272</guid>
		<description><![CDATA[I feel uncomfortable when I see large switch statements. I appreciate how they break the Open Closed Principle. I have enough experience to know that they seem to attract extra conditions &#38; additional logic during maintenance, and quickly become bug hotspots. A refactoring I use frequently to deal with this is Replace Conditional with Polymorphism; [...]]]></description>
			<content:encoded><![CDATA[<p>I feel uncomfortable when I see large switch statements.  I appreciate how they break the <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open Closed Principle</a>.  I have enough experience to know that they seem to attract extra conditions &amp; additional logic during maintenance, and quickly become bug hotspots.</p>
<p>A refactoring I use frequently to deal with this is <a href="http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html">Replace Conditional with Polymorphism</a>; but for simple switches, its always seemed like a rather large hammer.</p>
<p>Take the following simple example that performs slightly different processing logic based on the credit card type:</p>
<p><script src="https://gist.github.com/923516.js?file=CreditCard-simple-switch.js"></script> Its highly likely that the number of credit card types will increase; and that the complexity of processing logic for each will also increase over time.  The traditional application of the <a href="http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html">Replace Conditional with Polymorphism</a> refactoring gives the following:  </p>
<p><script src="https://gist.github.com/923516.js?file=CreditCard-simple-strategy.js"></script></p>
<p>This explosion of classes containing almost zero logic has always bothered me as quite a lot of boilerplate overhead for a relatively small reduction in complexity.</p>
<p>Consider however, the functional approach to the same refactoring:</p>
<p><script src="https://gist.github.com/923516.js?file=CreditCard-simple-functional.js"></script> </p>
<p>Here we have obtained the same simplification of the switch statement; but avoided the explosion of simple classes.  Whilst strictly speaking we are still violating the  <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open Closed Principle</a>; we do have a collection of simple methods that are easy to comprehend and test.  It&#8217;s worth noting that when our logic becomes very complex; converting to the OO Strategy pattern becomes a more compelling option.  Consider the case when we include a collection of validation logic for each credit card:  <script src="https://gist.github.com/923516.js?file=CreditCard-complex-functional.js"></script></p>
<p>In this case the whole file starts to feel too complex to me; and having the logic partitioned into separate strategy classes / files seems more maintainable to me.</p>
<p><script src="https://gist.github.com/923516.js?file=CreditCard-complex-strategy.js"></script></p>
<p>To conclude then, the fact that languages treat functions as first class constructs, gives us the flexibility to use them in a &#8220;polymorphic&#8221; way; where our &#8220;interface&#8221; is the function signature.  </p>
<p>And for some problems, like a refactoring a simple switch statement; I feel this gives us a more elegant solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2011/04/16/implementing-the-strategy-pattern-without-an-explosion-of-classes-part-3-of/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning functional Javascript through Koans</title>
		<link>http://davidlaing.com/2010/07/19/learning-functional-javascript-through-koans/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=learning-functional-javascript-through-koans</link>
		<comments>http://davidlaing.com/2010/07/19/learning-functional-javascript-through-koans/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 23:37:39 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Software Craftmanship]]></category>
		<category><![CDATA[koans; javascript; functional]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=236</guid>
		<description><![CDATA[Given how Javascript interpreters are improving in leaps and bounds; and that it seems to be the only language that will be supported by all web devices; its time to for me to revive my Javascript skilz. Fortunately the tooling has improved greatly; Eclipse 3.6 for Web Developers and JsTestDriver bring a refactoring and a [...]]]></description>
			<content:encoded><![CDATA[<p>Given how Javascript interpreters are improving in leaps and bounds; and that it seems to be the only language that will be supported by all web devices; its time to for me to revive my Javascript skilz.  Fortunately the tooling has improved greatly; Eclipse 3.6 for Web Developers and JsTestDriver bring a refactoring and a unit test runner to Javascript development.</p>
<p>Interestingly, Javascript seems to have more functional than object orientated characteristics; so it seems reasonable to learn it wearing my functional hat.</p>
<p>I&#8217;ve been enjoying learning Ruby syntax via <a href="http://github.com/edgecase/ruby_koans">RubyKoans &#8211; little tests that teach you syntax and convention as you make them pass</a></p>
<p>I though I&#8217;d create a similar set of <a href="https://github.com/mrdavidlaing/javascript-koans">Functional Javascript Koans</a> to help refresh my Javascript skills.</p>
<p>Its a bit rough; so please fork and contibute back improvements.<br />
<a href="https://github.com/mrdavidlaing/javascript-koans">https://github.com/mrdavidlaing/javascript-koans</a></p>
<p><object width="490" height="310"><param name="movie" value="http://www.youtube.com/v/qAoWxXPLB0Q&amp;hl=en_US&amp;fs=1?rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999&amp;border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/qAoWxXPLB0Q&amp;hl=en_US&amp;fs=1?rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="490" height="310"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2010/07/19/learning-functional-javascript-through-koans/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Why Pair Programming Doesn&#8217;t Reduce Productivity</title>
		<link>http://davidlaing.com/2010/06/06/why-pair-programming-doesnt-reduce-productivity/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=why-pair-programming-doesnt-reduce-productivity</link>
		<comments>http://davidlaing.com/2010/06/06/why-pair-programming-doesnt-reduce-productivity/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 15:15:50 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Pair Programming]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=220</guid>
		<description><![CDATA[The other day I was asked why pair programming doesn&#8217;t reduce productivity; and its taken me a few days to come up with a this succinct answer &#8211; because we&#8217;re building a system to release software changes rapidly over a long period of time, not type more lines of code to reach some predefined goal [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I was asked why pair programming doesn&#8217;t reduce productivity; and its taken me a few days to come up with a this succinct answer &#8211; </p>
<blockquote><p>because we&#8217;re building a system to release software changes rapidly over a long period of time, not type more lines of code to reach some predefined goal post
</p></blockquote>
<p>The purpose of a software team is to deliver a working software solution that solves customer&#8217;s problems over a long period of time.  </p>
<p>This would be easy if:</p>
<ol>
<li>Customers knew what they wanted</li>
<li>Developers knew how to deliver the features</li>
<li>The world remained the same on the day the software is released as it was at the time it was designed.</li>
</ol>
<p>The trouble is that none of these are true.  We have to guess at the right solution, get some real world experience with it, and then optimise when we know more about the problem domain (aka, after we have delivered the feature for the first time).</p>
<p>The way to do this better is to reduce the length of the feedback cycle (think 5 days, not 6 months), and grow a system that can rapidly and repeatedly deliver changes to the software over the life (years) of that software.</p>
<p>Pair programming contributes directly to growing this system by:</p>
<ul>
<li>Facilitating communication about the architecture &amp; design of the system, and ensuring everyone actually understands it</li>
<li>Reducing brittleness &amp; bottlenecks caused by one person &#8220;owning&#8221; a core module</li>
<li>Improving consistency and adherence to common standards</li>
<li>Catching bugs at the cheapest time to fix them</li>
</ul>
<p>Unintuatively, it also tends to ensure that developers actually spend longer working on the software by:</p>
<ul>
<li>Reducing &#8220;wander time&#8221;.  You are less likely to get sidetracked into email, facebook or some interesting blog article when pairing.</li>
<li>Reducing &#8220;stuck time&#8221;.  Two perspectives on a problem have twice as many solutions to try out</li>
</ul>
<p>These articles go into more depth:</p>
<ul>
<li><a href="http://www.menloinnovations.com/freestuff/whitepapers/pairedprogramming_qanda.htm">http://www.menloinnovations.com/freestuff/whitepapers/pairedprogramming_qanda.htm </a></li>
<li><a href="http://anarchycreek.com/2009/05/26/how-tdd-and-pairing-increase-production/">http://anarchycreek.com/2009/05/26/how-tdd-and-pairing-increase-production/</a></a></li>
</ul>
<p>To conclude, pair programming would be a unproductive if developers had the perfect solution is their head, and programming was just the task of typing that into the computer to release a single perfect version of the software.</p>
<p>But in the real world we we&#8217;re in the business of creating a system that can rapidly deliver changes to the software as it narrows in on, and adapts to the best solution to the problem at hand.  And to do this, pair programming excels.</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2010/06/06/why-pair-programming-doesnt-reduce-productivity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CI for Flex 4; running FlexUnit4 unit tests and FlexMonkey4 acceptance tests with Maven and FlexMojos</title>
		<link>http://davidlaing.com/2010/06/04/ci-for-flex-4-running-flexunit4-unit-tests-and-flexmonkey4-acceptance-tests-with-maven-and-flexmojos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ci-for-flex-4-running-flexunit4-unit-tests-and-flexmonkey4-acceptance-tests-with-maven-and-flexmojos</link>
		<comments>http://davidlaing.com/2010/06/04/ci-for-flex-4-running-flexunit4-unit-tests-and-flexmonkey4-acceptance-tests-with-maven-and-flexmojos/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 23:21:08 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[Continuous Deployment]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[HOWTO]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=216</guid>
		<description><![CDATA[The FlexMojos project is a great way to bring your Flex application under a grown up continuous build system like Maven. Getting FlexMojos 3.6.1 working with Flex 4, running Flash Builder 4&#8242;s version of unit tests and FlexMonkey4&#8242;s version of acceptance/UI tests is pretty tricky. Hopefully this sample project &#8211; http://github.com/mrdavidlaing/flexmojos-sample along with this screencast [...]]]></description>
			<content:encoded><![CDATA[<p>The FlexMojos project is a great way to bring your Flex application under a grown up continuous build system like Maven.</p>
<p>Getting FlexMojos 3.6.1 working with Flex 4, running Flash Builder 4&#8242;s version of unit tests and FlexMonkey4&#8242;s version of acceptance/UI tests is pretty tricky.</p>
<p>Hopefully this sample project &#8211; <a href="http://github.com/mrdavidlaing/flexmojos-sample">http://github.com/mrdavidlaing/flexmojos-sample</a> along with this screencast will save someone else the pain I went through to get all these playing together.</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12228897&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12228897&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>
<p><a href="http://vimeo.com/12228897">Howto add new component to FlexITP</a> from <a href="http://vimeo.com/user2901435">David Laing</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Patches welcome &#8211; just clone the git repo make your change, and request a pull.</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2010/06/04/ci-for-flex-4-running-flexunit4-unit-tests-and-flexmonkey4-acceptance-tests-with-maven-and-flexmojos/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HOWTO Reset MySQL 5.0 root password in Ubuntu 8.04 LTS</title>
		<link>http://davidlaing.com/2009/09/19/howto-reset-mysql-5-0-root-password-in-ubuntu-8-04-lts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=howto-reset-mysql-5-0-root-password-in-ubuntu-8-04-lts</link>
		<comments>http://davidlaing.com/2009/09/19/howto-reset-mysql-5-0-root-password-in-ubuntu-8-04-lts/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 15:20:08 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=194</guid>
		<description><![CDATA[Turns out there are lots of complicated ways, but in Ubuntu you can just reconfigure the package: dpkg-reconfigure mysql-server-5.0 Hopefully that will save someone some hair pulling]]></description>
			<content:encoded><![CDATA[<p>Turns out there are lots of complicated ways, but in Ubuntu you can just reconfigure the package:</p>
<p><code><br />
dpkg-reconfigure mysql-server-5.0<br />
</code></p>
<p>Hopefully that will save someone some hair pulling</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/09/19/howto-reset-mysql-5-0-root-password-in-ubuntu-8-04-lts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Pomodoro Technique &#8211; Scrum in the small</title>
		<link>http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-pomodoro-technique-scrum-in-the-small</link>
		<comments>http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/#comments</comments>
		<pubDate>Sun, 31 May 2009 09:57:41 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Software Craftmanship]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=182</guid>
		<description><![CDATA[Over the past month I&#8217;ve been experimenting with the pomodoro technique of time management to great success. The technique is surprisingly simple; yet I&#8217;ve found it contains a wealth of physical and emotional benefits. To give some context; I&#8217;m using it as a programmer as part of a agile scrum team. I typically program using [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past month I&#8217;ve been experimenting with the pomodoro technique of time management to great success.</p>
<p>The technique is surprisingly simple; yet I&#8217;ve found it contains a wealth of physical and emotional benefits.  To give some context; I&#8217;m using it as a programmer as part of a agile scrum team.  I typically program using TDD techniques.  That being said,  I don&#8217;t see why it wouldn&#8217;t be applicable in most &#8220;desk&#8221; based jobs.</p>
<p>A pomodoro is a unit of focused, uninterrupted time; measured by an egg timer.  For me, 25 minutes works well.</p>
<p>At the beginning of my work day, I write a collection of tasks that I think I achieve during the day onto a fresh piece of paper. (my todo list).  I estimate how long I think each task will take in units of a pomodoros. Next to each task I put a number of boxes; one for each pomodoro unit.  I make sure not to have more pomodoro units than I achieved yesterday; and I try to make sure that I&#8217;m estimating tasks based on how long similar tasks actually took me in the past.</p>
<p>Then I wind up my egg timer, place it visibly on my desk and begin the first task.  The ritual of winding up the timer, placing it down and hearing it tick helps me to drop into the zone of full concentration &#8211; and let my team know that they shouldn&#8217;t interrupt me.</p>
<p><em>Brrrriiinng</em>.  Pomodoro up, finish the current test and stop.  Cross out one of the boxes on my todo list.  Get up and leave my desk; stretch, drink some water, focus on something far away to relax the eyes, go and speak to anyone who came past during my pomodoro time &amp; was waived away.</p>
<p>Then back to the desk, reassess which is now the most important task to get one with, and start the next pomodoro.</p>
<p>At the end of the day I transcribe the results of my todo list back to a records sheet; update our project management software (VersionOne); and leave, satisfied that I achieved what I set out to do.</p>
<p>I&#8217;ve found that running my day like this greatly increases my job satisfaction &amp; efficiency.</p>
<p>Firstly; I&#8217;m breaking my addition to hopium, and setting myself up to fail every day.  I used to live in this lala land called &#8211; I have 8 hours of productive work time each day.  The empirical reality shows that I usually do 5 &#8211; 8 pomodoro units / day &#8211; so much more like 3 &#8211; 4 hours.  The rest gets gobbled up by meetings, emails, conversations.  So its no wonder that I used to achieved half what I thought I would each day; and left work feeling disappointed.</p>
<p>Secondly, having a forced reset every 25 mins really helps me to stop falling down rabbit holes.  I&#8217;ll often be trying to solve a problem with a specific technique that just isn&#8217;t working, and if I&#8217;m not careful I can spend a whole afternoon bashing my head against a wall.  With the forced breaks, I&#8217;ll often find that when I sit back down to the problem, I&#8217;ll have a flash of inspiration for a much simpler way to solve it, or realise that I don&#8217;t even need to solve it in the first place!</p>
<p>Thirdly, being reminded to get away from my desk frequently really helps physically.  I&#8217;ve experienced much less &#8220;mouse shoulder&#8221; and dry eyes.</p>
<p>The technique is also really helpful when pairing; keeping meetings from rambling; keeping focussed on one task (rather than having to check email or twitter every 10 seconds) and getting going on a large daunting task.</p>
<p>If you struggle with hopium like me; I&#8217;d really encourage you to give the Pomodori technique a try for 2 weeks, and let me know how you get on in the comments to this post.</p>
<p><em>Brrriiinng</em> <img src='http://davidlaing.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Resources</strong><br />
<a href="http://www.pomodorotechnique.com/">www.pomodorotechnique.com</a><br />

<a href='http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/pomodoro_records/' title='3 pomodoro_records'><img width="150" height="150" src="http://davidlaing.com/files/2009/05/pomodoro_records-150x150.png" class="attachment-thumbnail" alt="Pomodoro - Records sheet" title="3 pomodoro_records" /></a>
<a href='http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/pomodoro_todo_inventory/' title='1 pomodoro_todo_inventory'><img width="150" height="150" src="http://davidlaing.com/files/2009/05/pomodoro_todo_inventory-150x150.png" class="attachment-thumbnail" alt="Pomodoro - Todo inventory sheet" title="1 pomodoro_todo_inventory" /></a>
<a href='http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/pomodoro_todo_today/' title='2 pomodoro_todo_today'><img width="150" height="150" src="http://davidlaing.com/files/2009/05/pomodoro_todo_today-150x150.png" class="attachment-thumbnail" alt="Pomodoro - Todo today sheet" title="2 pomodoro_todo_today" /></a>
 </p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/05/31/the-pomodoro-technique-scrum-in-the-small/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Howto uninstall a broken MSI</title>
		<link>http://davidlaing.com/2009/05/27/howto-uninstall-a-broken-msi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=howto-uninstall-a-broken-msi</link>
		<comments>http://davidlaing.com/2009/05/27/howto-uninstall-a-broken-msi/#comments</comments>
		<pubDate>Wed, 27 May 2009 10:26:05 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[msi]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=179</guid>
		<description><![CDATA[I&#8217;m busy creating an MSI installer package at work; and managed to get my system into a bit of a knot. Basically, my custom action crashes on uninstall &#8211; so when I try to remove the broken MSI, it throws an error and rolls back the uninstall process. AAARGH! How do I remove the broken [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m busy creating an MSI installer package at work; and managed to get my system into a bit of a knot.</p>
<p>Basically, my custom action crashes on uninstall &#8211; so when I try to remove the broken MSI, it throws an error and rolls back the uninstall process.</p>
<p>AAARGH!  How do I remove the broken MSI now that I&#8217;ve fixed the bug?</p>
<p>Fortunately MSKB supplies this helpful little tool:</p>
<p><a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;290301">Windows Installer CleanUp Utility</a></p>
<p>Simply run, select offending MSI, and it will forceably remove any MSI registration from your system.  </p>
<p>Got me out of a pickle; and will hopefully do the same for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/05/27/howto-uninstall-a-broken-msi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symbolic links for WinXP</title>
		<link>http://davidlaing.com/2009/03/11/symbolic-links-for-winxp/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=symbolic-links-for-winxp</link>
		<comments>http://davidlaing.com/2009/03/11/symbolic-links-for-winxp/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 16:15:41 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[HOWTO]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=173</guid>
		<description><![CDATA[Hurrah &#8211; symbolic links have arrived for WinXP; via Junction. C:&#62;junction.exe c:Test c:WINDOWS Thanks for this great tip Nick]]></description>
			<content:encoded><![CDATA[<p>Hurrah &#8211; symbolic links have arrived for WinXP; via Junction.</p>
<pre>
  C:&gt;junction.exe c:Test c:WINDOWS
</pre>
<p>Thanks for <a href="http://www.sertis.net/tool-tip-junction-for-windows-xp">this great tip Nick</a></p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/03/11/symbolic-links-for-winxp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Try/Catch for SQL!?</title>
		<link>http://davidlaing.com/2009/03/05/trycatch-for-sql/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=trycatch-for-sql</link>
		<comments>http://davidlaing.com/2009/03/05/trycatch-for-sql/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 11:42:05 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[MSSQL]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=167</guid>
		<description><![CDATA[Thanks to Nick Sertis for this trick &#8211; who knew TSQL could do try/catch statements! Very useful when you need to write data manipulation scripts for production databases. BEGIN TRY BEGIN TRAN --Some SQL COMMIT TRAN END TRY -- Catch the errors on the inserts BEGIN CATCH ROLLBACK TRAN SELECT ERROR_MESSAGE() END CATCH]]></description>
			<content:encoded><![CDATA[<p>Thanks to <a href="http://www.sertis.net">Nick Sertis</a> for this trick &#8211; who knew TSQL could do try/catch statements!</p>
<p>Very useful when you need to write data manipulation scripts for production databases.</p>
<pre>
BEGIN TRY

    BEGIN TRAN

        --Some SQL

    COMMIT TRAN

END TRY
-- Catch the errors on the inserts
BEGIN CATCH

    ROLLBACK TRAN
    SELECT ERROR_MESSAGE()

END CATCH
</pre>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/03/05/trycatch-for-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

