<?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>Boost Blog &#187; Development</title>
	<atom:link href="http://www.boost.co.nz/blog/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.boost.co.nz/blog</link>
	<description>All the stuff we love - Web design &#124; Usability &#124; Ruby on Rails &#124; Agile and Scrum &#124; eLearing</description>
	<lastBuildDate>Wed, 18 Aug 2010 22:44:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Friday links: design, development, usability and more</title>
		<link>http://www.boost.co.nz/blog/random-thoughts/friday-links-1/</link>
		<comments>http://www.boost.co.nz/blog/random-thoughts/friday-links-1/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 21:20:46 +0000</pubDate>
		<dc:creator>courtney</dc:creator>
				<category><![CDATA[Cool tools]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Random thoughts]]></category>
		<category><![CDATA[Usabilty]]></category>
		<category><![CDATA[inspiration]]></category>
		<category><![CDATA[research]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=903</guid>
		<description><![CDATA[This is the first entry in a semi-regular series sharing things that we&#8217;ve been looking at and reading recently &#8230; Sarah (one of our project managers) Broadband becomes a legal right in Finland Guggenheim collaborates with YouTube and invites video submissions Sue (one of our designers, recently returned from a break in the sunny northern [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Frandom-thoughts%2Ffriday-links-1%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Frandom-thoughts%2Ffriday-links-1%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=inspiration,research" height="61" width="50" /><br />
			</a>
		</div>
<p>This is the first entry in a semi-regular series sharing things that we&#8217;ve been looking at and reading recently &#8230;</p>
<p><strong>Sarah </strong>(one of our project managers)</p>
<ul>
<li> <a href="http://www.pcworld.com/article/200261/1mbps_broadband_becomes_a_legal_right_in_finland.html?tk=nl_dnx_t_crawl">Broadband becomes a legal right in Finland</a></li>
</ul>
<ul>
<li><a href="http://www.nytimes.com/2010/06/14/arts/design/14video.html?_r=1&amp;ref=arts">Guggenheim collaborates with YouTube and invites video submissions</a></li>
</ul>
<p><strong>Sue</strong> (one of our designers, recently returned from a break in the sunny northern hemisphere)</p>
<ul>
<li>Eye-candy and inspiration on <a href="http://www.citid.net">www.citid.net</a></li>
</ul>
<ul>
<li><a href="http://webdesignledger.com/freebies/26-free-progressive-and-experimental-fonts">Great experimental fonts</a> (also: free!)</li>
</ul>
<ul>
<li> Lighten up your winter blues: heaps of colour and shapes on <a href="http://thecoolhunter.com.au/design">Coolhunter</a></li>
</ul>
<p><strong>Alastair</strong> (one of our developers)</p>
<ul>
<li><a href="http://blog.mozilla.com/blog/2010/07/06/firefox-4-beta-1-tell-us-what-you-think">Firefox 4</a> introduces more HTML 5 and CSS functionality. One step further towards the death of Flash?  Still in beta so one for the developers.</li>
</ul>
<ul>
<li>Excellent! <a href="http://maps.google.com/maps?sll=33.776665,-84.393822&amp;sspn=0.01236,0.01929&amp;ll=50.378628,-4.135151&amp;spn=0.009483,0.01929&amp;t=h&amp;z=16&amp;layer=c&amp;cbll=50.378691,-4.134783&amp;panoid=4xGPoJ72ohZ1VZnZ1PHZfA&amp;cbp=12,276.12,,3,0.83">Wayne and Garth spotted in the UK.</a> Party on!</li>
</ul>
<p><strong>Rachel</strong> (our office manager)</p>
<ul>
<li><a href="http://www.telegraph.co.uk/culture/culturevideo/artvideo/7865736/Artist-creates-masterpiece-on-an-iPad.html">Artist creates masterpiece on an iPad</a></li>
</ul>
<ul>
<li><a href="http://www.guardian.co.uk/news/datablog/2010/jul/06/world-cup-2010-statistics">World Cup 2010 statistics</a>: all the key data for each team, from the <em>Guardian</em></li>
</ul>
<p>(Rachel notes that she&#8217;s not as much of a sports fiend as the above link might suggest, and also recommends data/infographic blog <a href="http://www.coolinfographics.com">Cool Infographics</a>)</p>
<p><strong>Jake</strong> (who looks after our usability testing tool <a href="http://www.intuitionhq.com/">IntuitionHQ</a>)</p>
<ul>
<li>David Gillis on <a href="http://uxmag.com/design/fusing-content-strategy-with-design">Fusing Content Strategy with Design</a>, in <em>UX Magazine</em></li>
</ul>
<ul>
<li><a href="http://www.slideshare.net/padday/the-real-life-social-network-v2">The Real Life Social Network</a>, slides from a presentation by Paul Adams, Senior User Experience Researcher at Google</li>
</ul>
<ul>
<li><a href="http://www.youtube.com/watch?v=tVljiwwqwfc&amp;feature=youtu.be">Gnarcade</a> &#8211; Video Game Invasion: for video game fans, and geeks in general</li>
</ul>
<p><strong>Courtney</strong> (that&#8217;s me &#8211; project manager)</p>
<ul>
<li>Aaron Straup Cope&#8217;s <a href="http://shapetiles.spum.org">magical slippy map</a> showing the world as revealed by geo-tagged photos on Flickr</li>
</ul>
<ul>
<li><a href="http://significantobjects.com/about/">Significant Objects</a>, an investigation of art and the market through short stories and eBay</li>
</ul>
<ul>
<li><a href="http://roberthealdgallery.com/">Swallows and Amazons</a>, the current exhibition at Robert Heald Gallery, which is close to our office &#8211; on show until 31 July.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/random-thoughts/friday-links-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working with Git</title>
		<link>http://www.boost.co.nz/blog/random-thoughts/working-with-git/</link>
		<comments>http://www.boost.co.nz/blog/random-thoughts/working-with-git/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 04:14:51 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Random thoughts]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=810</guid>
		<description><![CDATA[During a brief slow period on a Friday afternoon I started pondering how much work I actually do, and if it was even useful knowing. Obviously all our code is stored in a version control system (git), so in a way all of the data for finding out the quantity of work is readily available. [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Frandom-thoughts%2Fworking-with-git%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Frandom-thoughts%2Fworking-with-git%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=git,ruby" height="61" width="50" /><br />
			</a>
		</div>
<p>During a brief slow period on a Friday afternoon I started pondering how much work I actually do, and if it was even useful knowing. Obviously all our code is stored in a version control system (git), so in a way all of the data for finding out the quantity of work is readily available. A little investigation and I found that it&#8217;s quite easy to pull a list of commits from git showing total lines added and deleted per file:</p>
<p><code>git log --oneline --numstat</code></p>
<p>I&#8217;ve committed a lot of code that I didn&#8217;t write, such as plugins, the Rails framework etc. So a quick and dirty ruby script later I could get a list of all unique files in all repositories that I&#8217;ve committed to. It was pretty easy to go through the list and create an exclusion list. I then broke out <a href="http://rubyreports.org/">Ruport</a> to aggregate everything by extension. That gave me the following table:</p>
<p><img class="size-full wp-image-859 aligncenter" style="margin: 0px auto;" title="lines" src="http://www.boost.co.nz/blog/wp-content/uploads/2010/07/Screen-shot-2010-07-02-at-10.00.01-PM.png" alt="" width="407" height="283" /></p>
<p>I&#8217;ve cleaned this up a little and collapsed some alternative extensions down.</p>
<div id="attachment_850" class="wp-caption alignright" style="width: 128px"><img class="size-full wp-image-850 " title="bar" src="http://www.boost.co.nz/blog/wp-content/uploads/2010/07/bar.png" alt="" width="118" height="336" /><p class="wp-caption-text">Commits per week</p></div>
<p>Just over 110,000 lines added and 50,000 deleted, of which about 100,000 are to Ruby files. Now I&#8217;m not claiming to have written all those lines myself, any part of any line changed counts towards the total. All this does is illustrate the general balance of work that I do. There have been two lines added for every line deleted. This year has seen a lot of refactoring work, so it&#8217;ll be interesting to run the same exercise next year and see if the results are similar (of course git holds historical data, but we only started using it about 18 months ago, and previously had everything stored in subversion).</p>
<p>It&#8217;s interesting to see that the proportion of additons to deletions is much higher in view (rhtml/haml) files than in ruby code. This could point to the way things look being changed much more than the way things work.</p>
<p>Now if only there was a way to measure the quality of work. (Actually there are tools; <a href="http://metric-fu.rubyforge.org/">metric_fu</a> is a good starting point and we use it a lot at Boost. However, that&#8217;s going a little too far for this post).</p>
<p>Another interesting bit of data I extracted from git is the number of commits I&#8217;ve done per week over the last 52 weeks.</p>
<p>I&#8217;ve posted my script as a <a href="http://gist.github.com/461157">github gist</a>. You  can run it by modifying the @repositories array with a list of git repositories, @author with your email address and @excludes with a list of regular expressions for excluding files. Run the script as ruby gitcount.rb. If it is run with the argument &#8220;files&#8221; then it will list individual files, making it easier to build the exclude list.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/random-thoughts/working-with-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DrupalSouth Presentation</title>
		<link>http://www.boost.co.nz/blog/development/drupalsouth-presentation/</link>
		<comments>http://www.boost.co.nz/blog/development/drupalsouth-presentation/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 02:34:28 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=629</guid>
		<description><![CDATA[DrupalSouth, an annual gathering of Drupal people from around New Zealand, happened over the long weekend here in Wellington. The venue was Mac&#8217;s Brewery; a great location on the Wellington waterfront, a good venue for a conference of this size and of course geeks love good beer, it&#8217;s a fact. Alastair (a fellow Boost developer) and [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fdrupalsouth-presentation%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fdrupalsouth-presentation%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><a title="DrupalSouth" href="http://wellington2010.drupalsouth.net.nz" target="_blank">DrupalSouth</a>, an annual gathering of Drupal people from around New Zealand, happened over the long weekend here in Wellington.</p>
<p>The venue was Mac&#8217;s Brewery; a great location on the Wellington waterfront, a good venue for a conference of this size and of course geeks love good beer, it&#8217;s a fact.</p>
<p>Alastair (a fellow Boost developer) and I presented a talk on beginning Drupal module development at one of two Sunday morning red-eye sessions. Our presentation focused on getting people started with Drupal module development. The intention was to give simple examples of how you can tap into Drupal hooks and other elements of the API, such as the Form API.</p>
<p>Pitching a technical talk to beginners is always difficult depending on the background of the audience, hopefully it&#8217;s simple enough to understand while giving enough information for those who are raring to go.</p>
<p>The presentation slides and our sample code are available to download.</p>
<ul>
<li><a href="http://www.boost.co.nz/blog/ModuleDevelopment.pdf">Presentation slides</a></li>
<li><a href="http://www.boost.co.nz/blog/ModuleDevelopment.zip">Sample code</a></li>
</ul>
<p>Any feedback will be appreciated, please feel free to comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/drupalsouth-presentation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Scrum and Kanban – a developer&#8217;s perspective</title>
		<link>http://www.boost.co.nz/blog/development/scrum-and-kanban-a-developers-perspective/</link>
		<comments>http://www.boost.co.nz/blog/development/scrum-and-kanban-a-developers-perspective/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 02:37:49 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=602</guid>
		<description><![CDATA[We&#8217;ve been using Kanban for a few weeks now on some projects, taking over from Scrum where appropriate. We&#8217;ve used the Kanban process for projects in ongoing maintenance and for those that seem more like a list of tasks to be performed (Drupal CMS integration). Pros Forces workflow. Easier to see each task&#8217;s status &#8211; [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fscrum-and-kanban-a-developers-perspective%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fscrum-and-kanban-a-developers-perspective%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>We&#8217;ve been using <a href="http://www.boost.co.nz/blog/development/scrum-and-kanban-less-is-more/">Kanban</a> for a few weeks now on some projects, taking over from Scrum where appropriate. We&#8217;ve used the Kanban process for projects in ongoing maintenance and for those that seem more like a list of tasks to be performed (Drupal CMS integration).<span id="more-602"></span></p>
<p><strong>Pros</strong></p>
<ul>
<li>Forces workflow.</li>
<li>Easier to see each task&#8217;s status &#8211; it has a place in the workflow instead of being not started / working / complete as with scrum.</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>Less satisfaction &#8211; you don&#8217;t see the burndown or how much work you&#8217;ve personally completed.</li>
<li>Kanban is more about a flow of tasks, and one premise is that the number of tasks in each stage of the workflow is restricted. This can be difficult when there are tasks that must be dealt with by different team members &#8211; for example design tasks verses programming tasks. A design task may take up a slot in the workflow for a long period of time.</li>
<li>Kanban can&#8217;t express dependent tasks. This sometimes causes tasks to move back and forth along the workflow to free spots for the tasks they depend upon. Scrum has a less confusing way of showing what&#8217;s happening.</li>
<li>Harder to see overall project status. This is a problem when working with Kanban for the whole project, but not for projects in maintenance mode.</li>
</ul>
<p>Some of these cons are things that we need to work around by improving our own processes. Ideally all the tasks can be dealt with by all team members (but this is impracticable for expressing our design tasks). We also need to work towards each task being a self contained unit of work with no dependencies.</p>
<p>I think with Kanban we&#8217;re still finding our feet. The <a href="http://agilezen.com/" target="_blank">tools</a> aren&#8217;t yet as mature and easy to use as the <a href="http://acunote.com" target="_blank">scrum tools</a> we use. Our task descriptions and workflows are still evolving. It seems to me that the Kanban structure requires more ongoing maintenance from the project manager than scrum where the structure is set at the beginning of each sprint. As we&#8217;re still only experimenting with Kanban we haven&#8217;t found a good balance and tasks tend to pile in the completed stack for too long before being verified.</p>
<p>My overall feeling is that scrum is a more satisfying process to develop under &#8211; you get better and more immediate feedback. Kanban is helpful in preventing work being done when the scrum process isn&#8217;t in place &#8211; a situation that is very tempting when bugs start appearing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/scrum-and-kanban-a-developers-perspective/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Drupal linked themes</title>
		<link>http://www.boost.co.nz/blog/development/drupal-linked-themes/</link>
		<comments>http://www.boost.co.nz/blog/development/drupal-linked-themes/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 01:52:18 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=611</guid>
		<description><![CDATA[We&#8217;ve released our first public Drupal module &#8211; linkedtheme. This modules gives you the ability to link themes together so that they share their block configuration, great for subthemes. You might use this Drupal module for a site where one section has a significantly different look to another, but the header or menu section has [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fdrupal-linked-themes%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fdrupal-linked-themes%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=Drupal" height="61" width="50" /><br />
			</a>
		</div>
<p>We&#8217;ve released our first public Drupal module &#8211; <a href="http://drupal.org/project/linkedtheme">linkedtheme</a>. This modules gives you the ability to link themes together so that they share their block configuration, great for subthemes.<span id="more-611"></span></p>
<p>You might use this Drupal module for a site where one section has a significantly different look to another, but the header or menu section has the same look and you want to display the same blocks.</p>
<div id="attachment_624" class="wp-caption alignnone" style="width: 470px"><img class="size-full wp-image-624" title="linkedtheme copy" src="http://www.boost.co.nz/blog/wp-content/uploads/2010/01/linkedtheme-copy.png" alt="" width="460" height="297" /><p class="wp-caption-text">Linked themes</p></div>
<p>This Drupal module would also be useful if you had user selectable themes. As the user changed the theme they used they would see the same blocks on the site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/drupal-linked-themes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scrum and Kanban &#8211; less is more</title>
		<link>http://www.boost.co.nz/blog/development/scrum-and-kanban-less-is-more/</link>
		<comments>http://www.boost.co.nz/blog/development/scrum-and-kanban-less-is-more/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 00:01:29 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=578</guid>
		<description><![CDATA[Here at Boost we are always endeavouring to improve our processes and ultimately our outputs. The &#8216;cycle of continuous improvement&#8217;, if you will. This means we actively looking for new ideas to test and where appropriate integrate into our day. Recently we have been researching the agile process Kanban and how it might integrate with [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fscrum-and-kanban-less-is-more%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fscrum-and-kanban-less-is-more%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=Development" height="61" width="50" /><br />
			</a>
		</div>
<p>Here at <a href="http://www.boost.co.nz">Boost</a> we are always endeavouring to improve our processes and ultimately our outputs. The &#8216;cycle of continuous improvement&#8217;, if you will. This means we actively looking for new ideas to test and where appropriate integrate into our day.</p>
<p>Recently we have been researching the agile process Kanban and how it might integrate with our Scrum processes. Kanban is a less prescriptive agile methodology than Scrum. It concentrates on moving items through the pipeline from formulation to completion. It shares many ideas with Scrum and often Kanban teams adopt Scrum artifacts such as daily standups.</p>
<p><strong>What is Kanban</strong></p>
<p><strong><span style="font-weight: normal;">Kanban is an agile methodology that shares much in common with Scrum, but it also has a number of key differences. For example, where scrum uses sprints to limit work in progress, Kanban limits work in progress by workflow state. </span></strong></p>
<p><strong><span style="font-weight: normal;"><span id="more-578"></span>For a given project, a number of states are decided on, for instance backlog, develop, test and deploy. Each of these states can have a limit to the number of items that can be in that state at any given time. In this example, the develop state may have a limit of three while the test state may have a limit of two. Nothing can be moved from one state to the next if that limit has been reached. Some states may not have a limit &#8211; the backlog, for instance. </span></strong></p>
<p>Work flows from backlog -&gt; develop -&gt; test -&gt; deploy. We can measure how long it takes a task to move through the pipeline from beginning development to being deployed. This is called lead (or cycle) time and is Kanban&#8217;s key metric.</p>
<div id="attachment_582" class="wp-caption alignnone" style="width: 160px"><a rel="lightbox-page" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban1.JPG.jpeg"><img class="size-thumbnail wp-image-582" title="One day in Kanban land. Thanks to Henrik Kniberg" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban1.JPG-150x150.jpg" alt="One day in Kanban land. Thanks to Henrik Kniberg" width="150" height="150" /></a><p class="wp-caption-text">One day in Kanban land. How a Kanban project might proceed. Thanks to Henrik Kniberg</p></div>
<div style="display: none;">
<div id="attachment_583" class="wp-caption alignnone" style="width: 160px"><a rel="lightbox-page" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban2.JPG.jpeg"><img class="size-thumbnail wp-image-583" title="One day in Kanban land. Thanks to Henrik Kniberg" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban2.JPG-150x150.jpg" alt="One day in Kanban land. Thanks to Henrik Kniberg" width="150" height="150" /></a><p class="wp-caption-text">One day in Kanban land. Thanks to Henrik Kniberg</p></div>
<div id="attachment_584" class="wp-caption alignnone" style="width: 160px"><a rel="lightbox-page" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban3.JPG.jpeg"><img class="size-thumbnail wp-image-584" title="One day in Kanban land. Thanks to Henrik Kniberg" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban3.JPG-150x150.jpg" alt="One day in Kanban land. Thanks to Henrik Kniberg" width="150" height="150" /></a><p class="wp-caption-text">One day in Kanban land. Thanks to Henrik Kniberg</p></div>
<div id="attachment_585" class="wp-caption alignnone" style="width: 160px"><a rel="lightbox-page" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban4.JPG1.jpeg"><img class="size-thumbnail wp-image-585" title="One day in Kanban land. Thanks to Henrik Kniberg" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/12/Kanban4.JPG1-150x150.jpg" alt="One day in Kanban land. Thanks to Henrik Kniberg" width="150" height="150" /></a><p class="wp-caption-text">One day in Kanban land. Thanks to Henrik Kniberg</p></div>
</div>
<p><strong>Where could Kanban be of benefit over Scrum</strong></p>
<p>For Boost there are a couple of situations where I can see an immediate improvement with Kanban.</p>
<p>One situation is when a web application or product is in a maintenance phase. During this time we need to address defects and issues as they arise, as well as implementing new, usually smaller, features. We find that a fixed length sprint can limit our responsiveness to defects as we are reluctant to alter a sprint that is in progress. Kanban would enable us to prioritise issues while still addressing the planned smaller features.</p>
<p>The other situation where we see Kanban working well is when developing content managed websites. In this case it is often difficult to break the work into two week sprints. It often feels as though the work is more of a constant stream of very small features that come together to make the site. Often at the end of the sprint we often don&#8217;t have a product increment to demo or deploy, especially in the early stages. Kanban would enable us to deploy and demo when ready rather than on a rigid schedule. Deployments would become more frequent as the project progressed.</p>
<p>I won&#8217;t go into too much more detail here. There is an excellent forty page PDF entitled <a href="http://www.crisp.se/henrik.kniberg/Kanban-vs-Scrum.pdf" target="_blank">Kanban vs Scrum </a>written by Henrik Kniberg (<a href="http://www.crisp.se/henrik.kniberg" target="_blank">http://www.crisp.se/henrik.kniberg</a>) that goes into some detail about what Kanban is and how it can work with Scrum.</p>
<p>Would love to hear about your experiences of Kanban!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/scrum-and-kanban-less-is-more/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How the west was clustered</title>
		<link>http://www.boost.co.nz/blog/development/how-the-west-was-clustered/</link>
		<comments>http://www.boost.co.nz/blog/development/how-the-west-was-clustered/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 00:30:06 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=520</guid>
		<description><![CDATA[Our new product, IntuitionHQ, shows clusters of clicks on an image. To generate these clusters we made use of a gem called Hierclust. The great thing about this gem is it&#8217;s simplicity &#8211; just input the points and a minimum cluster separation, and out come the clusters. The problem with Hierclust was the performance. With [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fhow-the-west-was-clustered%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fhow-the-west-was-clustered%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=rails,ruby" height="61" width="50" /><br />
			</a>
		</div>
<div id="attachment_521" class="wp-caption alignright" style="width: 239px"><a href="http://www.boost.co.nz/blog/wp-content/uploads/2009/10/Screen-shot-2009-10-27-at-9.20.25-AM.png"><img class="size-full wp-image-521   " title="Screen shot 2009-10-27 at 9.20.25 AM" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/10/Screen-shot-2009-10-27-at-9.20.25-AM.png" alt="Screen shot 2009-10-27 at 9.20.25 AM" width="229" height="175" /></a><p class="wp-caption-text">A cluster on IntuitionHQ</p></div>
<p>Our new product, <a href="http://www.intuitionhq.com">IntuitionHQ</a>, shows clusters of clicks on an image. To generate these clusters we made use of a gem called <a href="http://hierclust.rubyforge.org/">Hierclust</a>. The great thing about this gem is it&#8217;s simplicity &#8211; just input the points and a minimum cluster separation, and out come the clusters.</p>
<p>The problem with Hierclust was the performance. With fewer than 100 points to cluster Hierclust was running too slow to do it dynamically. This was no problem, we moved the clustering program into a cronjob and stored the data in a marshalled file.</p>
<p>However, in testing we found that Hierclust was still too slow. Once we had over 200 points being clustered it started taking minutes to process &#8211; an unsustainable amount of time for the data we expected. The graph below shows the timings, which I believe is O(n<sup>3</sup>). We had to disable cluster processing while looking at the problem due to issues it was causing on the server.</p>
<div id="attachment_528" class="wp-caption aligncenter" style="width: 466px"><img class="size-full wp-image-528 " title="Screen shot 2009-10-27 at 10.14.36 AM" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/10/Screen-shot-2009-10-27-at-10.14.36-AM1.png" alt="Screen shot 2009-10-27 at 10.14.36 AM" width="456" height="313" /><p class="wp-caption-text">Graph of points v time taken</p></div>
<p><span id="more-520"></span></p>
<h2>ai4r</h2>
<p>The first course of action was to look for an alternative way to do the clustering. Looking at several solutions, the most promising looked to be the gem <a href="http://ai4r.rubyforge.org/">ai4r</a>. This provided a number of different clustering algorithms, and was faster / more scalable. Unfortunately the clustering algorithms needed to know the number of clusters &#8211; information that we didn&#8217;t want to estimate.</p>
<h2>Documentation</h2>
<p>It&#8217;s important to always read the documentation of gems you&#8217;re using. After going back to Hierclust and looking through the code I found a value I could tweak to improve the performance at the cost of accuracy. This bought us some time by reducing the processing time of our current data from minutes to 10-20 seconds. It wasn&#8217;t going to scale, but we could re-enable the cronjob.</p>
<h2>ruby-prof</h2>
<p>We then decided that if we could improve the performance of the Hierclust gem itself we didn&#8217;t need to worry that it was taking so much longer for each point, as there would be a natural limit to the number of points viable for a project. Using Benchmark and <a href="http://ruby-prof.rubyforge.org/">ruby-prof</a> I started to go through the gem with a fine tooth comb. I had test data with 250 points, taking 11 seconds to run. You can take a look at my test file here: <a href="http://gist.github.com/219094">http://gist.github.com/219094</a>.</p>
<p>Profiling the code showed that it was spending a lot of time flattening arrays. Looking at every place where flatten was called I found that where each cluster contained an array of points, each of which could be a cluster, flatten was called. By simply changing the code to store the flattened array in an instance variable (invalidating when required) the time to run the test data went from 11 seconds to 3 seconds, a nearly 4 times improvement.</p>
<pre> %self     total     self     wait    child    calls  name
 15.31      9.02     9.02     0.00     0.00  <strong>4404288  Hierclust::Point#points</strong>
 12.41     35.59     7.31     0.00    28.27   920825  Array#map-1
 12.31     30.76     7.26     0.00    23.50  1060120  Array#map
 12.16      7.17     7.17     0.00     0.00  <strong>1980941  Array#flatten</strong>
  6.94     26.08     4.09     0.00    21.99   530058  Hierclust::Cluster#x
  6.77     38.33     3.99     0.00    34.34  <strong>1060116  Hierclust::Cluster#points</strong>
  6.74     25.28     3.97     0.00    21.30   530058  Hierclust::Cluster#y
  6.31     56.69     3.72     0.00    52.97   265029  Hierclust::Point#distance_to</pre>
<h2>Table lookup</h2>
<p>A 4 times improvement was good, but we needed something closer to a 10 times improvement. I couldn&#8217;t find anywhere else in the code to improve the performance. However, we did note that quite a lot of time was spent calculating the distance between points (a Pythagoras calculation). Lookup tables are faster, we thought, so why not pre-generate possible values and load them from disk. This was quickly discounted when some quick maths showed us it would require gigabytes of space; probably not faster then.</p>
<h2>RubyInline</h2>
<p>The next step was to look at throwing some C code into the gem to improve the performance. I tried recoding various methods using <a href="http://www.zenspider.com/ZSS/Products/RubyInline/">RubyInline</a>, a brilliant gem that makes it easy to add small snippets of C code to ruby. For example, the following ruby code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> distance_to<span style="color:#006600; font-weight:bold;">&#40;</span>other<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC00FF; font-weight:bold;">Math</span>.<span style="color:#9900CC;">sqrt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span>other.<span style="color:#9900CC;">x</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">x</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">**</span> <span style="color:#006666;">2</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006600; font-weight:bold;">&#40;</span>other.<span style="color:#9900CC;">y</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">y</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">**</span> <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Can be rewritten in the same file in C:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">inline <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>builder<span style="color:#006600; font-weight:bold;">|</span>
  builder.<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#996600;">'
'</span>
  builder.<span style="color:#9900CC;">c</span> <span style="color:#996600;">&quot;
    double pyth(double x1, double y1, double x2, double y2) {
      double rr = pow((long)x2 - (long)x1, 2) + pow((long)y2 - (long)y1, 2);
      return sqrt(rr);
  }&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Unfortunately the speed benefits were very small, 3 seconds to 2.5 seconds, or 4.5 times faster than the original 11 seconds. You can see my efforts at patching Hierclust here: <a href="http://github.com/jemmyw/hierclust">http://github.com/jemmyw/hierclust</a>.</p>
<h2>C Extension</h2>
<p>I reasoned from the data I got from ruby-prof that the main bottleneck in the gem, apart from the distance calculation, was in doing array operations. Using RubyInline wasn&#8217;t going to solve that. So, using my rusty knowledge of C and <a href="http://java.ociweb.com/mark/NFJS/RubyCExtensions.pdf">this PDF</a> I set about rewriting the Hierclust algorithm in C. As we didn&#8217;t require hierarchical clustering I dropped that part of the algorithm and just stored the cluster information with coordinates and cluster size. I used the previous test data of 250 points during development to ensure that the output from the C extension was exactly the same as the output from Hierclust, and once complete I ported Hierclust&#8217;s spec files to the new gem.</p>
<p>The results were well worth the effort. The same set of 250 points that took 11 seconds with Hierclust and 3 seconds after my modifications, took ~0.009 seconds using the new C based gem, 1000 times faster. The test file required only changing three lines (class names and requires).</p>
<p>The fastcluster gem can be downloaded:</p>
<pre>gem install fastcluster</pre>
<p>Or you can get the source code from <a href="http://github.com/jemmyw/fastcluster">http://github.com/jemmyw/fastcluster</a>.</p>
<p>Test files for Hierclust and fastcluster: <a href="http://gist.github.com/219094">http://gist.github.com/219094</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/how-the-west-was-clustered/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What should break the test?</title>
		<link>http://www.boost.co.nz/blog/development/what-should-break-the-test/</link>
		<comments>http://www.boost.co.nz/blog/development/what-should-break-the-test/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 21:31:14 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=474</guid>
		<description><![CDATA[I recently came across FakeFS, which sounds like a great idea for helping to test file functions. However, I did pick up on the following off the website: [...] it means replacing our mkdir call with a call to mkdir_p won’t break our tests. Because, really, it shouldn’t. Now I understand that in the context [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fwhat-should-break-the-test%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fwhat-should-break-the-test%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=ruby,tdd" height="61" width="50" /><br />
			</a>
		</div>
<p>I recently came across <a href="http://ozmm.org/posts/fakefs.html">FakeFS</a>, which sounds like a great idea for helping to test file functions. However, I did pick up on the following off the website:</p>
<blockquote><p>[...] it means replacing our mkdir call with a call to mkdir_p won’t break our tests. Because, really, it shouldn’t.</p></blockquote>
<p>Now I understand that in the context of the example given, mkdir and mkdir_p should do the same thing. But <strong>mkdir</strong> and <strong>mkdir_p</strong> do perform different operations, and the tests <em>should</em> break if mkdir_p is changed to mkdir. If you change mkdir_p to mkdir and your passing tests don&#8217;t fail then your tests aren&#8217;t correct.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/what-should-break-the-test/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Squirrel and the custom nut matcher</title>
		<link>http://www.boost.co.nz/blog/ruby-on-rails/squirrel-and-the-custom-nut-matcher/</link>
		<comments>http://www.boost.co.nz/blog/ruby-on-rails/squirrel-and-the-custom-nut-matcher/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 04:01:05 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=451</guid>
		<description><![CDATA[I recently found squirrel, and I wanted to use it for a project we&#8217;re working on to simplify some complex finder statements. Squirrel allows turning something like this: Task.find&#40;:all, :conditions =&#38;gt; &#91; 'active = ? and (updated_at &#38;gt; cache_version or cache_version IS NULL)', true &#93; &#41; into: Task.find&#40;:all&#41; do active == true any do updated_at [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fsquirrel-and-the-custom-nut-matcher%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fsquirrel-and-the-custom-nut-matcher%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=rails,rspec,ruby,tdd" height="61" width="50" /><br />
			</a>
		</div>
<p>I recently found <a href="http://www.thoughtbot.com/projects/squirrel">squirrel</a>, and I wanted to use it for a project we&#8217;re working on to simplify some complex finder statements. Squirrel allows turning something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Task.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>,
  <span style="color:#ff3333; font-weight:bold;">:conditions</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span>
    <span style="color:#996600;">'active = ? and (updated_at &amp;gt; cache_version or cache_version IS NULL)'</span>, <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>into:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Task.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  active == <span style="color:#0000FF; font-weight:bold;">true</span>
  any <span style="color:#9966CC; font-weight:bold;">do</span>
    updated_at <span style="color:#006600; font-weight:bold;">&amp;</span>gt; cache_version
    cache_version.<span style="color:#0000FF; font-weight:bold;">nil</span>?
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>The problem is testing</h3>
<p>Then I ran into a serious problem &#8211; how to test this piece of code using rspec? Here was my first attempt:<span id="more-451"></span></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">'should find all active tasks where updated_at is greater than cache_version or cache_version is null'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:find</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>@tasks<span style="color:#006600; font-weight:bold;">&#41;</span>
  Task.<span style="color:#9900CC;">update_cache</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This doesn&#8217;t test the search conditions at all. So I moved on to yield:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:find</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_yield</span>
 received unexpected message <span style="color:#996600;">&quot;active&quot;</span></pre></div></div>

<p>Then I started adding in the expectations:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:active</span><span style="color:#006600; font-weight:bold;">&#41;</span>
Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:find</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_yield</span></pre></div></div>

<p>But how do I know that active is being compared to true? Now I&#8217;d have to use a mock to do that:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">mock_active = mock<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:active</span><span style="color:#006600; font-weight:bold;">&#41;</span>
mock_active.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span>:==<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:active</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>mock_active<span style="color:#006600; font-weight:bold;">&#41;</span>
Task.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:find</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_yield</span></pre></div></div>

<p>As you can see, this is getting quite painful. So it was time to abstract this out into something more meaningful. I created a class called FindWithSquirrel:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Spec::Matchers</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>klass, expected<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@klass</span> = klass
    <span style="color:#0066ff; font-weight:bold;">@expected</span> = expected
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> verify
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And I added a way to gain access to the class:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#9966CC; font-weight:bold;">Class</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> should_receive_squirrel_find_with<span style="color:#006600; font-weight:bold;">&#40;</span>expected<span style="color:#006600; font-weight:bold;">&#41;</span>
    FindWithSquirrel.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>, expected<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now the new class needs to extend ActiveRecord to override find and record what happens:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>klass, expected<span style="color:#006600; font-weight:bold;">&#41;</span>
    ...
    <span style="color:#9900CC;">extend</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> extend
    <span style="color:#0066ff; font-weight:bold;">@klass</span>.<span style="color:#9900CC;">class_eval</span> <span style="color:#006600; font-weight:bold;">%</span>Q<span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">find_with_finds</span>
        <span style="color:#0066ff; font-weight:bold;">@find_with_finds</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">find_with_find_with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>amp;blk<span style="color:#006600; font-weight:bold;">&#41;</span>
        find_with_finds <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; find_without_find_with<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:query</span>, <span style="color:#006600; font-weight:bold;">&amp;</span>amp;blk<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_find_conditions</span>
        find_without_find_with<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>amp;blk<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#0000FF; font-weight:bold;">self</span>
        alias_method <span style="color:#ff3333; font-weight:bold;">:find_without_find_with</span>, <span style="color:#ff3333; font-weight:bold;">:find</span>
        alias_method <span style="color:#ff3333; font-weight:bold;">:find</span>, <span style="color:#ff3333; font-weight:bold;">:find_with_find_with</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So now I&#8217;ve got a variable on the model class holding an array of generated conditions. I can fill in the verify method:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  <span style="color:#9966CC; font-weight:bold;">def</span> finds
    <span style="color:#0066ff; font-weight:bold;">@klass</span>.<span style="color:#9900CC;">find_with_finds</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> verify
    finds.<span style="color:#9900CC;">should</span> <span style="color:#9966CC; font-weight:bold;">include</span><span style="color:#006600; font-weight:bold;">&#40;</span>@expected<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>That&#8217;s all fine, but now I need to make rspec actually call my verify method. I can do that by reusing the way rspec mocks work. I can do that by adding my class instances to the same array that rspec adds it&#8217;s mock expectations:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>klass, expected<span style="color:#006600; font-weight:bold;">&#41;</span>
    ...
    <span style="color:#ff6633; font-weight:bold;">$rspec_mocks</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#ff6633; font-weight:bold;">$rspec_mocks</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now the rspec mock framework is expecting to call the methods &#8216;rspec_verify&#8217; and &#8216;rspec_reset&#8217;, so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  alias_method <span style="color:#ff3333; font-weight:bold;">:rspec_verify</span> <span style="color:#ff3333; font-weight:bold;">:verify</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> rspec_reset
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now I can run this spec, and it works great. But it seems to break all the subsequent specs that also use the find function. I have to flesh out that reset function a little. Remember my earlier <em>extend</em> function &#8211; I need to remove my ActiveRecord extensions:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FindWithSquirrel
  <span style="color:#9966CC; font-weight:bold;">def</span> unextend
    <span style="color:#0066ff; font-weight:bold;">@klass</span>.<span style="color:#9900CC;">class_eval</span> <span style="color:#006600; font-weight:bold;">%</span>Q<span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#0000FF; font-weight:bold;">self</span>
        alias_method <span style="color:#ff3333; font-weight:bold;">:find</span>, <span style="color:#ff3333; font-weight:bold;">:find_without_find_with</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  alias_method <span style="color:#ff3333; font-weight:bold;">:rspec_reset</span>, <span style="color:#ff3333; font-weight:bold;">:unextend</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So what does my spec look like?</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">'should find all active tasks where updated_at is greater than cache_version or cache_version is null'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  Task.<span style="color:#9900CC;">should_receive_squirrel_find_with</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;(tasks.active = ? AND (tasks.updated_at &amp;gt; tasks.cache_version OR tasks.cache_version IS NULL))&quot;</span>, <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  Task.<span style="color:#9900CC;">update_cache</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So the class is testing that squirrel is outputting the correct conditions. You could argue that squirrel&#8217;s own tests fulfill this testing need, but this class gives a good jumping point to testing that squirrel is receiving the correct parameters. <a href="http://gist.github.com/182070">The full file can be found here</a>. Just include it from your spec_helper.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/ruby-on-rails/squirrel-and-the-custom-nut-matcher/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Choosing which database indexes to add</title>
		<link>http://www.boost.co.nz/blog/ruby-on-rails/which-database-indexes-to-add/</link>
		<comments>http://www.boost.co.nz/blog/ruby-on-rails/which-database-indexes-to-add/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 05:24:19 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=409</guid>
		<description><![CDATA[When writing a Rails application, how do you decide on the best indexes to add to your database? It might seem obvious, especially if you work on a project from scratch. The problem is a little harder when you come to optimize an existing codebase. New Relic Recently I&#8217;ve been using two methods to work [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fwhich-database-indexes-to-add%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fwhich-database-indexes-to-add%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=mysql,rails" height="61" width="50" /><br />
			</a>
		</div>
<p>When writing a Rails application, how do you decide on the best indexes to add to your database? It might seem obvious, especially if you work on a project from scratch. The problem is a little harder when you come to optimize an existing codebase.</p>
<h3>New Relic</h3>
<p>Recently I&#8217;ve been using two methods to work out where to put indexes. Firstly I&#8217;d strongly recommend using <a href="http://www.newrelic.com/">New Relic RPM</a> in development mode. When running your application you can visit /newrelic to get all kinds of useful information. Here you can see the most recent rails calls:</p>
<p style="text-align: center;"><a href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/Picture-42.png"><img class="size-full wp-image-414 aligncenter" title="Picture 4" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/Picture-42.png" alt="Picture 4" width="613" height="112" /></a></p>
<p><span id="more-409"></span>And you can drill down to see the database calls:</p>
<p><a href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/Picture-8.png"><img class="size-full wp-image-417 aligncenter" title="Picture 8" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/Picture-8.png" alt="Picture 8" width="661" height="82" /></a></p>
<p>And then you can drill down further to see a statement analysis. This will give you information like so:</p>
<table border="0">
<tbody>
<tr>
<td>Query</td>
<td>SELECT * FROM `projects` WHERE (`projects`.account_id = 3) ORDER BY position</td>
</tr>
<tr>
<td>Select type</td>
<td>SIMPLE</td>
</tr>
<tr>
<td>Possible Keys</td>
<td></td>
</tr>
<tr>
<td>Key</td>
<td></td>
</tr>
<tr>
<td>Extra</td>
<td>Using where; Using filesort</td>
</tr>
</tbody>
</table>
<p>So this will tell you that there are no keys used, and no possible keys to use. If you now create a migration as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> CreateIndexes <span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    add_index <span style="color:#ff3333; font-weight:bold;">:projects</span>, <span style="color:#ff3333; font-weight:bold;">:account_id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now run the query again after migrating:</p>
<table border="0">
<tbody>
<tr>
<td>Query</td>
<td>SELECT * FROM `projects` WHERE (`projects`.account_id = 3) ORDER BY position</td>
</tr>
<tr>
<td>Select type</td>
<td>SIMPLE</td>
</tr>
<tr>
<td>Possible Keys</td>
<td>index_projects_on_account_id</td>
</tr>
<tr>
<td>Key</td>
<td>index_projects_on_account_id</td>
</tr>
<tr>
<td>Extra</td>
<td>Using where; Using filesort</td>
</tr>
</tbody>
</table>
<p>But we could do better. Notice that in the extra field it says &#8220;Using filesort&#8221;. This means that MySQL is doing a normal sort using the row data. If projects are usually selected by account_id and ordered by position then we have a good case for sorting by index. We can&#8217;t just add an index on the position column as this won&#8217;t be used (try it and you&#8217;ll see exactly the same results). Instead we have to add an index that covers both account_id and position:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">add_index <span style="color:#ff3333; font-weight:bold;">:projects</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:account_id</span>, <span style="color:#ff3333; font-weight:bold;">:position</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>Now looking in RPM again you&#8217;ll see things change to:</p>
<table border="0">
<tbody>
<tr>
<td>Query</td>
<td>SELECT * FROM `projects` WHERE (`projects`.account_id = 3) ORDER BY position</td>
</tr>
<tr>
<td>Select type</td>
<td>SIMPLE</td>
</tr>
<tr>
<td>Possible Keys</td>
<td>index_projects_on_account_id_and_position</td>
</tr>
<tr>
<td>Key</td>
<td>index_projects_on_account_id_and_position</td>
</tr>
<tr>
<td>Extra</td>
<td>Using where</td>
</tr>
</tbody>
</table>
<h3>Overriding execute</h3>
<p>I talked about using two tools to work out where to put indexes. New Relic is great and gives lots of useful information, but I wanted to see what queries were running without indexes as the application was used, in order decide if they required optimizing. I placed the following (ugly) snippet of code into the development or staging environment file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">after_initialize</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9900CC;">respond_to</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:old_execute</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#9900CC;">class_eval</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      alias_method <span style="color:#ff3333; font-weight:bold;">:old_execute</span>, <span style="color:#ff3333; font-weight:bold;">:execute</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">def</span> log_explain<span style="color:#006600; font-weight:bold;">&#40;</span>str<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> str =~ <span style="color:#006600; font-weight:bold;">/</span>^SELECT.<span style="color:#006600; font-weight:bold;">*</span>WHERE<span style="color:#006600; font-weight:bold;">/</span>i
          results = old_execute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'EXPLAIN %s'</span> <span style="color:#006600; font-weight:bold;">%</span> str<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
          <span style="color:#9966CC; font-weight:bold;">while</span> row = results.<span style="color:#9900CC;">fetch_row</span>
            <span style="color:#9966CC; font-weight:bold;">if</span> row<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
              <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>RAILS_ROOT <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'/log/sql.log'</span>, <span style="color:#996600;">'a'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
                f.<span style="color:#CC0066; font-weight:bold;">puts</span> str
                f.<span style="color:#CC0066; font-weight:bold;">puts</span> row.<span style="color:#9900CC;">inspect</span>
              <span style="color:#9966CC; font-weight:bold;">end</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">def</span> execute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
        log_explain<span style="color:#006600; font-weight:bold;">&#40;</span>args.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        old_execute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This performs a similar task to RPM in that it runs MySQL&#8217;s <a href="http://dev.mysql.com/doc/refman/5.0/en/explain.html">EXPLAIN</a> statement on each SELECT statement that runs. However, I&#8217;ve set it up to filter out any statements that are already using keys (if row[5].blank?). Now by tailing the file log/sql.log I&#8217;ll be able to see any unindexed queries that are running on the database. I can use this information to quickly run through the whole application to find any problem areas.</p>
<h3>What not to index</h3>
<p>Most of the database calls from a rails application are going to be quite generic, the same thing over and over, and indexing is good in this situation. Some database calls are going to be a little different &#8211; think search, statistical count, etc. You&#8217;ll need to think careful if these require indexes or not, considering how often they&#8217;re run, and how fast they need to be. Caching can be a good replacement in these areas. Also take into account that indexes slow down database writes, and indexes on string columns are going to be much more intensive that indexes on integer columns.</p>
<h3>Load testing</h3>
<p>Of course you might not find all problem areas, or you might not be optimizing the correct queries. These methods should give you a good idea, but they&#8217;re no replacement for doing good load testing on your application. We&#8217;ll be posting more about load testing a rails application in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/ruby-on-rails/which-database-indexes-to-add/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Litmus to integrate cross-browser testing into our workflow</title>
		<link>http://www.boost.co.nz/blog/design/cross-browser-testing/</link>
		<comments>http://www.boost.co.nz/blog/design/cross-browser-testing/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 00:27:16 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Cool tools]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Quality assurance]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=362</guid>
		<description><![CDATA[Cross-browser compatibility issues are the bane of web developers world-wide and in this ever shifting landscape it is important to have processes that integrate cross-browser testing in a robust and systematic way. Over the last 9 years we have evolved a robust workflow for web development and cross-browser testing is an integral part of this. [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdesign%2Fcross-browser-testing%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdesign%2Fcross-browser-testing%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=Quality+assurance" height="61" width="50" /><br />
			</a>
		</div>
<p>Cross-browser compatibility issues are the bane of web developers world-wide and in this ever shifting landscape it is important to have processes that integrate cross-browser testing in a robust and systematic way. Over the last 9 years we have evolved a robust workflow for web development and cross-browser testing is an integral part of this.</p>
<h3>An overview of the process</h3>
<p>We start by constructing the HTML/CSS in a text editor (Textmate, RubyMine IDE or Aptana IDE) and viewing it in Firefox. We develop standards compliant HTML/CSS, so Firefox is a great starting point as it supports the CSS standards well and enables us to use a number of key tools including <a href="/blog/design/making-your-site-pixel-perfect/">Pixel Perfect</a>, <a href="http://developer.yahoo.com/yslow/">YSlow</a> and the <a href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer</a> toolbar.</p>
<p>Once we are happy that the design is accurately implemented in Firefox we use <a href="http://litmusapp.com/">Litmus</a> to create screenshots across a selection of Browser/Operating System combinations. <a href="http://litmusapp.com/">Litmus</a> has a number of great features that really make this process easy. Firstly, you can retest the page with a simple button click and <a href="http://litmusapp.com/">Litmus</a> keeps track of the revisions, secondly <a href="http://litmusapp.com/">Litmus</a> uses the W3C validators to check that the HTML and CSS validate and links trough to the error pages and thirdly <a href="http://litmusapp.com/">Litmus</a> lets us indicate visually whether a particular combination is rendering correctly so we can keep track of what is complete and what remains.<br />
<span id="more-362"></span><br />
Running the initial test in <a href="http://litmusapp.com/">Litmus</a> will usually through up a number of issues, especially in IE6 (suprise!). At this stage we move on to the target Browser/Operating system to correct the issues. More often than not this is a process of finding work-arounds for the poor standards support in IE6 and IE7 while still ensuring the the HTML/CSS validates and is semantically correct.</p>
<p>We iterate through the testing in Litmus and fixing problems on the target platform until we are happy that the design is working correctly across all platforms. We then use the publish option in Litmus to create  publicly accessible version of the test to send through to our client. This enables our clients to be certain the design is rendering correctly across platforms. You can see an example test here: <a style="color: #000000; outline-style: none; outline-width: initial; outline-color: initial; padding: 0px; margin: 0px;" href="http://boost.litmusapp.com/pub/5125956" target="_blank">http://boost.litmusapp.com/pub/5125956</a></p>
<p>From here the HTML/CSS gets passed to a developer who integrates the HTML with the web application or content management system. This is where the utility of Litmus really shines. During this phase we use Litmus in the same way as we use Unit tests in our programming, to confirm that nothing is broken as we add features and develop the site. This is the key to consistent and successful projects, constant and consistent testing during the life-cycle of development.</p>
<h3>Using Litmus</h3>
<p>The first step is entering the URL to test and choosing the Browser/Operating Systems. Once you have made your choice you can set this to be the default for further tests.</p>
<div id="attachment_387" class="wp-caption alignnone" style="width: 524px"><a rel="lightbox-litmus" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-1.jpg"><img class="size-large wp-image-387" title="Litmus: starting the test" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-1-514x455.jpg" alt="Litmus: starting the test" width="514" height="455" /></a><p class="wp-caption-text">Litmus: starting the test</p></div>
<p>The second step is viewing the results. The overview screen gives an estimate of how long all tests will take to complete and the page updates as the tests complete. On the left side it shows the results of the HTML and CSS validation.</p>
<div id="attachment_381" class="wp-caption alignnone" style="width: 524px"><a rel="lightbox-litmus" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-2.jpg"><img class="size-large wp-image-381" title="Litmus: Test overview screen" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-2-514x501.jpg" alt="Litmus: Test overview screen" width="514" height="501" /></a><p class="wp-caption-text">Litmus: Test overview screen</p></div>
<p>The third step is to check each of the individual results. At this stage we usually mark the ones that are passing and the ones that are failing to keep track of progress.</p>
<p>Below is a page that is not rendering correctly, and we mark this as incompatible.</p>
<div id="attachment_383" class="wp-caption alignnone" style="width: 524px"><a rel="lightbox-litmus" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-3.jpg"><img class="size-large wp-image-383" title="Litmus: Example of a failing page" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-3-514x501.jpg" alt="Litmus: Example of a failing page" width="514" height="501" /></a><p class="wp-caption-text">Litmus: Example of a failing page</p></div>
<p>Below is a page that is rendering correctly, and we mark this as compatible.</p>
<div id="attachment_385" class="wp-caption alignnone" style="width: 524px"><a rel="lightbox-litmus" href="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-4.jpg"><img class="size-large wp-image-385" title="Litmus: Example of a passing page" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/08/litmus-4-514x501.jpg" alt="Litmus: Example of a passing page" width="514" height="501" /></a><p class="wp-caption-text">Litmus: Example of a passing page</p></div>
<p>The final step is to publish the test and send the URL to the client, you can view the test here: <a style="color: #000000; outline-style: none; outline-width: initial; outline-color: initial; padding: 0px; margin: 0px;" href="http://boost.litmusapp.com/pub/5125956" target="_blank">http://boost.litmusapp.com/pub/5125956</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/design/cross-browser-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Making your site Pixel Perfect</title>
		<link>http://www.boost.co.nz/blog/design/making-your-site-pixel-perfect/</link>
		<comments>http://www.boost.co.nz/blog/design/making-your-site-pixel-perfect/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 00:39:04 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Cool tools]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Development tools]]></category>
		<category><![CDATA[Firefox plugin]]></category>
		<category><![CDATA[Quality assurance]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=314</guid>
		<description><![CDATA[Here at Boost we lovingly handcraft our HTML and CSS when implementing our designs. We use text editors rather than programs like Dreamweaver or Frontpage. We find it&#8217;s faster, and it enables us to produce clean, correct code that&#8217;s easy to integrate. Our process starts with the production of the designs in either Photoshop or [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdesign%2Fmaking-your-site-pixel-perfect%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdesign%2Fmaking-your-site-pixel-perfect%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=Development+tools,Firefox+plugin,Quality+assurance" height="61" width="50" /><br />
			</a>
		</div>
<p>Here at Boost we lovingly handcraft our HTML and CSS when implementing our designs. We use text editors rather than programs like Dreamweaver or Frontpage. We find it&#8217;s faster, and it enables us to produce clean, correct code that&#8217;s easy to integrate.</p>
<p>Our process starts with the production of the designs in either Photoshop or Fireworks. Once these are approved by our client, we convert them to HTML/CSS templates before integrating them with the web application or content management system.</p>
<p>At the HTML/CSS stage we use two tools to ensure the design is being accurately implemented: <a href="http://www.pixelperfectplugin.com/">Pixel Perfect</a> and Litmus. Today I&#8217;ll focus on <a href="http://www.pixelperfectplugin.com/">Pixel Perfect</a> - I&#8217;ll talk about Litmus another time.</p>
<p><span id="more-314"></span></p>
<h3>What is Pixel Perfect?</h3>
<p>Pixel Perfect is a Firefox/<a href="http://getfirebug.com/">Firebug</a> extension that allows web developers and designers to easily overlay a web composition on top of the developed HTML. Pixel Perfect is built on top of Firebug (another Firefox extension), so you will need to have Firebug installed and active to use Pixel Perfect.</p>
<p>The video below is a quick look at how Pixel Perfect is used.</p>
<div id="attachment_299" class="wp-caption alignnone" style="width: 514px"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="504" height="380" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=1319052&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00a8ea&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="504" height="380" src="http://vimeo.com/moogaloop.swf?clip_id=1319052&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00a8ea&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
<p class="wp-caption-text">Pixel Perfect in use.</p></div>
<h3>Why Pixel Perfect?</h3>
<p>We strive to ensure that the integrity of the design is kept as it is implemented.</p>
<p>Because of the way different that browser and operating systems render HTML text, it is practically impossible to get sites rendering identically across all browsers and operating systems that we support. Using tools like Pixel Perfect helps us to make the differences all but imperceptible.</p>
<p>With considerable effort going into our design at Boost, it is important that this is reflected in the final product. While a small gap here and a slightly different text size there seem like small issues in the rough and tumble of building a site, they all add up. What was once a tight, balanced and considered solution to a design problem can turn out as ramshackle, unpolished and unprofessional.</p>
<p>Before we found Pixel Perfect we tried a number of different tools including <a href="http://infinite-labs.net/afloat/">Afloat</a>, which makes the OS X Preview application partially transparent, but this approach was less flexible and didn&#8217;t work as well.</p>
<h3>What are the benefits of using Pixel Perfect?</h3>
<p>Using Pixel Perfect in our HTML/CSS production workflow provides a number of tangible benefits, including:</p>
<ul>
<li>reduced time and cost during the quality assurance process</li>
<li>increased speed of development of the HTML/CSS</li>
<li>creating closer working relationships between designers and developers</li>
<li>a better looking website of which we can all be proud.</li>
</ul>
<h3>Run, don&#8217;t walk, to get Pixel Perfect today</h3>
<p>Grab your copy, for free, from: <a href="http://www.pixelperfectplugin.com/">http://www.pixelperfectplugin.com/</a></p>
<p>And don&#8217;t forget to give a donation if you want to see this great plugin grow and flourish.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/design/making-your-site-pixel-perfect/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flex radar chart component</title>
		<link>http://www.boost.co.nz/blog/development/flex-radar-chart-component/</link>
		<comments>http://www.boost.co.nz/blog/development/flex-radar-chart-component/#comments</comments>
		<pubDate>Wed, 06 May 2009 00:37:24 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[flex flash as3 charting]]></category>

		<guid isPermaLink="false">http://www.boost.co.nz/blog/?p=169</guid>
		<description><![CDATA[We&#8217;ve released a radar (spider, polar) chart component for Flex as an open source (MIT) project on github. This is abstracted from our Sonarhq product. For the most part we&#8217;ve been using the Flex Charting components from Adobe, but this doesn&#8217;t include radar charts. We looked at several commercial packages, but these turned out to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fflex-radar-chart-component%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fdevelopment%2Fflex-radar-chart-component%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly&amp;hashtags=flex+flash+as3+charting" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://www.boost.co.nz/blog/wp-content/uploads/2009/05/blog_graphs_5.png"></a>We&#8217;ve released a radar (spider, polar) chart component for Flex as an open source (MIT) project on <a href="http://github.com/boost/radar-chart">github</a>. This is abstracted from our <a href="http://www.sonarhq.com">Sonarhq</a> product. For the most part we&#8217;ve been using the Flex Charting components from Adobe, but this doesn&#8217;t include radar charts. <img class="borderless alignright size-full wp-image-175" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/05/picture-5.png" border="0" alt="picture-5" width="58" height="62" /> We looked at several commercial packages, but these turned out to be either too expensive, or not flexible enough. There is a free component a vailable at <a href="http://labs.kapit.fr/display/radarchart/Radar+Chart">Kap Lap</a>, but it didn&#8217;t support the styles we needed to match the design we had.</p>
<p>In the end it was easier to produce our own (about a day and a half of work). The project depends on some common libraries we&#8217;ve developed at Boost over the last couple of years, which we haven&#8217;t decided on open sourcing yet, but we have included the binary under the same license so that the charting component can work. Here&#8217;s a demo and how to get going:</p>
<p><span id="more-169"></span></p>
<p style="text-align: center;"><img class="borderless size-full wp-image-174 aligncenter" src="http://www.boost.co.nz/blog/wp-content/uploads/2009/05/picture-2.png" alt="picture-2" width="313" height="272" align="center" /></p>
<p>Download the code or the <a href="http://cloud.github.com/downloads/boost/radar-chart/radar_chart.swc">swc [230KB]</a> file from github and create a new project. In the project properties add the swc library or open the chart project and include it. Create an application with the following code:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;">  <span style="color: #66cc66;">&lt;!</span><span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>
&nbsp;
    <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
      radarChart.<span style="color: #006600;">addAxis</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'bread'</span><span style="color: #66cc66;">&#41;</span>;
      radarChart.<span style="color: #006600;">addAxis</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'cheese'</span><span style="color: #66cc66;">&#41;</span>;
      radarChart.<span style="color: #006600;">addAxis</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wine'</span><span style="color: #66cc66;">&#41;</span>;
      radarChart.<span style="color: #006600;">addAxis</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'fish'</span><span style="color: #66cc66;">&#41;</span>;
      radarChart.<span style="color: #006600;">addAxis</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'meat'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
      radarChart.<span style="color: #006600;">addSeries</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Male'</span>, <span style="color: #66cc66;">&#123;</span>bread: <span style="color: #cc66cc;">3</span>, cheese: <span style="color: #cc66cc;">4</span>, wine: <span style="color: #cc66cc;">5</span>, fish: <span style="color: #cc66cc;">1</span>, meat: <span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
      radarChart.<span style="color: #006600;">addSeries</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Female'</span>, <span style="color: #66cc66;">&#123;</span>bread: <span style="color: #cc66cc;">4</span>, cheese: <span style="color: #cc66cc;">2</span>, wine: <span style="color: #cc66cc;">4</span>, fish: <span style="color: #cc66cc;">5</span>, meat: <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>This will show a simple chart similar to the one here. The charts can be styled quite a bit. Take a look through the code to see the styles that can be applied. Note that I haven&#8217;t yet allowed for styling the bits of text.</p>
<p>Originally my intention was to extend the flex charting objects in order to implement the chart. Unfortunately I found the structure a bit complex, and documentation for extending non-existent. I&#8217;m sure it would have been possible, but I didn&#8217;t get very far and just wanted to just get it done.</p>
<p><strong>Update 24th Aug 2009:</strong> New release that fixes issues with drawing the highlight and removing series <a href="http://cloud.github.com/downloads/boost/radar-chart/radar_chart-1.1.swc">radar_chart-1.1.swc</a>.</p>
<p><strong>Update 28th Oct 2009:</strong> New release that fixes removing labels when removing axis: <a href="http://cloud.github.com/downloads/boost/radar-chart/radar_chart-1.2.swc">radar_chart-1.2.swc</a>.</p>
<p><strong>Update 16th Jul 2010:</strong> Release that works correctly with Flex 4. This is for Flex 4 (Flash Builder 4) only, and will not work with Flex 3. <a href="http://github.com/downloads/boost/radar-chart/radar_chart-1.3-flex4.swc">radar_chart-1.3-flex4.swc</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/development/flex-radar-chart-component/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>JRuby presentation for WellRailed</title>
		<link>http://www.boost.co.nz/blog/ruby-on-rails/jruby-presentation-for-wellrailed/</link>
		<comments>http://www.boost.co.nz/blog/ruby-on-rails/jruby-presentation-for-wellrailed/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 20:28:43 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://boost.co.nz/blog/?p=32</guid>
		<description><![CDATA[On the 25th of February &#8217;09 I did a brief JRuby presentation on JRuby and how we&#8217;re using it at Boost. We&#8217;re really excited about some of the capabilities of JRuby. We&#8217;re running a client deployment on Tomcat fronted by IIS, and it was really easy to get everything set up. We wanted to try [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fjruby-presentation-for-wellrailed%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.boost.co.nz%2Fblog%2Fruby-on-rails%2Fjruby-presentation-for-wellrailed%2F&amp;source=boostnewmedia&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>On the 25th of February &#8217;09 I did a brief JRuby <a href="http://boost.co.nz/blog/wp-content/uploads/2009/03/jruby1.pdf">presentation</a> on JRuby and how we&#8217;re using it at Boost. We&#8217;re really excited about some of the capabilities of JRuby.</p>
<p>We&#8217;re running a client deployment on Tomcat fronted by IIS, and it was really easy to get everything set up. We wanted to try another deployment on <a href="http://glassfish.dev.java.net">Glassfishv3</a> with no webserver in front. Unfortunately (and glassfishv3 is still in development) there were two barriers that prevented us doing so <span id="more-32"></span>:</p>
<ul>
<li>Exessive memory consumption: 2 rails apps + the admin interface = more than a 1G slice could handle.</li>
<li>SSL: I was so close to getting this working, but several hours of working on this is too much, it should be easier.</li>
</ul>
<p>In conclusion, JRuby isn&#8217;t quite ready for our in house projects where we control the deployment, but it is great for Windows deployments. We&#8217;ll keep an eye on it. <a href="http://jruby.codehaus.org/">JRuby 1.2</a> was released just a few days ago with performance increases.</p>
<p>Download the <a href="http://boost.co.nz/blog/wp-content/uploads/2009/03/jruby1.pdf">presentation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boost.co.nz/blog/ruby-on-rails/jruby-presentation-for-wellrailed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
