<?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; Platforms</title>
	<atom:link href="http://davidlaing.com/category/platforms/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.2.1</generator>
		<item>
		<title>AMEE in Excel</title>
		<link>http://davidlaing.com/2012/01/29/amee-in-excel/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=amee-in-excel</link>
		<comments>http://davidlaing.com/2012/01/29/amee-in-excel/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 15:35:02 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[climate change]]></category>

		<guid isPermaLink="false">http://davidlaing.com/2012/01/29/amee-in-excel/</guid>
		<description><![CDATA[The AMEEConnect API gives access to a vast amount of climate related data. It also exposes standardise methodologies and to perform calculations based on that data. As part of the London Green Hackathon I created the AMEE-in-Excel addin to tightly integrate this data and calculations into Excel. So, if Excel is your preferred way to [...]]]></description>
			<content:encoded><![CDATA[<p>The AMEEConnect API gives access to a vast amount of climate related data.  It also exposes standardise methodologies and to perform calculations based on that data.</p>
<p>As part of the London Green Hackathon I created the AMEE-in-Excel addin to tightly integrate this data and calculations into Excel.</p>
<p><object style="height: 390px; width: 640px"><param name="movie" value="http://www.youtube.com/v/elIBxU0nfUE?version=3&#038;feature=player_detailpage"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed src="http://www.youtube.com/v/elIBxU0nfUE?version=3&#038;feature=player_detailpage" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"></object></p>
<p>So, if Excel is your preferred way to work with climate data, then this should be in your toolkit.</p>
<p>All code is open source and hosted at <a href="https://github.com/mrdavidlaing/AMEEInExcel" title="https://github.com/mrdavidlaing/AMEEInExcel"></a>.  Pull-requests are welcome!</p>
<p><strong>UPDATE</strong><br />
Hurrah!  AMEE in Excel <a href="http://london.greenhackathon.com/hacks/amee-in-excel/">won the behaviour change prize</a>:</p>
<blockquote><p>We believe over 80% of the sustainability field currently use spreadsheets. As a process, this is broken, not scalable and inaccurate. AMEE in Excel Integrates spreadsheets with web-services, to create a behaviour change that could address this issue and bring more credibility to the market.</p></blockquote>
<p>So, if you want to collaborate on some Award Winning Software <img src='http://davidlaing.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , send in those pull requests<br />
<a href="http://davidlaing.com/files/2012/01/IMG_20120201_105135.jpg"><img src="http://davidlaing.com/files/2012/01/IMG_20120201_105135-150x150.jpg" alt="" title="IMG_20120201_105135" width="150" height="150" class="alignnone size-thumbnail wp-image-313" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2012/01/29/amee-in-excel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Functional programming in Javascript and F#</title>
		<link>http://davidlaing.com/2011/06/19/functional-programming-in-javascript-and-f/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=functional-programming-in-javascript-and-f</link>
		<comments>http://davidlaing.com/2011/06/19/functional-programming-in-javascript-and-f/#comments</comments>
		<pubDate>Sun, 19 Jun 2011 09:39:00 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=295</guid>
		<description><![CDATA[During June 2011 I presented a session at the SPA2011 conference in London, UK. My session was a hands on introduction to functional programming techniques with code samples in Javascript and F#. The focus on the session was to get peopling thinking about first class functions; and the techniques they enable to simplify and increase [...]]]></description>
			<content:encoded><![CDATA[<p>During June 2011 I presented a session at the <a href="http://www.spaconference.org/spa2011/index.php?page=programme">SPA2011</a> conference in London, UK. </p>
<p>My session was a hands on introduction to functional programming techniques with code samples in Javascript and F#.  The focus on the session was to get peopling thinking about first class functions; and the techniques they enable to simplify and increase readability of code when solving certain classes of problems.</p>
<p>The code samples can be found at:</p>
<ul>
<li>Javascript &#8211; <a href="https://github.com/mrdavidlaing/functional-javascript">https://github.com/mrdavidlaing/functional-javascript</a> </li>
<li>F# &#8211;  <a href="https://github.com/mrdavidlaing/functional-fsharp">https://github.com/mrdavidlaing/functional-fsharp</a></li>
</ul>
<p>An online/executable version of the Javascript code is at <a href="http://functional-javascript.davidlaing.com">http://functional-javascript.davidlaing.com</a>.</p>
<p>Judging by the feedback I received, the session went very well.  People seemed to like the hands-on format of the session; and just being left alone for a while to learn something at their own pace.</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2011/06/19/functional-programming-in-javascript-and-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>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>Utils anti-pattern &amp; AutoMapper</title>
		<link>http://davidlaing.com/2009/06/02/utils-anti-pattern-automapper/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=utils-anti-pattern-automapper</link>
		<comments>http://davidlaing.com/2009/06/02/utils-anti-pattern-automapper/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 09:18:41 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Code smells]]></category>
		<category><![CDATA[automapper]]></category>
		<category><![CDATA[utils-anti-pattern]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=190</guid>
		<description><![CDATA[These are more for my reference purposes &#8211; hopefully you&#8217;ll find them useful: If you&#8217;re about to name a class **Util; think harder &#8211; there is a better name that discribes what that class is for: Chriss Missal has some advice for you Faced with the prospect of heaps of left hand side =&#62; right [...]]]></description>
			<content:encoded><![CDATA[<p>These are more for my reference purposes &#8211; hopefully you&#8217;ll find them useful:</p>
<p>If you&#8217;re about to name a class **Util; think harder &#8211; there is a better name that discribes what that class is for:<br />
<a href="http://www.lostechies.com/blogs/chrismissal/archive/2009/06/01/anti-patterns-and-worst-practices-utils-class.aspx">Chriss Missal has some advice for you</a></p>
<p>Faced with the prospect of heaps of left hand side =&gt; right hand side code in your DTO of anti-corruption layer?  Consider <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx">Jimmy Bogard&#8217;s Automapper</a></p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/06/02/utils-anti-pattern-automapper/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>
		<item>
		<title>Functions with side effects are just rude!</title>
		<link>http://davidlaing.com/2009/02/25/functions-with-side-effects-are-just-rude/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=functions-with-side-effects-are-just-rude</link>
		<comments>http://davidlaing.com/2009/02/25/functions-with-side-effects-are-just-rude/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 14:30:26 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Code smells]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=155</guid>
		<description><![CDATA[Today I fell into a trap when using a function that had a side effect &#8211; it unexpectedly changed an input parameter; causing a later statement to fail. Debugging took an age! For example, consider the following function: string StringReplace(string haystack, string needle) If this function is side-effect free, we can use it without fear [...]]]></description>
			<content:encoded><![CDATA[<p>Today I fell into a trap when using a function that had a side effect &#8211; it unexpectedly changed an input parameter; causing a later statement to fail.  Debugging took an age!</p>
<p>For example, consider the following function:</p>
<pre>
      string StringReplace(string haystack, string needle)
</pre>
<p>If this function is side-effect free, we can use it without fear like this:</p>
<pre>
        string menagerie = "cat,dog,bee,llama";
        string catFreeMenagerie = StringReplace(menagerie, "cat");
        string beeFreeMengerie = StringReplace(menagerie, "eric");

        Assert.AreEqual(",dog,fish,llama", catFreeMenagerie);
        Assert.AreEqual("cat,dog,,llama", beeFreeMengerie);
</pre>
<p>However, if StringReplace() had the side effect of also changing the passed in haystack, then the second Assert would fail, because the first StringReplace has the unexpected side effect of changing one of its arguments.</p>
<p>Evans in the DDD book has quite a bit to say about this; arguing that <a href="http://my.safaribooksonline.com/0321125215/ch10lev1sec2">having side effect free functions goes a long way towards making a supple design</a></p>
<p><a href="http://webmat.wordpress.com/2007/12/13/an-easy-way-to-make-your-code-more-testable/">Side effect free functions also make testing &amp; refactoring easier</a> (less state to worry about etc)</p>
<p>Remember, a function that changes its parameters is rude, and should not be trusted!</p>
<p>PS:  <a href="http://lyrics.doheth.co.uk/songs/monty-python/sings/eric-the-half-a-bee.php">Eric the half a bee lyrics</a></p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2009/02/25/functions-with-side-effects-are-just-rude/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Selenium gotcha &#8211; selenium.GetHtmlSource() returns processed HTML</title>
		<link>http://davidlaing.com/2008/12/29/selenium-gotcha-seleniumgethtmlsource-returns-processed-html/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=selenium-gotcha-seleniumgethtmlsource-returns-processed-html</link>
		<comments>http://davidlaing.com/2008/12/29/selenium-gotcha-seleniumgethtmlsource-returns-processed-html/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 18:11:01 +0000</pubDate>
		<dc:creator>mrdavidlaing</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[acceptance test]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[selenium]]></category>

		<guid isPermaLink="false">http://davidlaing.com/?p=142</guid>
		<description><![CDATA[Whilst writing some Selenium based acceptance tests today; I bumped into a hair pulling gotcha.  Hopefully this post will prevent you from the same pain. The test was to check whether some tracking tag javascript was being inserted into the page correctly or not. I assumed that I could get the page source as it [...]]]></description>
			<content:encoded><![CDATA[<p>Whilst writing some Selenium based acceptance tests today; I bumped into a hair pulling gotcha.  Hopefully this post will prevent you from the same pain.</p>
<p>The test was to check whether some tracking tag javascript was being inserted into the page correctly or not.</p>
<p>I assumed that I could get the page source as it was being delivered to the browser by calling selenium.GetHtmlSource(); and then check that for the javascript string I was expected.</p>
<p>Unfortunately, GetHtmlSource is just a proxy for the browsers DOM.InnerHTML method; and that returns the Html <strong>after</strong> it has been preprocessed by the browser.</p>
<p>Turns out that preprocessing does a couple of funky things, including</p>
<ul>
<li>Changing line-endings (Firefox)</li>
<li>Changing capitalization (IE6)</li>
<li>Seemingly random removal / insertion of &#8221; &amp; &#8216;  (IE6)</li>
</ul>
<p>So, when I was expecting a string like this:</p>
<pre>

&lt;!--
   var amPid = &#039;206&#039;&#039;;
   var amPPid = &#039;4803&#039;;
   if (document.location.protocol==&#039;https:&#039;)
...[snip]...
</pre>
<p>IE6 was presenting me with:</p>
<pre>

&lt;!--
   var amPid = &#039;206&#039;&#039;;
   var amPPid = &#039;4803&#039;;
   if (document.location.protocol==&#039;https:&#039;)
...[snip]...
</pre>
<p>A possible solution is to ignore case, whitespace and quotes when doing the comparison, with a helper method like this:</p>
<pre>
///
<summary>
        /// Use this to compare strings to those returned from selenium.GetHtmlSource for an Internet Explore instance
        /// (IE6 seems to change case and inclusion of quotes, especially for Javascript.?)
        /// </summary>

        ///
        ///
        private static void AssertStringContainsIgnoreCaseWhiteSpaceAndQuotes(string expected, string actual)
        {
            string expectedClean = Regex.Replace(expected, @"s", "").ToLower().Replace(""","").Replace("'","");
            string actualClean = Regex.Replace(actual, @"s", "").ToLower().Replace(""", "").Replace("'", "");
            StringAssert.Contains(expectedClean,actualClean,
                                  string.Format("Expected string nn{0} nnis not contained within nn{1}", expected, actual));
        }
</pre>
<p>It was the line endings that really floored me; because they were automatically normalized/corrected by my test runner when displaying the error.  Aaargh!</p>
]]></content:encoded>
			<wfw:commentRss>http://davidlaing.com/2008/12/29/selenium-gotcha-seleniumgethtmlsource-returns-processed-html/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

