<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>SKORKS</title>
	
	<link>http://www.skorks.com</link>
	<description>For the betterment of the software craft...</description>
	<lastBuildDate>Wed, 10 Mar 2010 04:00:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/softwaretechandmore" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="softwaretechandmore" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">softwaretechandmore</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>How To Fix The WP-Syntax Special Character Escaping Issue</title>
		<link>http://www.skorks.com/2010/03/how-to-fix-the-wp-syntax-special-character-escaping-issue/</link>
		<comments>http://www.skorks.com/2010/03/how-to-fix-the-wp-syntax-special-character-escaping-issue/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 04:00:30 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-syntax]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1421</guid>
		<description><![CDATA[I use Wordpress as my blogging platform, it&#39;s a great tool, has a heap of plugins so you can do much with very little effort, which suits me fine :). As a software development blog I often have code snippets that I need to post and I want these to look good (i.e. formatting, syntax [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/installing-and-using-sqlite-with-ruby-on-windows/' rel='bookmark' title='Permanent Link: Installing And Using SQLite With Ruby On Windows'>Installing And Using SQLite With Ruby On Windows</a></li>
<li><a href='http://www.skorks.com/2009/08/the-most-handy-netbeans-shortcuts-for-ruby-development/' rel='bookmark' title='Permanent Link: The Most Handy NetBeans Shortcuts For Ruby Development'>The Most Handy NetBeans Shortcuts For Ruby Development</a></li>
<li><a href='http://www.skorks.com/2010/03/writing-a-more-ruby-ish-array-intersection-function-and-sorting-structs/' rel='bookmark' title='Permanent Link: Writing A More Ruby-ish Array Intersection Function And Sorting Structs'>Writing A More Ruby-ish Array Intersection Function And Sorting Structs</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1423" height="304" hspace="25" src="http://www.skorks.com/wp-content/uploads/2010/03/special.jpg" style="width: 406px; height: 304px;" title="special" vspace="5" width="406" />I use <a href="http://wordpress.org/" target="_blank">Wordpress</a> as my blogging platform, it&#39;s a great tool, has a heap of plugins so you can do much with very little effort, which suits me fine :). As a software development blog I often have code snippets that I need to post and I want these to look good (i.e. formatting, syntax highlighting). This is why I use the<a href="http://wordpress.org/extend/plugins/wp-syntax/" target="_blank"> WP-Syntax Wordpress plugin</a>. I am not going to go into why it&#39;s so great, if you&#39;re curious you can check it out for yourself. Suffice to say, it does the job fine except for one very annoying issue. Whenever you have any kind of special characters in your code (which you inevitably do e.g. &lt;, &gt;, &amp; etc.), these always render as their escaped representations. For example if you wanted to write:</p>
<pre>if (foo &lt; 5 &amp;&amp; bar &gt; 6)</pre>
<p>you would end up with:</p>
<pre>if (foo &amp;lt; 5 &amp;amp;&amp;amp; bar &amp;gt; 6)</pre>
<p>Extremely annoying. This only happens if you use the WYSIWYG editor in Wordpress, which is why the plugin FAQ recommends switching off the visual editor and using the source code editor, but that eventually gets to be beyond annoying.</p>
<p>The other day my annoyance threshold reached it&#39;s limit and I decided to find a solution to this issue. I armed myself with an apple (for munching purposes :)) and set to googling. I eventually found a couple of sites which mentioned this issue e.g. <a href="http://www.timshowers.com/2008/08/fixing-escaping-problems-in-wp-syntax/" target="_blank">this one</a> and <a href="http://www.xchris.de/blog/?tag=html-special-characters" target="_blank">this one</a>. Both of these tried to point me to the following link &#8211; <a href="http://blog.felho.hu/escaping-problem-with-wp-syntax-wordpress-plugin.html" target="_blank">http://blog.felho.hu/escaping-problem-with-wp-syntax-wordpress-plugin.html</a>.</p>
<p>Unfortunately when I tried to go there I got:</p>
<pre>Parse error: syntax error, unexpected $end in /home/felho/www/blog.felho.hu/wp-includes/default-filters.php  on line 213</pre>
<p>What a massive fail! Most of the time you don&#39;t want to duplicate information that can be found in other places on the web (which is why we link), but <strong>sometimes the beauty of the internet is the fact that you can find the same info in many different places</strong>. In this case &#8211; the internet failed. The information was only to be found in one place (with everyone else linking there) and that place was dead.</p>
<p>Thankfully the magic of google cache came to the rescue and I was able to recover the original post. So, in the interest keeping the information alive on the web :), I&#39;ll re-post the solution here. Here is what you need to do to fix that special character escaping issue:</p>
<ul>
<li>Jump into your Wordpress configuration and deactivate the WP-syntax plugin for the moment</li>
<li>Jump into your WP-syntax plugin folder, in my case it was the <strong><em>wp-content/plugins/wp-syntax</em></strong> folder under the root of your Wordpress install</li>
<li>Crack open the <strong><em>wp-syntax.php</em></strong> file and find the <strong><em>wp_syntax_highlight</em></strong> function (in my case it was on line 94)</li>
<li>Inside the function find the following line:</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$geshi</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeSHi<span style="color: #009900;">&#40;</span><span style="color: #000088;">$code</span><span style="color: #339933;">,</span> <span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Replace this line with the following:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$geshi</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeSHi<span style="color: #009900;">&#40;</span><span style="color: #990000;">htmlspecialchars_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$code</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>If you&#39;re running your Wordpress install on a server with a PHP version which is older than 5.1, you will not actually have the <strong><em>htmlspecialchars_decode()</em></strong> function. Of course I would be surprised if your PHP version was older than 5.1, but just in case it is, here is what you need to do. You will need to roll your own <strong><em>htmlspecialchars_decode()</em></strong> function, so put in the following code right before the line that you replaced above:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;htmlspecialchars_decode&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">htmlspecialchars_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$quote_style</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">ENT_COMPAT</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">strtr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #990000;">array_flip</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">get_html_translation_table</span><span style="color: #009900;">&#40;</span>HTML_SPECIALCHARS<span style="color: #339933;">,</span> <span style="color: #000088;">$quote_style</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<ul>
<li>Save and exit the file and then go an reactive your plugin in the Wordpress config.</li>
</ul>
<p>This should solve your special character escaping issue &#8211; <strong>it solved mine</strong>.</p>
<p>Here is the funny thing, after I made sure everything was working I went and had a look at the code in <strong><em>wp-syntax.php</em></strong> again, and here is what I found right above the line that we replaced:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$escaped</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;true&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$code</span> <span style="color: #339933;">=</span> <span style="color: #990000;">htmlspecialchars_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$code</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Now, I am no PHP expert, but it looks like we shouldn&#39;t have needed to do what we did, this line should have taken care of everything, but obviously <em>$escaped</em> isn&#39;t equal to <em>&quot;true&quot;</em> and so <em><strong>htmlspecialchars_decode()</strong></em> function never gets called (either that or it does get called, but shouldn&#39;t be). I didn&#39;t really want to experiment with my live blog, but if you have a extraneous Wordpress install with <em>WP-syntax</em> floating around somewhere feel free to poke around. It feels like this shouldn&#39;t be an issue. Anyways, do let me know if you find something out. In the meantime you have a work-around thanks to <em>blog.felho.hu</em> (which is still down :)) and google cache.&nbsp; &nbsp;</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/justin_case/56674818/" target="_blank">Dr Case</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/installing-and-using-sqlite-with-ruby-on-windows/' rel='bookmark' title='Permanent Link: Installing And Using SQLite With Ruby On Windows'>Installing And Using SQLite With Ruby On Windows</a></li>
<li><a href='http://www.skorks.com/2009/08/the-most-handy-netbeans-shortcuts-for-ruby-development/' rel='bookmark' title='Permanent Link: The Most Handy NetBeans Shortcuts For Ruby Development'>The Most Handy NetBeans Shortcuts For Ruby Development</a></li>
<li><a href='http://www.skorks.com/2010/03/writing-a-more-ruby-ish-array-intersection-function-and-sorting-structs/' rel='bookmark' title='Permanent Link: Writing A More Ruby-ish Array Intersection Function And Sorting Structs'>Writing A More Ruby-ish Array Intersection Function And Sorting Structs</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=vPpzHvQSEzM:Sdb7RoMu3KA:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=vPpzHvQSEzM:Sdb7RoMu3KA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=vPpzHvQSEzM:Sdb7RoMu3KA:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/vPpzHvQSEzM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/how-to-fix-the-wp-syntax-special-character-escaping-issue/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Writing A More Ruby-ish Array Intersection Function And Sorting Structs</title>
		<link>http://www.skorks.com/2010/03/writing-a-more-ruby-ish-array-intersection-function-and-sorting-structs/</link>
		<comments>http://www.skorks.com/2010/03/writing-a-more-ruby-ish-array-intersection-function-and-sorting-structs/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 05:00:11 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[array intersection]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1402</guid>
		<description><![CDATA[In my previous post on boolean search, we wrote an efficient list (array) intersection function. But, to be honest, I wasn&#8217;t very happy with it. Considering the fact that we were using Ruby, it just wasn&#8217;t very Ruby-like. So, this time I am going to try and show how that function can be re-written to [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/using-ruby-blocks-and-rolling-your-own-iterators/' rel='bookmark' title='Permanent Link: Using Ruby Blocks And Rolling Your Own Iterators'>Using Ruby Blocks And Rolling Your Own Iterators</a></li>
<li><a href='http://www.skorks.com/2009/09/a-wealth-of-ruby-loops-and-iterators/' rel='bookmark' title='Permanent Link: A Wealth Of Ruby Loops And Iterators'>A Wealth Of Ruby Loops And Iterators</a></li>
<li><a href='http://www.skorks.com/2009/08/more-advanced-ruby-method-arguments-hashes-and-blocks/' rel='bookmark' title='Permanent Link: More Advanced Ruby Method Arguments &#8211; Hashes And Block Basics'>More Advanced Ruby Method Arguments &#8211; Hashes And Block Basics</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img vspace="2" hspace="20" align="left" class="alignleft size-full wp-image-1414" title="intersection" src="http://www.skorks.com/wp-content/uploads/2010/03/intersection.jpg" style="width: 380px; height: 359px;" alt="" />In my previous post on <a href="http://www.skorks.com/2010/02/lets-roll-our-own-boolean-query-search-engine/" target="_blank">boolean search</a>, we wrote an efficient list (array) intersection function. But, to be honest, I wasn&#8217;t very happy with it. Considering the fact that we were using Ruby, it just wasn&#8217;t very Ruby-like. So, this time I am going to try and show how that function can be re-written to not only be more Ruby-ish but to also be tighter and easier to understand. In addition I will look at a couple of interesting aspects of <em>OpenStruct</em>, which will lead nicely into my next post on skip pointers (I&#8217;ve spoken about <a href="http://www.skorks.com/2010/03/how-search-engines-process-documents-before-indexing/" target="_blank">covering skip pointers</a> before).</p>
<h2>The Ruby-ish Intersection Function</h2>
<p>The last time we implemented an array intersection function it looked like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> intersect_lists<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span>
  final_list = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  current_list1_index = <span style="color:#006666;">0</span>
  current_list2_index = <span style="color:#006666;">0</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">while</span><span style="color:#006600; font-weight:bold;">&#40;</span>current_list1_index <span style="color:#006600; font-weight:bold;">&lt;</span> list1.<span style="color:#9900CC;">length</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> 
                          current_list2_index <span style="color:#006600; font-weight:bold;">&lt;</span> list2.<span style="color:#9900CC;">length</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> list1<span style="color:#006600; font-weight:bold;">&#91;</span>current_list1_index<span style="color:#006600; font-weight:bold;">&#93;</span> == list2<span style="color:#006600; font-weight:bold;">&#91;</span>current_list2_index<span style="color:#006600; font-weight:bold;">&#93;</span>
      final_list <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> list1<span style="color:#006600; font-weight:bold;">&#91;</span>current_list1_index<span style="color:#006600; font-weight:bold;">&#93;</span>
      current_list1_index <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
      current_list2_index <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
    <span style="color:#9966CC; font-weight:bold;">elsif</span> list1<span style="color:#006600; font-weight:bold;">&#91;</span>current_list1_index<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> list2<span style="color:#006600; font-weight:bold;">&#91;</span>current_list2_index<span style="color:#006600; font-weight:bold;">&#93;</span>
      current_list1_index <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      current_list2_index <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  final_list
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>There is actually nothing wrong with the code itself. It is an efficient implementation. The reason it is efficient is due to the fact that we only need to walk through each of the lists once, in order to produce the intersected list. So if the sizes of our two lists are <strong><em>x</em> </strong>and <strong><em>y</em></strong>, the intersection takes <strong><em>x+y</em></strong> operations, i.e. the complexity of the algorithm is <strong><em>O(x+y)</em></strong>. If we were writing that function in C, everything would be fine at this point, but we&#8217;re using Ruby. What we really want our function to look like is something along the lines of:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> intersect_lists<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span>
  list1.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item1<span style="color:#006600; font-weight:bold;">|</span>
    list2.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item2<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#008000; font-style:italic;">#stuff</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 would actually work, but we go back to the naive array intersection implementation where we scan through the whole of one list for each of the elements in the other. What we really want is to be able to exit the inner <em>each </em>iterator to allow the outer one to advance, but then restart where we left off the next time we enter the inner one. This way we can compare all the values in both arrays to produce the intersection while still scanning both lists only once. Fortunately with Ruby, we can simply open up the array class and create just such an iterator:</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:#CC0066; font-weight:bold;">Array</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> each_continued
    <span style="color:#9966CC; font-weight:bold;">if</span> !@current_index
      reset_current_index
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0066ff; font-weight:bold;">@current_index</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">size</span>
      next_index = <span style="color:#9966CC; font-weight:bold;">yield</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;">&#91;</span>@current_index<span style="color:#006600; font-weight:bold;">&#93;</span>,@current_index<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> next_index
        <span style="color:#0066ff; font-weight:bold;">@current_index</span> = next_index
        <span style="color:#9966CC; font-weight:bold;">break</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#0066ff; font-weight:bold;">@current_index</span> <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</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> reset_current_index
    <span style="color:#0066ff; font-weight:bold;">@current_index</span> = <span style="color:#006666;">0</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>As you can see our new iterator uses a class level variable (<em>@current_index</em>) to keep track of where the iteration is at. We stop the iteration based on the value that is returned from the block that needs to be passed to this iterator. If the value returned from the block is <em>nil</em>, we continue to iterate. When the value returned is a number, we set it to be the index from which we will restart the iteration next time the method is called. This allows us to not only stop and restart the iteration where we left off, but also roll the iteration forward or back if necessary. This is actually important as we will see shortly. There is only one issue with this implementation, the fact that we need to use a class level variable. The problem is the fact that when one full iteration through the array completes, you need to remember to rewind (i.e. must call <em>reset_current_index</em>) &#8211; not great. The only way to overcome this would be keep track of the current position of the iteration externally and pass this value in as a parameter to the iterator, but we won&#8217;t worry about that for now, for our purposes, resetting the array is not such a big deal.</p>
<p>We can now re-implement our intersection function, it will look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> rubyish_intersect_lists<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span>
  list3 = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  list1.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>value1<span style="color:#006600; font-weight:bold;">|</span>
    list2.<span style="color:#9900CC;">each_continued</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>value2, index2<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> value1 == value2
        list3 <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> value2
        index2 <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> value1 <span style="color:#006600; font-weight:bold;">&lt;</span> value2
        index2
      <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>
  list3
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>You&#8217;ll probably agree that&#8217;s much tighter and more Ruby-ish looking. There are two important things to note, in order to understand how it works.</p>
<ol>
<li>When the values from both lists match, we copy the result into our intersection array, we then need to advance both lists. In order to do this, we get the block of the inner iterator to return the index of the next value in the list. This will cause the inner iterator to terminate, but will also prime it to restart from the index we return out of the block (see what I mean about the importance of giving our iterator the ability to restart the iteration from any index we want). This way we advance our inner iterator and naturally advance the outer one, since the inner one has exited.</li>
<li>When the value of the array in the inner loop is bigger than the outer one, we want to keep advancing the outer iterator, but keep the inner one where it is. We do this very easily, by making the block of the inner iterator return the current index of the list. This has the effect of exiting the inner iterator and priming it to restart in exactly the same place on the next iteration, and of course it naturally advances the outer iterator.</li>
</ol>
<p>The only other scenario is when the value of the outer loop iterator is bigger then the inner one, in which case we want to advance the inner one. This will happen by default, and so needs no special code to handle it.</p>
<h2>Sorting <a href="http://ruby-doc.org/stdlib/libdoc/ostruct/rdoc/classes/OpenStruct.html" target="_blank">OpenStructs</a></h2>
<p>As I said, this post actually a lead into another post, which will be about skip pointers. This in itself, is no big deal, we still want to intersect lists, the only issue is, they have to be lists of objects rather than lists of primitive integers. After all you actually need somewhere to put the skip pointers (if you don&#8217;t really get it, don&#8217;t worry, I&#8217;ll <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">explain in the next post</a>). When I was playing around with skip pointers initially I decided to use <em>OpenStruct </em>to wrap the integers (which are the values of the arrays we were going to intersect). In hindsight I should have created an object, but I was a bit too far along and didn&#8217;t want to go around changing a bunch of code. Here is the problem.</p>
<p>In order to test my intersection function, I generate arrays of integers, using the following function.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> create_raw_mock_postings_list<span style="color:#006600; font-weight:bold;">&#40;</span>min_postings, max_postings, corpus_size<span style="color:#006600; font-weight:bold;">&#41;</span>
  postings_list = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  num_postings = min_postings <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span>max_postings<span style="color:#006600; font-weight:bold;">&#41;</span>
  num_postings.<span style="color:#9900CC;">times</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    postings_list <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span>corpus_size<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  postings_list.<span style="color:#9900CC;">sort</span>.<span style="color:#9900CC;">uniq</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This allows me to dummy up what a <a href="http://www.skorks.com/2010/01/search-fundamentals-basic-indexing/" target="_blank">posting list</a> for a term would look like (a particular number of document ids each of which is a random number between 1 and the size of the corpus). The important bits are in the end i.e. <strong><em>postings_list.sort.uniq</em></strong>. It is very important that the posting list is sorted and all values are distinct. This is fine when your value are integers, it all just works. It would also be fine if the value were objects, since all you would need to do would be to implement the spaceship operator (<strong><em>&lt;=&gt;</em></strong>, so that you can compare them to each other) for everything to once again work (which is why I should have used an object). I, of course, was using OpenStruct and I don&#8217;t know of any way to implement the comparison operator.</p>
<p>When it comes to <strong><em>sort</em></strong>, this is reasonably easy to overcome, since that function takes a block that it can use for comparison, but when it comes to <strong><em>uniq</em></strong>, we&#8217;re out of luck. I needed a function similar to the following:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> create_wrapped_mock_postings_list<span style="color:#006600; font-weight:bold;">&#40;</span>min_postings, max_postings, corpus_size<span style="color:#006600; font-weight:bold;">&#41;</span>
  postings_list = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  num_postings = min_postings <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span>max_postings<span style="color:#006600; font-weight:bold;">&#41;</span>
  num_postings.<span style="color:#9900CC;">times</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    wrapped_id = OpenStruct.<span style="color:#9900CC;">new</span>
    wrapped_id.<span style="color:#9900CC;">value</span> = <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span>corpus_size<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
    postings_list <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> wrapped_id
  <span style="color:#9966CC; font-weight:bold;">end</span>
  postings_list.<span style="color:#9900CC;">sort</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>x,y<span style="color:#006600; font-weight:bold;">|</span> x.<span style="color:#9900CC;">value</span> <span style="color:#006600; font-weight:bold;">&lt;=&gt;</span> y.<span style="color:#9900CC;">value</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">block_uniq</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>item<span style="color:#006600; font-weight:bold;">|</span> item.<span style="color:#9900CC;">value</span><span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ruby goodness came to the rescue, since we can, once again, open up Array and create our own <strong>uniq </strong>function. Like 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> <span style="color:#CC0066; font-weight:bold;">Array</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> block_uniq
    uniqness_hash = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    uniqed_array = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>value<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> block_given?
        uniqness_value = <span style="color:#9966CC; font-weight:bold;">yield</span><span style="color:#006600; font-weight:bold;">&#40;</span>value<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        uniqness_value = value
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> !uniqness_hash.<span style="color:#9900CC;">key</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>uniqness_value<span style="color:#006600; font-weight:bold;">&#41;</span>
        uniqed_array <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> value
        uniqness_hash<span style="color:#006600; font-weight:bold;">&#91;</span>uniqness_value<span style="color:#006600; font-weight:bold;">&#93;</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>
    uniqed_array
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>We use a hash, to make sure the items are unique (i.e. if it is already in the hash, discard it). If no block is given to this function it will just operate like a normal <em><strong>uniq </strong></em>function, but when the block is there, it will use the return value of the block rather than the array items themselves to do it&#8217;s job. Implementing this function allows our <em>create_wrapped_mock_postings_list</em> function to work as intended. One last thing to note is the fact that our new <strong><em>block_uniq</em></strong> function preserves the order of the elements of the array we are uniquing, always good to keep things neat.</p>
<h2>Intersecting Structs</h2>
<p>Now that we&#8217;re dealing with structs rather than integers, our previous intersection function is no longer correct (for exactly the same reason, why <em>sort </em>and <em>uniq </em>were such a pain, I really should have used an object instead of <em>OpenStruct</em>, it&#8217;s a good learning experience, but let that be a lesson to me for later).</p>
<p>We could just slightly alter our intersection function to work with our structs:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> rubyish_intersect_for_wrapped<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span>
  list3 = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  list1.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item1<span style="color:#006600; font-weight:bold;">|</span>
    list2.<span style="color:#9900CC;">each_continued</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item2, index2<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> item1.<span style="color:#9900CC;">value</span> == item2.<span style="color:#9900CC;">value</span>
        list3 <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> item2
        index2 <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> item1.<span style="color:#9900CC;">value</span> <span style="color:#006600; font-weight:bold;">&lt;</span> item2.<span style="color:#9900CC;">value</span>
        index2
      <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>
  list3
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This is actually what I did, but is not necessarily a good solution, since we can augment the original function to work either with integers or with structs or anything else, in a similar way to how we implemented our <strong><em>block_uniq</em></strong> function. For example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> rubyish_intersect_for_wrapped<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span>
  list3 = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  list1.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item1<span style="color:#006600; font-weight:bold;">|</span>
    list2.<span style="color:#9900CC;">each_continued</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>item2, index2<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#9966CC; font-weight:bold;">yield</span><span style="color:#006600; font-weight:bold;">&#40;</span>item1<span style="color:#006600; font-weight:bold;">&#41;</span> == <span style="color:#9966CC; font-weight:bold;">yield</span><span style="color:#006600; font-weight:bold;">&#40;</span>item2<span style="color:#006600; font-weight:bold;">&#41;</span>
        list3 <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> item2
        index2 <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> <span style="color:#9966CC; font-weight:bold;">yield</span><span style="color:#006600; font-weight:bold;">&#40;</span>item1<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#9966CC; font-weight:bold;">yield</span><span style="color:#006600; font-weight:bold;">&#40;</span>item2<span style="color:#006600; font-weight:bold;">&#41;</span>
        index2
      <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>
  list3
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>We can now call this function like so, when we want to work with structs:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">rubyish_intersect_for_wrapped<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>item<span style="color:#006600; font-weight:bold;">|</span> item.<span style="color:#9900CC;">value</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>when we have just plain integers, we would do:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">rubyish_intersect_for_wrapped<span style="color:#006600; font-weight:bold;">&#40;</span>list1, list2<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>item<span style="color:#006600; font-weight:bold;">|</span> item<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Of course, it would be nicer if we had used the <em>block_given?</em> method so that we don&#8217;t have to supply any block at all in the second case, but I&#8217;ll leave that one as an exercise :).</p>
<p>We&#8217;re now ready to tackle skip pointers and see if can actually get better performance (than <em>O(x+y)</em>) from our intersection function. This is <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">coming up very shortly</a>.&nbsp;</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/thomashawk/93498192/" target="_blank">Thomas Hawk</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/using-ruby-blocks-and-rolling-your-own-iterators/' rel='bookmark' title='Permanent Link: Using Ruby Blocks And Rolling Your Own Iterators'>Using Ruby Blocks And Rolling Your Own Iterators</a></li>
<li><a href='http://www.skorks.com/2009/09/a-wealth-of-ruby-loops-and-iterators/' rel='bookmark' title='Permanent Link: A Wealth Of Ruby Loops And Iterators'>A Wealth Of Ruby Loops And Iterators</a></li>
<li><a href='http://www.skorks.com/2009/08/more-advanced-ruby-method-arguments-hashes-and-blocks/' rel='bookmark' title='Permanent Link: More Advanced Ruby Method Arguments &#8211; Hashes And Block Basics'>More Advanced Ruby Method Arguments &#8211; Hashes And Block Basics</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=GaH6_etXbn4:GK-3SHgo-gg:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=GaH6_etXbn4:GK-3SHgo-gg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=GaH6_etXbn4:GK-3SHgo-gg:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/GaH6_etXbn4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/writing-a-more-ruby-ish-array-intersection-function-and-sorting-structs/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Why Your Developers Don’t Want To Swap Pairs – Practical Agility</title>
		<link>http://www.skorks.com/2010/03/why-your-developers-dont-want-to-swap-pairs-practical-agility/</link>
		<comments>http://www.skorks.com/2010/03/why-your-developers-dont-want-to-swap-pairs-practical-agility/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 05:00:55 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[pair programming]]></category>
		<category><![CDATA[pair swapping]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1396</guid>
		<description><![CDATA[Much of the agile process literature is very general. There is a lot of focus on practices and philosophy and empowering teams (nothing wrong with that by the way), but there is also often a lack of practical advice on how to solve the day-to-day problems you run into when working in an agile environment. [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/rules-of-standup-you-dont-need-to-justify-your-own-existence/' rel='bookmark' title='Permanent Link: Rules Of Standup &#8211; You Don&#8217;t Need To Justify Your Own Existence'>Rules Of Standup &#8211; You Don&#8217;t Need To Justify Your Own Existence</a></li>
<li><a href='http://www.skorks.com/2008/10/are-you-actually-a-post-agilist/' rel='bookmark' title='Permanent Link: Are You Actually A Post-Agilist?'>Are You Actually A Post-Agilist?</a></li>
<li><a href='http://www.skorks.com/2009/07/how-to-get-the-most-out-of-your-design-sessions/' rel='bookmark' title='Permanent Link: How To Get The Most Out Of Your Design Sessions'>How To Get The Most Out Of Your Design Sessions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1398" hspace="25" src="http://www.skorks.com/wp-content/uploads/2010/03/pair.jpg" style="width: 368px; height: 245px;" title="pair" vspace="5" />Much of the agile process literature is very general. There is a lot of focus on practices and philosophy and empowering teams (<em>nothing wrong with that by the way</em>), but there is also often a lack of practical advice on how to solve the day-to-day problems you run into when working in an agile environment. It is difficult, as every team encounters different problems and even similar problems often have a different root cause depending on the environment. Regardless, I can see a need for a cookbook type of text, but in the meantime I&#39;d like to weigh on an issue that I have seen quite often with agile teams, that of <a href="http://www.skorks.com/2009/07/effective-vs-ineffective-pair-programming/" target="_blank">pair programming</a> and<strong> the apparent reluctance of many developers to actually swap pairs regularly</strong>.</p>
<blockquote>
<p>If this kind of thing is of interest to you then remember to <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">subscribe to my RSS feed</a> as I <a href="http://www.skorks.com/2010/01/thoughts-on-tdd-a-case-study-with-ruby-and-rspec/" target="_blank">often</a> <a href="http://www.skorks.com/2010/01/the-perfect-size-for-an-agile-team-1-person-its-crazy/" target="_blank">write</a> <a href="http://www.skorks.com/2009/09/types-of-agile-projects-and-the-value-of-velocity/" target="_blank">about</a> <a href="http://www.skorks.com/2009/09/rules-of-standup-you-dont-need-to-justify-your-own-existence/" target="_blank">this</a> <a href="http://www.skorks.com/2009/08/the-most-important-agile-practice-of-all/" target="_blank">sort</a> of <a href="http://www.skorks.com/2009/08/before-there-was-lean-agile-or-waterfall-there-was-theory-x-y-and-z/" target="_blank">stuff</a>.&nbsp;</p>
</blockquote>
<h2>A Novice Agile Team</h2>
<p>I don&#39;t really want to spend too much time here as the issues in the case of novice agile teams are reasonably clear. <strong>It is likely a people or a team dynamics problem</strong>. I would look at one of two things:</p>
<ol>
<li>Did you introduce all the agile practices at once (<em>the big bang approach</em>)? If so, you&#39;ve likely found your problem. <strong>It is often best to introduce practices slowly</strong> to allow everyone to acclimatize. Otherwise people start to feel adrift and try to anchor themselves somehow. The easiest way to do that (anchor yourself) is to make sure you complete the stories you start and so people avoid swapping pairs. It may be worth ignoring the lack of pair swapping and giving the team some more time to get used to the new process (focus on pair swapping a little later).</li>
<li>If people seem comfortable with the practices then <strong>your problem is probably lack of buy-in</strong>. The team doesn&#39;t understand the benefits of pair swapping and sees no need for it. Once again, there is a certain level of discomfort involved with pair swapping. You&#39;re leaving a story in a half-finished state and developers don&#39;t like to do that. You&#39;re also potentially leaving someone you get along with really well (you current pair) for a person who is less familiar to you. Without buy-in there is nothing to counter-balance that discomfort and pair swapping suffers. Your path here is clear, you need to sell people on the benefits that pair swapping brings. Communicate with the team and explain, until you get to the point where people start to prompt each other to swap pairs.&nbsp;</li>
</ol>
<p>It is that simple when it comes to a novice agile team.</p>
<h2>The Experienced Team</h2>
<p>When it comes to an experienced agile team, the problems are not as easy to diagnose. The people are fully aware of the benefits and everyone is comfortable with the process and yet pair swapping is still an issue. It is likely not a people or a team dynamics problem, the culprit is elsewhere in your process. Consider the fact that <strong>your stories might be too big</strong> &#8211; it takes too long for a pair to finish a story.</p>
<p>In order to comfortably swap pairs a developer needs to reach a certain level of understanding regarding a story:</p>
<ul>
<li>have a clear idea of the business requirements (where the current story is concerned)</li>
<li>be comfortable with how everything will be implemented from a technical perspective</li>
<li>have a good idea of how everything will look in a finished state</li>
</ul>
<p>To get to this level of understanding <strong>you need to be involved with a story until it is approximately half-finished</strong> (<em>based on personal experience</em>). Otherwise you feel like you don&#39;t really have a handle on the situation, haven&#39;t yet made enough of a contribution and so will be reluctant to move on to something else.</p>
<p><strong>One of the benefits of pair swapping is to get more people across a particular story</strong>, so it is actually beneficial to swap half way through a story. Unfortunately, not all stories are the same size even when the estimated point value is the same, so all stories reach the half-way point at different times. This is why most teams try to swap pairs at regular time intervals (i.e. half way through the day, start of every day etc.). But, if your stories take two or more days to implement, there will be a lot of reluctance to swap half way through the day. You can certainly make the swap interval longer, but then the new person needs to make up so much ground as far as context is concerned that it is almost counter-productive, they become a passenger. Not to mention the fact that when a story is long and complex you want to see it through to the end to get that satisfied, &quot;job-well-done&quot; feeling.</p>
<p><strong>You would be better off recalibrating the point values for your estimates</strong> so that a 1-pointer becomes a lot smaller (<em>less complex and so takes less time to implement</em>) and consequently larger point-value stories are also smaller. I would go as far as to say that the majority of the stories should be 1-pointers with a few 2-pointers, anything bigger than that should be broken up.</p>
<p>If all of this is unconvincing, here are some reasons why smaller stories are better stories.</p>
<ol>
<li>They allow the team to check in more often (not as many conflicts)</li>
<li>Smaller stories are easier to wrap your head around</li>
<li>Go along way to preventing situations where you&#39;re half way through multiple stories at the end of an iteration (because when you underestimate a small 1-pointer, you&#39;re only a few hours off, when you underestimate a huge 3-pointer, you could be off by more than a day)</li>
</ol>
<p>And of course, people will be a lot happier to swap pairs when the stories are smaller as it takes a lot less time to reach that level of understanding (<em>that I talked about above</em>), where a pair swap is no longer a pain.</p>
<h2>The &quot;Rules&quot; For Breaking Up Functionality</h2>
<p>I have found that people tend to write stories according to a set of pet rules, e.g.:</p>
<ul>
<li>each story must be a vertical</li>
<li>each story must have tangible business value (must be tied directly to requirements)</li>
<li>you must be able to express a story in the form &#8211; &quot;As an X I want to be able to do Y&quot;</li>
<li>etc.</li>
</ul>
<p>The thing to remember is that all those are guidelines. <strong>If sticking to those rules makes a story too big then break them</strong>. Don&#39;t worry too much about business value and it is ok not to make a story a complete vertical. When you break a story up, remember that stories don&#39;t have to be completely independent. Agile teams often try to maintain the illusion that each story is independent and the system is built up from a bunch of discrete verticals. This is never true, there are always dependencies, so if you need to, you can reorganise your task board to make these explicit, this way it becomes easier to break up stories, since you no longer have to try and make each story make sense in isolation.</p>
<p>The lesson here is this, if you see an issue in an experienced agile team (<em>like the reluctance to pair swap</em>), don&#39;t automatically assume it is a people problem or lack of understanding. Look to other parts of your process, there may be a connection you wouldn&#39;t expect. <em>Do you think there are other reasons why people are often reluctant to pair swap? If so, please leave a comment, I&#39;d love to hear them.</em></p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/mikebaird/384300327/" target="_blank">mikebaird</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/rules-of-standup-you-dont-need-to-justify-your-own-existence/' rel='bookmark' title='Permanent Link: Rules Of Standup &#8211; You Don&#8217;t Need To Justify Your Own Existence'>Rules Of Standup &#8211; You Don&#8217;t Need To Justify Your Own Existence</a></li>
<li><a href='http://www.skorks.com/2008/10/are-you-actually-a-post-agilist/' rel='bookmark' title='Permanent Link: Are You Actually A Post-Agilist?'>Are You Actually A Post-Agilist?</a></li>
<li><a href='http://www.skorks.com/2009/07/how-to-get-the-most-out-of-your-design-sessions/' rel='bookmark' title='Permanent Link: How To Get The Most Out Of Your Design Sessions'>How To Get The Most Out Of Your Design Sessions</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=qnCSYBuXJL0:Zk6FdI2Drxk:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=qnCSYBuXJL0:Zk6FdI2Drxk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=qnCSYBuXJL0:Zk6FdI2Drxk:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/qnCSYBuXJL0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/why-your-developers-dont-want-to-swap-pairs-practical-agility/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Most Common Things You Do To A Large Data File With Bash</title>
		<link>http://www.skorks.com/2010/03/the-most-common-things-you-do-to-a-large-data-file-with-bash/</link>
		<comments>http://www.skorks.com/2010/03/the-most-common-things-you-do-to-a-large-data-file-with-bash/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 04:29:35 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[bash shell]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1388</guid>
		<description><![CDATA[I find that whenever I get a large data file from somewhere (i.e. extract some data from a database, crawl some sites and dump the data in a file) I always need to do just that little bit of extra processing before I can actually use it. This processing is always just non-trivial enough and [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/using-bash-to-output-to-screen-and-file-at-the-same-time/' rel='bookmark' title='Permanent Link: Using Bash To Output To Screen And File At The Same Time'>Using Bash To Output To Screen And File At The Same Time</a></li>
<li><a href='http://www.skorks.com/2009/08/bash-shell-awesomeness-mass-killing-processes-on-ubuntu/' rel='bookmark' title='Permanent Link: Bash Shell Awesomeness &#8211; Mass Killing Processes (On Ubuntu)'>Bash Shell Awesomeness &#8211; Mass Killing Processes (On Ubuntu)</a></li>
<li><a href='http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/' rel='bookmark' title='Permanent Link: Bash Shortcuts For Maximum Productivity'>Bash Shortcuts For Maximum Productivity</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1389" hspace="25" src="http://www.skorks.com/wp-content/uploads/2010/03/large.jpg" style="width: 330px; height: 261px;" title="large" vspace="5" />I find that whenever I get a large data file from somewhere (i.e. extract some data from a database, crawl some sites and dump the data in a file) I always need to do just that little bit of extra processing before I can actually use it. This processing is always just non-trivial enough and I do it just uncommonly enough for me to always forget exactly how to go about it. Of course, this is to be expected, if you learn something and want it to stick you have to keep doing it. It&#39;s all part and parcel of how our brain works when it comes to <a href="http://www.skorks.com/2009/08/all-developers-should-know-how-they-learn-best/" target="_blank">learning new skills</a>, but that doesn&#39;t make it any less annoying.</p>
<p>Back to our data file, for me I find that I almost always need to do 3 things (amongst others) before doing anything else with my file.</p>
<ul>
<li>delete the first line (especially when pulling data out of the database)</li>
<li>delete the last line&nbsp;</li>
<li>remove all blank lines</li>
</ul>
<p>Don&#39;t ask me why but for whatever reason, you always get an extraneous first line and unexpected blank lines (and less often an extraneous last line) no matter how you produce the file :).</p>
<p>Anyways, my tool of choice in the matter is <em>bash </em>- it is just too trivial to use anything else (plus I love the <a href="http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/" target="_blank">simplicity and power of the shell</a>). So, to make sure I never forget again here is the easiest way of doing all the three things above using <a href="http://en.wikipedia.org/wiki/Sed" target="_blank"><em>sed</em></a>:</p>
<pre>sed 1d input_file | sed &#39;$d&#39; | sed &#39;/^$/d&#39; &gt; output_file
</pre>
<blockquote>
<p><em><strong>Update</strong></em>: <em>As Evan pointed out in the comments, it would be more efficient to do the following</em>:</p>
<p>sed -e 1d -e &lsquo;$d&rsquo; -e &lsquo;/^$/d&rsquo; input_file &gt; output_file</p>
<p><em>This way the file doesn&#39;t have to go through multiple pipes.<br />
		</em></p>
</blockquote>
<p>Of course since we&#39;re using <em>bash</em>, there should be numerous ways of doing the above.</p>
<p>You can remove the first line using <a href="http://en.wikipedia.org/wiki/AWK" target="_blank"><em>awk</em></a>:</p>
<pre>awk &#39;FNR&gt;1&#39;</pre>
<p>but I don&#39;t know how to remove the last line using <em>awk</em>. Anyone?</p>
<p>You can use <em>head </em>or <em>tail </em>to get rid of the first and last line:</p>
<pre>head --lines=-1 input_file | tail --lines=+2
</pre>
<p>but not to remove blank lines.</p>
<p>You can use <a href="http://en.wikipedia.org/wiki/Grep" target="_blank"><em>grep </em></a>to remove blank lines</p>
<pre>grep -v &quot;^$&quot; input_file
</pre>
<p>but it would be silly to try and use it to remove the first and last line (possible though).</p>
<p>If you know of an easier way to do the above three things in a one-liner using bash &#8211; do share it.</p>
<p><strong>What are some of the most common (but non-trivial enough) things that you find yourself doing with <em>bash </em>when it comes to pre-processing that large data file?</strong></p>
<p><em>For more tips and opinions on software development, process and people <a href="http://feeds.feedburner.com/softwaretechandmore">subscribe to skorks.com</a> today.</em></p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/23209605@N00/4095308330/" target="_blank">rachel_thecat</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/using-bash-to-output-to-screen-and-file-at-the-same-time/' rel='bookmark' title='Permanent Link: Using Bash To Output To Screen And File At The Same Time'>Using Bash To Output To Screen And File At The Same Time</a></li>
<li><a href='http://www.skorks.com/2009/08/bash-shell-awesomeness-mass-killing-processes-on-ubuntu/' rel='bookmark' title='Permanent Link: Bash Shell Awesomeness &#8211; Mass Killing Processes (On Ubuntu)'>Bash Shell Awesomeness &#8211; Mass Killing Processes (On Ubuntu)</a></li>
<li><a href='http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/' rel='bookmark' title='Permanent Link: Bash Shortcuts For Maximum Productivity'>Bash Shortcuts For Maximum Productivity</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=ay4aJFZwdVw:4TmoplbJcFc:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=ay4aJFZwdVw:4TmoplbJcFc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=ay4aJFZwdVw:4TmoplbJcFc:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/ay4aJFZwdVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/the-most-common-things-you-do-to-a-large-data-file-with-bash/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>How A Good Manager Is Like A Ninja</title>
		<link>http://www.skorks.com/2010/03/how-a-good-manager-is-like-a-ninja/</link>
		<comments>http://www.skorks.com/2010/03/how-a-good-manager-is-like-a-ninja/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 06:30:23 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[team building]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1381</guid>
		<description><![CDATA[Firstly, let me start by saying that I am not recommending you dress up in black pyjamas and go on a killing spree :). With that out of the way, this idea actually came to me when I was reading chapter 4 of Beautiful Teams (I&#39;ve mentioned Beautiful Teams before). For whatever reason I must [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/02/how-to-become-a-spammer-as-a-programmer-regardless-of-people-following-you-on-twitter/' rel='bookmark' title='Permanent Link: How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter'>How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1384" hspace="20" src="http://www.skorks.com/wp-content/uploads/2010/03/ninja.jpg" style="width: 279px; height: 362px;" title="ninja" vspace="5" />Firstly, let me start by saying that I am not recommending you dress up in black pyjamas and go on a killing spree :). With that out of the way, this idea actually came to me when I was reading chapter 4 of <a href="http://www.amazon.com/Beautiful-Teams-Inspiring-Cautionary-Veteran/dp/0596518021" target="_blank">Beautiful Teams</a> (I&#39;ve <a href="http://www.skorks.com/2010/02/high-academic-results-make-better-programmers/" target="_blank">mentioned Beautiful Teams before</a>). For whatever reason I must have had ninjas on my mind (<em>as you do</em> :)) and thought that it would be interesting to draw some parallels, since ninjas and managers have a lot more in common than the obvious potential scariness factor.</p>
<p>You see, ninjas are not all about killing. Yes, they may be assassins for hire, but they are, in essence, great enablers. They remove obstacles and through their actions make the impossible, probable. They remain unseen, in the shadows, but what they do has a tremendous impact. <strong>This is what every manager should be &#8211; an enabler</strong>. They should concentrate on removing obstacles to enable you to have the most impact as a professional. When there is an organisational obstacle, that you see no way to overcome, they should be able to use their skills and cunning to make the impossible happen. All this should be done without kicking up too much of a fuss. All you would need to do is watch, slightly bemused, as roadblocks, that were preventing you from doing what you needed to do, disappeared almost by magic. That is true management <a href="http://en.wikipedia.org/wiki/Ninjutsu" target="_blank">ninjutsu</a>.</p>
<p>Let&#39;s speak plainly. You help your people, but you allow them to shine. You don&#39;t seek credit (how useful is an assassin that seeks fame?), you seek to achieve goals. You gain validation through the achievements of your team. What&#39;s the main theme here? It is the fact that<strong> as a manager, you&#39;re actually a servant &#8211; not a dictator</strong>. You serve your people and try to make their lives better, kinda like what a politician should be :). This in turn will allow your people to have a greater positive impact on the wider community (i.e. the company). Everyone benefits in the long run.</p>
<h2>Enough Ninjas</h2>
<p>The rest of what I have to say doesn&#39;t really fit my metaphor, so I am going to abandon it at this point (since I don&#39;t really want to engage in any kind of verbal contortionism :)). It is reasonably easy to distil the <a href="http://www.btimes.co.za/97/1102/tech/tech6.htm" target="_blank">qualities that a good manager needs</a> (<em>even though everyone has different ideas here</em>), even I have done it once <a href="http://www.noop.nl/2009/07/traits-that-make-a-good-dev-manager---a-developers-perspective.html" target="_blank">before in a guest post</a>. <strong><em>The difficult part is HOW do you come to embody those qualities, especially when some of them go directly against your personality?</em></strong></p>
<p>It really comes down to only one factor, <strong>you need to genuinely care about the people who work for you </strong>(<em>if you don&#39;t give a shit about people you&#39;re out of luck</em>). And I don&#39;t mean you need to &#39;<em>say</em>&#39; that you care in a group meeting, you actually have to do it, on an individual basis and then back it up when it counts (i.e. <em>when the person really needs your help</em>). And you have to keep showing that you care &#8211; for each person as an individual &#8211; this is how you build trust. It is difficult for most people to talk about &quot;<em>touchy-feely</em>&quot; stuff in a one-on-one setting, makes us feel uncomfortable. So, we overcome it by avoiding it. Not a good strategy, all it gets you is a generic corporate atmosphere, it does not engender any loyalty. If you can generate loyalty, through building trust and genuinely caring for your people, then when you ask me to <a href="http://www.skorks.com/2010/02/did-your-boss-thank-you-for-coding-yourself-to-death/" target="_blank">put in some extra effort</a>, I am likely to do it, because I know you care and I know you wouldn&#39;t ask frivolously.</p>
<p><strong>A good manager is a good listener</strong>, more than that, <strong>they&#39;re good at reading between the lines</strong>. Remember what I said about removing roadblocks? Well, you&#39;re lucky if the issues are visible and clear-cut (e.g. &quot;<em>We need more machines</em>&quot;). Often the issues are subtle, two team-members don&#39;t get along, people don&#39;t feel empowered, personal problems are affecting work etc. You would be the luckiest manager in the world for someone to just come out and tell you that these problems exist. Often your people themselves aren&#39;t even aware of the issue, or even when they are they may not be comfortable confiding, or simply can&#39;t articulate it. But, through your individual interactions with the people you manage you should be able to deduce what the problems are and it is up to you to then do something about it (<em>yeah you have to be almost a mind-reader &#8211; I didn&#39;t say I had quick and easy answers</em> :)).</p>
<p>Lastly, a good manager, just like a good developer should know his/her business. It doesn&#39;t matter how you fell into your management role, it is up to you to become a professional in what is now your trade. <strong>It is more than just annoying when the only qualification a manager has is their age</strong> or being in the right place at the right time, it is dangerous. When you as a manager don&#39;t try to improve yourself constantly, it paints an unflattering picture, it undermines everything you try to do. Like a fat personal trainer &#8211; it is tantamount to hypocrisy.</p>
<p><em>For more tips and opinions on software development, process and people <a href="http://feeds.feedburner.com/softwaretechandmore">subscribe to skorks.com</a> today.</em></p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/narisa/435307555/" target="_blank">Narisa</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/02/how-to-become-a-spammer-as-a-programmer-regardless-of-people-following-you-on-twitter/' rel='bookmark' title='Permanent Link: How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter'>How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=PPkjgVWmohU:wcdnMEJ28q4:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=PPkjgVWmohU:wcdnMEJ28q4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=PPkjgVWmohU:wcdnMEJ28q4:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/PPkjgVWmohU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/how-a-good-manager-is-like-a-ninja/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How Search Engines Process Documents Before Indexing</title>
		<link>http://www.skorks.com/2010/03/how-search-engines-process-documents-before-indexing/</link>
		<comments>http://www.skorks.com/2010/03/how-search-engines-process-documents-before-indexing/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 10:20:59 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[preprocesing]]></category>
		<category><![CDATA[search indexing]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1369</guid>
		<description><![CDATA[From my last two posts about searching (i.e. basic indexing and boolean queries), you might get an impression that writing a search engine is a fairly straight forward process. Infact nothing could be further from the truth. To highlight this I am going to explore one of the issues that I have glossed over previously [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/01/search-fundamentals-basic-indexing/' rel='bookmark' title='Permanent Link: Search Fundamentals &#8211; Basic Indexing'>Search Fundamentals &#8211; Basic Indexing</a></li>
<li><a href='http://www.skorks.com/2010/02/lets-roll-our-own-boolean-query-search-engine/' rel='bookmark' title='Permanent Link: Lets Roll Our Own Boolean Query Search Engine'>Lets Roll Our Own Boolean Query Search Engine</a></li>
<li><a href='http://www.skorks.com/2009/09/become-a-better-developer-by-indexing-your-brain/' rel='bookmark' title='Permanent Link: Become A Better Developer By Indexing Your Brain'>Become A Better Developer By Indexing Your Brain</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1372" hspace="20" src="http://www.skorks.com/wp-content/uploads/2010/03/language.jpg" style="width: 423px; height: 289px;" title="language" vspace="5" />From my last two posts about searching (i.e. <a href="http://www.skorks.com/2010/01/search-fundamentals-basic-indexing/" target="_blank">basic indexing</a> and <a href="http://www.skorks.com/2010/02/lets-roll-our-own-boolean-query-search-engine/" target="_blank">boolean queries</a>), you might get an impression that writing a search engine is a fairly straight forward process. Infact nothing could be further from the truth. To highlight this I am going to explore one of the issues that I have glossed over previously in a little bit more detail &#8211; that of linguistic preprocessing of documents before indexing occurs. This is a massive topic and I have no hope of covering all of it in any kind of detail in just one post, instead I will try and touch on some of the main concepts and issues involved, to give everyone an idea of the scope that even this tiny area of information retrieval can cover.</p>
<p>So, let&#39;s assume we have just fetched a document, what exactly do we need to do before we begin indexing?</p>
<h2>Determining Document Encoding And Getting A Character Sequence</h2>
<p>The first thing we need to be aware of is the fact that all we have is a byte stream. We don&#39;t necessarily know what kind of document we have just fetched. Of course if we are building a custom search system where we know the kinds of documents that we&#39;ll be dealing with then this is not the case. But, for a complex search engine that needs to deal with multiple document formats, before doing anything else, we need to <strong><em>determine the encoding</em></strong> of the document. We need to do this in order to correctly turn our byte stream into a character stream (some encoding systems use multiple bytes per character e.g. unicode). This may be simple for some documents as they will contain their encoding as metadata, otherwise it is somewhat more complex. I won&#39;t go into too much more detail, you can <a href="http://codesnipers.com/?q=node/68" target="_blank">look here</a> for a little bit more info about determining Unicode, do look around if you&#39;re interested and don&#39;t forget to let me know what you find :).</p>
<p>Once we have determined the encoding, our work is not yet over. Our ultimate aim is to get a character stream, but the document may be an archive (e.g. <em>zip</em>) which we may need to extract in order to work with it&#39;s contents. Alternatively a document may be a binary format (e.g. <em>pdf</em>, or <em>MS Word</em> document) where getting the character stream is quite a bit more involved. Even when this is not the case, <strong>most documents will contain spurious data which we don&#39;t want to deal with</strong> (e.g. <em>html</em> or <em>xml</em> tags) and will therefore need to strip from our document. Having done all of that we eventually end up with a character sequence that we can process further. It is also worth noting that, this part of the system will potentially need to be highly extensible in order to cater for different encodings and document formats (including future ones).</p>
<h2>Find The Document Unit</h2>
<p>Having extracted the relevant characters from the raw document, we now need to determine exactly what constitutes a document for the purposes of our index. In other words we need to find what&#39;s known as a <strong><em>document unit</em></strong> &#8211; i.e. the chunk of text that will be treated as a distinct document by our indexer. This is not as simple as it might appear. Consider &#8211; we have pulled-in a document which contains an e-mail conversation thread, do you treat each e-mail as a separate document, for indexing purposes, or do you just take the whole thread? What if some of the e-mails in the thread have attachments, do you ignore them, or treat each one as a separate document, or make it part of the e-mail that it was attached to? Taking this idea further, let&#39;s say you&#39;re indexing very large documents like books. Is the whole book one document? If someone does a multi-word query you don&#39;t necessarily want the book to come back as a result if one of the words appears at the start and the other at the end &#8211; they may be completely unrelated and would not satisfy the query. So, do you index the book with each chapter being a document, how about each paragraph? <strong>If your document units are too granular however you potentially miss out on concepts that ARE related and would thereby fail to return relevant results</strong>. As you can see it is a precision versus recall trade-off. Depending on your document collection (what you&#39;re trying to index), you may already have a clearly delineated document unit, or you may employ heuristic methods to work out the document units based on the content.</p>
<h2>Tokenizing The Document</h2>
<p>Once we know our document unit, it is time to tokenize. Once again this is deceptively complex. We want to split out document units into parts that will form the terms of our index. In the simplest case we want to split into words on whitespace and punctuation. But, this is only of limited utility. For example if we have words such as &quot;<em>are not</em>&quot; everything is fine, but what about &quot;<em>aren&#39;t</em>&quot;. The semantic meaning is the same so we potentially want to get the same two words &quot;<em>are not</em>&quot; out of it, but if we simply split on punctuation and whitespace, we&#39;ll get &quot;<em>aren t</em>&quot; &#8211; not quite as useful. There are countless examples like that one. But wait, there is more, what about names and terms such as <em>C++</em>, where discarding the plus signs will alter the meaning significantly. Then there are special cases such as URLs, dates, IP addresses, etc. that only make sense if taken as a single token. And if that wasn&#39;t enough consider terms that are made up of multiple words which lose their meaning (or have different meanings) when split up, for example <em>Baden-Baden</em>, <em>San Francisco</em>, <em>Sydney Opera House</em> etc. There are many other similar considerations that we need to be aware of. The crucial thing to remember is this, <strong>whatever tokenizer we apply to our documents during indexing we also need to apply to our queries at search time</strong>, otherwise you will get at best unpredictable results &#8211; pretty obvious. As you can see, tokenization can be a complicated problem and if you&#39;re working with documents in multiple languages, it&#39;s an order of magnitude more complicated still, as each language presents it&#39;s own set of challenges (if you speak a second language you&#39;ll see what I mean, if you don&#39;t, <em>consider the fact that some Asian languages are written without spaces</em> :)).</p>
<p style="text-align: center;"><img align="middle" alt="" class="size-full wp-image-1373" height="334" src="http://www.skorks.com/wp-content/uploads/2010/03/document.jpg" style="width: 444px; height: 334px;" title="document" vspace="5" width="444" /></p>
<h2>Removing Stop Words (Or Not)</h2>
<p>Once we have tokenized successfully, we are almost ready to index, but indexing some of the words adds very little or no value. These are normally called <a href="http://en.wikipedia.org/wiki/Stop_words" target="_blank"><strong><em>stop words</em></strong></a> (think words such as: <em>a, an, the</em> etc.) and are often discarded from the index entirely. To find the stop words we can sort our list of terms by frequency and pick the most frequent ones according to their lack of semantic value (<strong>this can be done by hand as stop lists are normally quite small</strong>). While stop words usually don&#39;t add much value and can be discarded safely, this is not always the case. For example, think of the phrase &quot;<em>to be or not to be</em>&quot; where every word is potentially a stop word, it is not the best outcome when the system returns no results for that kind of query. For this reason web search engines don&#39;t usually employ stop lists. If a search engine does decide to use a stop list, it must once again be applied not only to the documents during indexing, but also to the query during the search.&nbsp;</p>
<h2>Token Normalization</h2>
<p>If you think that we are pretty much ready to start indexing, you would be wrong. The next thing we want to do with our tokens is to <a href="http://en.wikipedia.org/wiki/Text_normalization" target="_blank">normalize</a> them. This means we turn each token we have into its <a href="http://en.wikipedia.org/wiki/Canonical_form" target="_blank">canonical</a> form. For example, as far as we are concerned the terms: <em>co-operation</em> and <em>cooperation</em> are equivalent. So we can say that the canonical form of both of those terms is &#8211; <em>cooperation</em>. We want searches for either of the terms (<em>co-operation or cooperation</em>) to return results applicable to both. We can do this in a couple of ways:</p>
<ul>
<li><strong><a href="http://en.wikipedia.org/wiki/Equivalence_class" target="_blank">Equivalence classing</a></strong> &#8211; this is an implicit process that is based on a set of rules and heuristics. For example we can say that the canonical form of a word with a hyphen is the same word without one and we will therefore create an equivalence class between those words (e.g. <em>co-operation, cooperation -&gt; cooperation</em>). These equivalence classes will be applied to the document terms during indexing as well as to the queries at runtime so that a query that contains one of the words in the equivalence class, will return documents that contains any of the words.</li>
<li><strong>Synonym lists</strong> &#8211; this is a more explicit and labour intensive process, but can give more control. <strong>Synonym lists are constructed by hand</strong> (e.g. think &#8211; <em>chair, stool, seat, throne</em>). These synonym lists can then be applied in one of two ways. At indexing time you can index the same document under all the terms that are synonyms of each other, this requires a bit more space, but at query time any of the synonym terms will match the document. You may also apply the synonym lists at runtime whereby you expand the query to contain more terms (i.e. all the synonyms) which means the query takes a bit longer to execute. How you decide to do it is up to you, <strong>it is a classic space/time trade-off</strong>.</li>
</ul>
<p>There are other normalization steps that can be applied to our terms, such as <em>case folding</em>, whereby we lower-case all our terms. This will of course need to be applied to the query as well, but can come back to bite us, especially where proper names are concerned. For example <em>Crunchy Nut Cornflakes</em> is a breakfast serial, <em>crunchy nut cornflakes</em> are just three random words. Despite this, case folding is normally used by most search engines.</p>
<h2>Stemming And Lemmatization</h2>
<p>We&#39;ve already done a lot of processing on our documents and terms, but there is still more to do. Different words often derive from the same root e.g. <em>differ, different, difference, differing</em> etc. <strong>It make sense that a query for one of these words will potentially be satisfied by a different form of it</strong>. We can therefore try to equate all of these words for indexing purposes. For this we can use either <em>stemming</em> or <em>lemmatization</em> (which are, I guess, types of <em>normalization</em> but deserve a section of their own in my opinion).</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Stemming" target="_blank">Stemming</a> basically concerns itself with chopping off suffixes using various heuristics to find the more of less correct base form of the word. There are several well known stemming algorithms. The <a href="http://snowball.tartarus.org/algorithms/lovins/stemmer.html" target="_blank">Lovins algorithm</a> is one of the earliest stemmers and the <a href="http://tartarus.org/~martin/PorterStemmer/" target="_blank">Porter stemmer</a> is one of the best known. <strong>Stemming tends to increase recall while harming precision</strong>.</li>
<li><a href="http://en.wikipedia.org/wiki/Lemmatisation" target="_blank">Lemmatization</a> is a more complex process using <a href="http://en.wikipedia.org/wiki/Morphology_%28linguistics%29" target="_blank">morphological</a> analysis and vocabularies to arrive at the base form.</li>
</ul>
<p>Neither stemming or lemmatization tend to have a lot of benefit when dealing with English language documents (which doesn&#39;t mean they are never used :)), however languages with richer morphologies will often benefit to a greater degree.</p>
<p>And there you have it. I hope this has given you an appreciation for how complex even a small area, like preprocessing, can be when it comes to search engines. Of course I am far from an expert, so if you have something to add or want to correct me :), then do feel free to leave a comment. I hope you&#39;ve been enjoying my posts about searching, since there is more to come. In my previous post on <a href="http://www.skorks.com/2010/02/lets-roll-our-own-boolean-query-search-engine/" target="_blank">boolean search</a> <strong>I asked if anyone could think of a faster way to intersect lists, well in my next search-related post, I will attempt to do just that</strong>. <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">Stay tuned</a>.</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Images by <a href="http://www.flickr.com/photos/shawnecono/149172094/" target="_blank">Shawn Econo</a> and <a href="http://www.flickr.com/photos/mucio/2889899144/" target="_blank">francescomucio</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/01/search-fundamentals-basic-indexing/' rel='bookmark' title='Permanent Link: Search Fundamentals &#8211; Basic Indexing'>Search Fundamentals &#8211; Basic Indexing</a></li>
<li><a href='http://www.skorks.com/2010/02/lets-roll-our-own-boolean-query-search-engine/' rel='bookmark' title='Permanent Link: Lets Roll Our Own Boolean Query Search Engine'>Lets Roll Our Own Boolean Query Search Engine</a></li>
<li><a href='http://www.skorks.com/2009/09/become-a-better-developer-by-indexing-your-brain/' rel='bookmark' title='Permanent Link: Become A Better Developer By Indexing Your Brain'>Become A Better Developer By Indexing Your Brain</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=xPabr2XMoVU:TsxFNJSWkT0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=xPabr2XMoVU:TsxFNJSWkT0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=xPabr2XMoVU:TsxFNJSWkT0:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/xPabr2XMoVU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/03/how-search-engines-process-documents-before-indexing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using Ruby On Rails With Oracle And Deploying It All To Tomcat</title>
		<link>http://www.skorks.com/2010/02/using-ruby-on-rails-with-oracle-and-deploying-it-all-to-tomcat/</link>
		<comments>http://www.skorks.com/2010/02/using-ruby-on-rails-with-oracle-and-deploying-it-all-to-tomcat/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 06:30:27 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1358</guid>
		<description><![CDATA[Ruby on Rails projects usually use MySQL or PostgreSQL for their database, but in the corporate world, Oracle is king. As much as you might like to have a Postgres backend, the powers-that-be have decreed and you must obey. Don&#39;t worry though, all is not lost, you don&#39;t have to slink back to Java, here [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/installing-and-using-sqlite-with-ruby-on-windows/' rel='bookmark' title='Permanent Link: Installing And Using SQLite With Ruby On Windows'>Installing And Using SQLite With Ruby On Windows</a></li>
<li><a href='http://www.skorks.com/2009/08/digging-into-a-ruby-installation-require-vs-load/' rel='bookmark' title='Permanent Link: Digging Into A Ruby Installation, Require vs Load And Other Stuff'>Digging Into A Ruby Installation, Require vs Load And Other Stuff</a></li>
<li><a href='http://www.skorks.com/2010/02/fetching-rss-feeds-with-ruby-from-behind-a-proxy/' rel='bookmark' title='Permanent Link: Fetching RSS Feeds With Ruby From Behind A Proxy'>Fetching RSS Feeds With Ruby From Behind A Proxy</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="oracle" class="alignleft size-full wp-image-1364" hspace="25" src="http://www.skorks.com/wp-content/uploads/2010/02/oracle.jpg" style="width: 271px; height: 395px;" title="oracle" vspace="5" /><a href="http://rubyonrails.org/" target="_blank">Ruby on Rails</a> projects usually use <a href="http://www.mysql.com/" target="_blank">MySQL</a> or <a href="http://www.postgresql.org/" target="_blank">PostgreSQL</a> for their database, but in the corporate world, <a href="http://www.oracle.com/us/products/database/index.htm" target="_blank">Oracle</a> is king. As much as you might like to have a Postgres backend, the powers-that-be have decreed and you must obey. Don&#39;t worry though, all is not lost, you don&#39;t have to slink back to Java, <strong>here is how you can get your Rails app working with an Oracle database</strong>. <u><em>Note: All of this works with Rails 2.3.5, I haven&#39;t tried it with <a href="http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/" target="_blank">Rails 3</a>, but feel free to give it a go and don&#39;t forget to let me know how it works out.</em></u></p>
<h2>Getting Rails To Play With Oracle</h2>
<p>Alright, first thing first, I hope you&#39;re using <a href="http://rvm.beginrescueend.com/" target="_blank">RVM</a>, cause <a href="http://www.skorks.com/2010/01/using-multiple-rubies-seamlessly-on-the-one-machine-with-rvm/" target="_blank">it&#39;s awesome</a> and will make your life easier. With that out of the way, you need to install two gems, before trying to use Oracle with Rails.</p>
<ol>
<li><a href="http://rubyforge.org/projects/ruby-oci8/" target="_blank">ruby-oci8 gem</a> &#8211; this is the ruby interface for oracle using the OCI8 API. <strong>You need to have a version of Oracle installed on your machine for this gem to work</strong>, otherwise the OCI8 library will not be available on your machine and this will make your life difficult (i.e. impossible :)), as you might imagine.</li>
<li><a href="http://github.com/rsim/oracle-enhanced" target="_blank">activerecord oracle enhanced adapter gem</a> &#8211; this is an ActiveRecord adapter that has useful extra methods for working with new and legacy Oracle databases from Rails.</li>
</ol>
<p>You can potentially <em>vendor</em> the oracle enhanced adapter gem within your rails app, but <strong>I wouldn&#39;t vendor the ruby-oci8 gem as it has native extensions</strong>. Normally that would be fine, but we&#39;re going to make a Java application out of this in the end (for deployment to Tomcat) and native extensions will once again make life very difficult (i.e. impossible :)).</p>
<p>So, to install these gems we do:</p>
<pre>gem install ruby-oci8
gem install activerecord-oracle_enhanced-adapter</pre>
<p>This will usually go smoothly, but I&#39;ve had one situation where the native extensions failed to build properly when installing <em>ruby-oci8</em>, and I couldn&#39;t find anything that should have caused that. To fix the issue, <strong>I simply compiled it from source and then re-installed it as a gem again</strong>, at which point everything went smoothly. Something to keep in mind.</p>
<h3>Rails Configuration</h3>
<p>As you would expect, we now need to modify our <em>database.yml</em> to configure our Oracle database. It is reasonably straight forward, but there are a few things to be aware of. By default your <em>database.yml</em> file will have something like this:</p>
<pre>development:
  adapter: mysql
  database: rails_development
  username: user
  password: pass
</pre>
<p>Of course there will also be similar entries for <em>test</em> and <em>production</em>.</p>
<p>Oracle has a slightly different model, we don&#39;t have to create different databases, <strong><em>we create different database users</em></strong>, so the username and password are used to distinguish between different Oracle dbs.</p>
<p>Our configuration will now look like this:</p>
<pre>development:
  adapter: oracle_enhanced
  database: YOUR_ORACLE_SID
  host: localhost
  username: user
  password: pass
  port: 1522
</pre>
<p>The differences from the norm are as follows:</p>
<ul>
<li>you need to have an <em>adapter</em> entry and the value will always be <em>oracle_enhanced</em></li>
<li><strong>the <em>database</em> entry should contain the SID of your oracle installation</strong>, this too will always remain the same</li>
<li>as I mentioned the <em>username</em> and <em>password</em> are not just the credentials but will also identify the Oracle database (as per how Oracle works)</li>
<li>if you changed the default port (the default is 1521) when installing Oracle you need to specify that too</li>
</ul>
<p>You will once again need similar entries for <em>test</em> and <em>production</em> to maintain the standard Rails conventions.</p>
<h3>Modifying Your Normal Workflow</h3>
<p>Of course things are not quite as simple as that (they never are with Oracle :)). Firstly, some of the <em>rake</em> commands you&#39;re used to will not work with Oracle, such as:</p>
<pre>rake db:create
rake db:drop</pre>
<p>You <strong>will need to create your Oracle databases by hand</strong>, which in &quot;<em>Oracle world</em>&quot; means you will need to create some users. You have to log in to Oracle as an admin user, create another user and give them the right privileges. To log in to Oracle using <em>sqlplus</em>, you can do the following:</p>
<pre>sqlplus admin_user/admin_password as sysdba</pre>
<p>You can then execute a series of SQL commands similar to those below, in order to create a new user and give them the right privileges:</p>
<pre>CREATE USER my_user IDENTIFIED BY my_password DEFAULT TABLESPACE some_tablespace TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON some_tablespace;
CREATE ROLE my_role;
GRANT all privileges TO my_role;
GRANT my_role TO my_user;</pre>
<p>The tablespace and quota stuff is optional (I think :)) so feel free to leave it out. If things are still not working after you&#39;ve configured it all in Rails and tried it out, you can also try:</p>
<pre>GRANT all privileges TO my_user;</pre>
<p>This should fix most of the issues you might encounter. At this point <strong>all the migrate commands should work</strong>, such as:</p>
<pre>rake db:migrate
rake db:migrate:down</pre>
<p>These are the important ones as far as I am concerned, so I am not too worried about loosing some of the others.</p>
<p>One last thing to note, if you don&#39;t create a separate <em>development</em> and <em>test</em> user due to laziness or whatever (which is exactly what happened in my case :)), be aware that if you run tests through rake all your dev data will be blown away (Rails blows away the data in the test database every time).</p>
<h2>But What If You Need To Deploy To Tomcat?</h2>
<p>Once again the corporate overlords make their presence felt :) and you&#39;re only allowed to deploy to <a href="http://tomcat.apache.org/" target="_blank">Tomcat</a>. You can develop everything in <a href="http://jruby.org/" target="_blank">JRuby</a> and then roll a WAR file in the end, but why bother when you have <a href="http://kenai.com/projects/warbler/pages/Home" target="_blank">Warbler</a>.</p>
<p><strong>Warbler is a gem that will make a WAR file out of your Rails app</strong> &#8211; pretty convenient. They way it does this is by bundling a copy of JRuby (i.e. you don&#39;t need to supply it) and then packaging all the resources in your Rails app into a WAR structure in a sensible fashion. To install Warbler all you need to do is:</p>
<pre>gem install warbler
</pre>
<p>There are a few different things you can do with Warbler, but you really just want to create a WAR file, so all you need to do is go to the root of your Rails app and type:</p>
<pre>warble
</pre>
<p>This will produce a WAR file for you which you can deploy directly to Tomcat &#8211; easy. There are however a few things to be aware of, especially in our case.</p>
<ol>
<li>As I mentioned already, make sure you&#39;re not using any gems that have native extensions (e.g. <a href="http://github.com/whymirror/hpricot" target="_blank">hpricot</a>). Warbler will try to bundle all the gems it needs and it will be pretty difficult (i.e. impossible :)) to do the compilation steps from within a container.</li>
<li>We&#39;re using Oracle, but we will not need the <em>ruby-oci8</em> gem (which has native extensions), <strong>instead we can use the <em>ojdbc14</em> JAR</strong>. All you need to do is place the JAR file in your Rails application&#39;s <em>/lib</em> folder and Warbler will take care of the rest.</li>
<li>Incidentally, if you need to include any other JAR files also put them in the <em>/lib</em> folder of your Rails app.</li>
</ol>
<p>That&#39;s it, unless you were doing something really fancy, you should be able to produce a WAR file, drop it into Tomcat and have a working Java web application with no extra effort. The good thing about this is that <strong>you can develop your application in pure Ruby</strong> (i.e. you don&#39;t need JRuby), JRuby only comes into the picture when you need to deploy. I would recommend deploying as frequently as you can though, to make sure you don&#39;t run into any unexpected surprises.</p>
<p>If you think this unlikely scenario (using Ruby on Rails with Oracle for dev and deploying it all as a Java app to Tomcat) can never happen, think again. This is all based on &quot;real world&quot; events and no animals were harmed in the making of it :). There are a couple of other interesting things we did in the course of that project, such as serving user uploaded images from outside the Rails folder structure with the help of <a href="http://www.modrails.com/" target="_blank">Passenger</a> (during development). I am planning to do a <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">quick post about that at a later date</a>, so if you&#39;re interested &#8211; stay tuned.</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/spacedoutspace/4300027599/" target="_blank">ellen reitman</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/installing-and-using-sqlite-with-ruby-on-windows/' rel='bookmark' title='Permanent Link: Installing And Using SQLite With Ruby On Windows'>Installing And Using SQLite With Ruby On Windows</a></li>
<li><a href='http://www.skorks.com/2009/08/digging-into-a-ruby-installation-require-vs-load/' rel='bookmark' title='Permanent Link: Digging Into A Ruby Installation, Require vs Load And Other Stuff'>Digging Into A Ruby Installation, Require vs Load And Other Stuff</a></li>
<li><a href='http://www.skorks.com/2010/02/fetching-rss-feeds-with-ruby-from-behind-a-proxy/' rel='bookmark' title='Permanent Link: Fetching RSS Feeds With Ruby From Behind A Proxy'>Fetching RSS Feeds With Ruby From Behind A Proxy</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=doHSo6bNPQM:Rii7FR3p4-A:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=doHSo6bNPQM:Rii7FR3p4-A:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=doHSo6bNPQM:Rii7FR3p4-A:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/doHSo6bNPQM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/02/using-ruby-on-rails-with-oracle-and-deploying-it-all-to-tomcat/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Did Your Boss Thank You For Coding Yourself to Death?</title>
		<link>http://www.skorks.com/2010/02/did-your-boss-thank-you-for-coding-yourself-to-death/</link>
		<comments>http://www.skorks.com/2010/02/did-your-boss-thank-you-for-coding-yourself-to-death/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 07:00:51 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[long hours]]></category>
		<category><![CDATA[overtime]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1349</guid>
		<description><![CDATA[Programmers love to work long hours! There I said it, c&#39;mon admit it, your job/boss doesn&#39;t make you do it, we do it to ourselves. Alright, I&#39;ll concede, maybe not all programmers love long hours, but surely with the amount of overtime that is prevalent in this industry at least half of us must love [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/its-not-about-the-duct-tape-its-about-the-people-and-more/' rel='bookmark' title='Permanent Link: It&#8217;s Not About The Duct Tape It&#8217;s About The People (And More)'>It&#8217;s Not About The Duct Tape It&#8217;s About The People (And More)</a></li>
<li><a href='http://www.skorks.com/2009/08/are-you-the-best-developer-in-the-world/' rel='bookmark' title='Permanent Link: Are You The Best Developer In The World?'>Are You The Best Developer In The World?</a></li>
<li><a href='http://www.skorks.com/2009/09/does-software-development-have-a-culture-of-rewarding-failure/' rel='bookmark' title='Permanent Link: Does Software Development Have A Culture Of Rewarding Failure'>Does Software Development Have A Culture Of Rewarding Failure</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><img align="left" alt="" class="alignleft size-full wp-image-1352" height="252" hspace="20" src="http://www.skorks.com/wp-content/uploads/2010/02/tired.jpg" style="width: 351px; height: 252px;" title="tired" vspace="5" width="351" /><strong>Programmers love to work long hours</strong>! There I said it, c&#39;mon admit it, your job/boss doesn&#39;t make you do it, we do it to ourselves. Alright, I&#39;ll concede, maybe not all programmers love long hours, but surely with the amount of overtime that is prevalent in this industry at least half of us must love it. Right?</p>
<p>I can hear the excuses already. &quot;<em>No, no that&#39;s not it, we just love working with cool tech and don&#39;t want to leave a problem unsolved. It is actually a good thing it&#39;s what makes us awesome!</em>&quot;</p>
<p>I say &#8211; you&#39;re not seeing the forest for the trees. Here is some perspective, you&#39;re not doing this for yourself, you&#39;re doing it for &quot;<em>the man</em>&quot;. Admittedly he might be a nice man, but you don&#39;t owe him slavish commitment. Here is even more perspective, <strong>how often are you actually playing with interesting problems and cool tech and how many times are you churning out code</strong> desperately trying to get something delivered and meet some arbitrary deadline that someone has assigned to you? But hey, you&#39;re a business savvy developer, you&#39;re helping the company succeed, your manager has explained the financial situation to you &#8211; it has to be done, we&#39;re relying on you. Well, unless that same manager is right there with you, entertaining you with amusing anecdotes at 2 am, his words are worthless.</p>
<p>Let me tell you a story that a friend once told me. It is about a brilliant developer &#8211; lets call him John.</p>
<blockquote>
<p>John was a superstar, a one in a million programmer. He had an uncanny ability to understand and write code and was 20 times more productive than anyone else. One day the company got a big contract that needed a fast turn-around. The client sent a massive spec document &#8211; to everyone&#39;s dismay. John came to the rescue, he took the spec home and noone heard from him for 3 days. When he came back to work, he looked like hell, but he had gone through the whole spec and had an outline of the solution already finished. Except for one bit which was impossible to implement, though the spec said otherwise &#8211; even the client didn&#39;t realise this, but John picked it up. Amazing!</p>
</blockquote>
<p>When I first heard that story, I was pretty impressed, my first question was, &quot;<em>So, where is this guy now?</em>&quot;. To which my friend replied &#8211; &quot;<em>He is dead, too much hard living!</em>&quot;. Too much hard coding would be more like it. Kinda takes the wind out of that story a little bit &#8211; <strong>John was in his early 30s</strong>.</p>
<p>Programmers take a perverse pleasure from sharing death-march war stories. Even when we do it with disgust, it is a disgust tinged with pride &#8211; daring our peers to do &quot;<em>better</em>&quot;. But it is a bit like those guys who wear their pants so low you can see ALL of their underwear or the people who take up smoking for the &quot;<em>trendy image</em>&quot;. They and their friends think it&#39;s cool &#8211; <strong>everybody else thinks it&#39;s stupid</strong>.</p>
<h2>Making A Bad Situation Worse</h2>
<p>I can see the necessity of occasionally putting in some extra effort and burning the midnight oil at work for a day or two. But when &quot;<em>occasionally</em>&quot; turns to &quot;<em>often</em>&quot;, <strong>when your boss stops thanking you profusely for your efforts and just treats it as norm</strong>, this is when we&#39;re all in trouble. It sets bad expectations, not just for you, for the whole industry. Humans are like dogs, we&#39;re eminently susceptible to <a href="http://www.docstoc.com/docs/8863598/Positive-And-Negative-Reinforcement-And" target="_blank">positive and negative reinforcement</a>. And this whole industry has been conditioned by years of death-marches to the point where it even <a href="http://www.skorks.com/2009/09/does-software-development-have-a-culture-of-rewarding-failure/" target="_blank">rewards this behaviour</a>. Every time we give-in to the long hours argument, we continue to negatively reinforce this trend.</p>
<p>It doesn&#39;t help that we&#39;re herd animals, you only need to get one person and everyone else wants to conform. Guilt comes into the equation &#8211; &quot;<em>we can&#39;t leave our mates by themselves to do the hard-yards, we gotta help them</em>&quot;. The more people conform, the more pressure on the rest of the herd to do so until the whole team is chugging coke and eating pizza at midnight. But how do they suck even one person in, <strong>where is that famed programmer independence</strong>. We&#39;re happy to &quot;<em>stick it to the man</em>&quot; and <a href="http://www.skorks.com/2010/02/high-academic-results-make-better-programmers/" target="_blank">do whatever we want in school</a>, but as soon as we&#39;re in the workforce all bets are off. It is puzzling.</p>
<p>Interestingly, sometimes these gargantuan efforts aren&#39;t even tracked properly, as it would make the project look bad. So they &quot;<em>cook the books</em>&quot;, as far <strong>as the client is concerned everybody is doing 40 hours</strong> a week (i.e. they get billed for 40 hours) and the project is coming in on schedule (maybe), never mind the other 40 hours that everyone on the team puts in. OK, maybe they&#39;ll track the real effort in a &quot;<em>second set of books</em>&quot;. Accountants go to jail for these kinds of shenanigans, but our industry expects it &#8211; nay almost demands it.</p>
<h2>The Sustainable Pace Effort</h2>
<p>Most Agile processes talk about <a href="http://en.wikipedia.org/wiki/Extreme_Programming_Practices#Sustainable_pace" target="_blank">sustainable development pace</a>. But, I&#39;ve <strong>seen even self-confessed agile teams knuckle under and put in the hours</strong>, you know, for the greater good and all. They were still agile though, and don&#39;t you dare say otherwise.</p>
<p>When I think about this stuff I am always reminded of lawyers. You come in as a new lawyer and you put in massive amounts of effort and time, it is the accepted way to get ahead in that industry. No developer wants to be compared to lawyers, but often the situation is similar except <strong>you&#39;re not going to get ahead by doing a lot of overtime as a developer</strong> (unless you&#39;re working for a big 4 consulting company and then you might as well be a lawyer :)). So, lawyer vs programmer, which one is the chump?</p>
<p><a href="http://archives.igda.org/articles/erobinson_crunch.php" target="_blank">Studies about productivity declines</a> when working more than 40 hours a week surface with disturbing regularity. As a developer your creativity declines, you make more mistakes, you miss existing issue etc., to the point where <a href="http://xprogramming.com/xpmag/jatsustainablepace/" target="_blank">you&#39;re doing more harm than good</a>. Should I even mention the health concerns when you spend that much time engaged in the same activity (<strong>they even had rules about spending too much time at work in the Soviet Union</strong>, and those guys were all about putting in the time for the good of the people). What about diet, you can only survive on coke for so long &#8211; poor John couldn&#39;t even make it to 40.</p>
<p>Can you tell that I am against long hours and death marches yet :)? Maybe one of these days <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">I&#39;ll tell you how I got my wake-up call</a>, it is an interesting story. Herding cats is easy compared to getting developers to make a concerted effort in the same direction, it is something I both love and hate about our people (programmers) :). But I do wish that once in a while all the smart developers just took a stand to eliminate at least one of the truly crappy and counter-productive trends in our industry. As far as I am concerned, <strong>smart programmers don&#39;t like to work long hours</strong> and won&#39;t be pressured into it &#8211; <a href="http://37signals.com/svn/posts/893-workplace-experiments" target="_blank">there is more to life</a>.</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/tattoodjay/4058988283/" target="_blank">Tattooed JJ</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/09/its-not-about-the-duct-tape-its-about-the-people-and-more/' rel='bookmark' title='Permanent Link: It&#8217;s Not About The Duct Tape It&#8217;s About The People (And More)'>It&#8217;s Not About The Duct Tape It&#8217;s About The People (And More)</a></li>
<li><a href='http://www.skorks.com/2009/08/are-you-the-best-developer-in-the-world/' rel='bookmark' title='Permanent Link: Are You The Best Developer In The World?'>Are You The Best Developer In The World?</a></li>
<li><a href='http://www.skorks.com/2009/09/does-software-development-have-a-culture-of-rewarding-failure/' rel='bookmark' title='Permanent Link: Does Software Development Have A Culture Of Rewarding Failure'>Does Software Development Have A Culture Of Rewarding Failure</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=rBmflnK87XQ:71C9YF4dbyo:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=rBmflnK87XQ:71C9YF4dbyo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=rBmflnK87XQ:71C9YF4dbyo:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/rBmflnK87XQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/02/did-your-boss-thank-you-for-coding-yourself-to-death/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>The One Skill You Need To Master To Succeed And Grow As A Developer</title>
		<link>http://www.skorks.com/2010/02/the-one-skill-you-need-to-master-to-succeed-and-grow-as-a-developer/</link>
		<comments>http://www.skorks.com/2010/02/the-one-skill-you-need-to-master-to-succeed-and-grow-as-a-developer/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 04:01:39 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[criticism]]></category>
		<category><![CDATA[skills]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1339</guid>
		<description><![CDATA[I am going to give it away right here in the first sentence, it&#39;s the ability to ask for and take criticism. Yeah I know technically it&#39;s two skills. Before you switch off and browse away to look at funny cats with bad grammar, I don&#39;t mean the ability to say:
&#34;Well, of course I can [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/are-you-the-best-developer-in-the-world/' rel='bookmark' title='Permanent Link: Are You The Best Developer In The World?'>Are You The Best Developer In The World?</a></li>
<li><a href='http://www.skorks.com/2009/09/the-best-way-to-interview-a-developer/' rel='bookmark' title='Permanent Link: The Best Way To Interview A Developer'>The Best Way To Interview A Developer</a></li>
<li><a href='http://www.skorks.com/2009/09/become-a-better-developer-by-indexing-your-brain/' rel='bookmark' title='Permanent Link: Become A Better Developer By Indexing Your Brain'>Become A Better Developer By Indexing Your Brain</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><a href="http://www.skorks.com/wp-content/uploads/2010/02/critic.jpg"><img align="left" alt="critic" class="alignleft size-full wp-image-1340" height="265" hspace="20" src="http://www.skorks.com/wp-content/uploads/2010/02/critic.jpg" style="width: 353px; height: 265px;" title="critic" vspace="5" width="353" /></a>I am going to give it away right here in the first sentence, it&#39;s <strong>the ability to ask for and take criticism</strong>. Yeah I know technically it&#39;s two skills. Before you switch off and browse away to look at <a href="http://icanhascheezburger.com/" target="_blank">funny cats with bad grammar</a>, I don&#39;t mean the ability to say:</p>
<p style="margin-left: 40px;">&quot;<em>Well, of course I can take criticism, I am hip, I am with-it.</em>&quot;</p>
<p>It&#39;s like asking people if they are good in bed, it&#39;s not as if anyone is actually going to say that they are terrible. And yet most developers (most people) can&#39;t take criticism well and even fewer know how to ask for criticism and have it be received without uncomfortable silences.</p>
<p><strong>Humans don&#39;t tend to be able to get a lot of insight into their own failings</strong>, so we need an outside opinion. Feel free to disagree with me here, but I&#39;ll tell you this. There are dozens of things I want to learn that I think will improve my skills and make me better at what I do, but it has always been external advice into how, where and what I should tackle that has given me the biggest boost in my growth as a developer. This advice was accidental every single time, just imagine if I could achieve a little bit of repeatability here. <em>I wonder if this is the exact same thought that the dudes who were implementing waterfall for the first time had</em>? Rigid processes aside, taking criticism and using it constructively is especially important for developers. It is basically a matter of survival within our field. There is so much to learn and new stuff comes along at a faster rate than you&#39;re able to &quot;master&quot; (when I say master, I mean become aware of) old stuff. We want our efforts to propel us forward in leaps rather than at the speed of a leisurely crawl (although there is something to be said for crawling as well, but I will <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">get to this some other time</a>).</p>
<h2>So Why Are People Bad At Taking Criticism?</h2>
<p>Well, it doesn&#39;t really help that<strong> most people are really crap at giving constructive criticism</strong>. There is just not a lot of criticism going around, how are you supposed to get good at it if you hardly ever get a chance to practice? Plus, our primal response to criticism is confrontational, either offensive or defensive (<a href="http://www.skorks.com/2009/08/all-developers-should-know-how-they-learn-best/" target="_blank">depending on personality</a>), goes back to the cave days.</p>
<p style="margin-left: 40px;">&quot;<em>I&#39;ve survived right? So how dare you say I am doing something wrong!</em>&quot;.</p>
<p>Double plus, developers are worse at this than most, we&#39;re ornery, we like to argue, we pick on minute details. By rejecting criticism we can immediately scratch too many itches, it&#39;s hard to ignore for the promise of some intangible benefits at a later date. &nbsp;</p>
<h2>What About Asking For Criticism?</h2>
<p>Remember how I said that most people are crap at giving constructive criticism? Well, they know it. They also know you&#39;re bad at it. We&#39;re not particularly comfortable when we&#39;re asked to do stuff that we are no good at. So, they don&#39;t ask you and you don&#39;t ask them, everyone is happy (kind-of). <strong>It&#39;s a global conspiracy that everybody buys into</strong> &#8211; easier that way. Sort of similar to how everything is overpriced 10-fold in the enterprise world (including software), but it is easier to try and get a piece of the pie rather than call the whole industry on it. And when they try to make us criticise other people, like for those crazy annual reviews that most companies have (I&#39;ve got thoughts about them); we do our best to get it over with as quickly as we can and try to use as many words as possible to say as few constructive things as we can get away with.</p>
<h2>What To Do</h2>
<p>Ha, I don&#39;t have all the answers. Just because I observe an issue and see the benefits if it were removed, doesn&#39;t mean I know how to remove it :). I am not particularly great at taking or giving criticism, I am a lot better than I used to be, but there is a long way to go.<strong> I&#39;ve already given one tidbit of advice that can get you on your way &#8211; practice</strong>. The one surefire way to get better at something is to keep doing it. Find some people you trust, and go crazy on each other &#8211; hopefully you&#39;ll still be friends afterwards :).</p>
<p>Here is some more advice, when asking for criticism, it really helps if people don&#39;t know you&#39;re doing it. You need some serious communication wu-shu to pull this off, but I have seen people who were awesome at this. Unsurprisingly considering everything I said above, these people were also awesome at a lot of other things.</p>
<p>Last piece of advice &#8211; <strong>grow a thick skin</strong> without becoming deaf to what people are saying about you. It&#39;s a sad life when you go around taking everything personally, but at the same time you don&#39;t want to dismiss it. There is a saying in Russian &quot;to coil on the moustache&quot; (it seriously doesn&#39;t translate well, considering it&#39;s metaphoric nature), but it essentially means, you examine a piece of information for relevance and take it under advisement if you find it useful. So, ummm, do that.</p>
<p>Seriously, if people followed some of this advise, we could improve workplace atmosphere across the board. Then maybe people could relax a little bit more at work. Of course there are already places where if people were any more relaxed they&#39;d need <a href="http://www.imdb.com/title/tt0701298/quotes" target="_blank">business hammocks</a>. I think I am veering off-topic a little, having a short attention span sucks. Somebody really aught to pull me up on that.</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/lastyearsgirl_/2581843770/" target="_blank">lism.</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2009/08/are-you-the-best-developer-in-the-world/' rel='bookmark' title='Permanent Link: Are You The Best Developer In The World?'>Are You The Best Developer In The World?</a></li>
<li><a href='http://www.skorks.com/2009/09/the-best-way-to-interview-a-developer/' rel='bookmark' title='Permanent Link: The Best Way To Interview A Developer'>The Best Way To Interview A Developer</a></li>
<li><a href='http://www.skorks.com/2009/09/become-a-better-developer-by-indexing-your-brain/' rel='bookmark' title='Permanent Link: Become A Better Developer By Indexing Your Brain'>Become A Better Developer By Indexing Your Brain</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=Jm1FOCxWITc:1w8EbU2YpuY:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=Jm1FOCxWITc:1w8EbU2YpuY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=Jm1FOCxWITc:1w8EbU2YpuY:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/Jm1FOCxWITc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/02/the-one-skill-you-need-to-master-to-succeed-and-grow-as-a-developer/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>High Academic Results Make Better Programmers</title>
		<link>http://www.skorks.com/2010/02/high-academic-results-make-better-programmers/</link>
		<comments>http://www.skorks.com/2010/02/high-academic-results-make-better-programmers/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 11:55:42 +0000</pubDate>
		<dc:creator>Alan Skorkin</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[academics]]></category>

		<guid isPermaLink="false">http://www.skorks.com/?p=1335</guid>
		<description><![CDATA[ I was reading Beautiful Teams the other day. In chapter 2, Scott Berkun talks about &#8220;Ugly Teams&#8221; and weighs in with an opinion on academic scores and how they tell you nothing about a persons aptitude (of course when I say &#8220;person&#8221;, in my mind that translates to &#8211; &#8220;developer&#8221; :)). I&#8217;ve heard similar [...]


<strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/02/how-to-become-a-spammer-as-a-programmer-regardless-of-people-following-you-on-twitter/' rel='bookmark' title='Permanent Link: How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter'>How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter</a></li>
<li><a href='http://www.skorks.com/2009/08/building-software-development-expertise-using-the-dreyfus-model/' rel='bookmark' title='Permanent Link: Building Software Development Expertise &#8211; Using The Dreyfus Model'>Building Software Development Expertise &#8211; Using The Dreyfus Model</a></li>
<li><a href='http://www.skorks.com/2010/03/how-a-good-manager-is-like-a-ninja/' rel='bookmark' title='Permanent Link: How A Good Manager Is Like A Ninja'>How A Good Manager Is Like A Ninja</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p></p><p><a href="http://www.skorks.com/wp-content/uploads/2010/02/better.jpg"><img align="left" alt="better" border="0" height="310" src="http://www.skorks.com/wp-content/uploads/2010/02/better_thumb.jpg" style="border: 0px none ; margin: 0px 20px 5px 0px; display: inline;" title="better" width="413" /></a> I was reading <a href="http://www.amazon.com/Beautiful-Teams-Inspiring-Cautionary-Veteran/dp/0596518021" target="_blank">Beautiful Teams</a> the other day. In chapter 2, Scott Berkun talks about &ldquo;Ugly Teams&rdquo; and weighs in with an opinion on <strong>academic scores and how they tell you nothing about a persons aptitude</strong> (of course when I say &ldquo;person&rdquo;, in my mind that translates to &#8211; &ldquo;developer&rdquo; :)). I&rsquo;ve heard similar opinions so many times now that I felt like I had to champion the other side of the argument. Here are some quotes:</p>
<blockquote>
<p>&ldquo;<em>If we go beneath the superficial, perfect grades </em><em>often mean the perfect following of someone else&#39;s rules</em>&rdquo;</p>
<p>or</p>
<p>&ldquo;<em>They (good grades) are not good indicators of passionate, free-thinking, risk-taking minds</em>&rdquo;</p>
<p>or</p>
<p>&ldquo;<em>The tragedy of a team of perfect people is that they will all be so desperate to maintain their sense of perfection, their 4.0 in life, that when faced with the pressure of an important project their selfish drives will tear the team apart</em>&rdquo;</p>
<p>or</p>
<p>&ldquo;<em>Beautiful people are afraid of scars: they don&#39;t have the imagination to see how beautiful scars can be</em>&rdquo;</p>
</blockquote>
<p>Frankly I have to say &ndash; that is all so much bullshit. How is it that <strong>in the world of software, mediocre grades have come to be equated with creativity and flair</strong> and flashes of genius. &ldquo;Oh, he is an academic underachiever you say &ndash; well that must mean he is a creative, entrepreneurial go-getter who thinks outside the box&rdquo;. You see they just didn&rsquo;t get the poor guy at university, it is so sad that his genius has been overlooked. What a load of rubbish, why is it that this side of the argument is never vociferously argued by people with perfect GPAs and a record of academic excellence? Sure, poor grades can be an indicator of a creative mind but they can also indicate laziness, inability to concentrate, lack of knowledge and skill, inability to complete tasks, poor interpersonal skills etc. Good grades can sometimes mean slavish obedience (rarely), but are more likely to indicate, superior knowledge, better study skills, adaptability, great teamwork skills, quicker mind etc. It is beyond me how high academics can possibly indicate lack of passion and creativity.</p>
<p>So you want to employ some people, you have some high academic achievers and you have some mediocre ones, who do you hire? Do consider the average Joe, those grade jockeys are just law-abiding drones, Joe is the radical who is going to revolutionise the industry, he just needs the right kind of motivation. What about motivation then? <strong>Lack of the right kind of motivation is often cited as the reason for average academic performance</strong>. If only our underachieving friends had the &ldquo;right&rdquo; kind of motivation, they would be brilliant. Well, it&rsquo;s not as if the high achievers get their kicks out of boring lectures and worked examples. The difference is that the high achievers are able do well and motivate themselves despite the banality and minutia. So which skill is more valuable, ability to self-motivate no matter what, or passively waiting for the &ldquo;right&rdquo; type of motivation? Are you sure you have the &ldquo;right&rdquo; kind where you are?</p>
<p>Let&rsquo;s get this one out of the way, cause it will inevitably come up. Yes, <strong>there are plenty of people in the world of software who had average (or worse) grades when they were studying, but have since &ldquo;made it&rdquo;</strong>. They gained kudos, money, the acceptance of their peers (either or all of those) there is no arguing this point. But that in itself is the problem, these academic underachievers who succeed have the spotlight cast upon them, because people didn&rsquo;t expect it of them. They get hailed and written about &ndash; see, even the average Joe can make it. Thing is &#8211; they are the exception, not the rule. These people succeeded &ldquo;despite the fact&rdquo; and this is the very reason why they are interesting. People love an underdog story, makes us feel good, nobody wants to hear about the brilliant guy who lived up to his potential and made it big, as per expectations.</p>
<p>Rather than looking at high academic achievers as conformist drones, let me paint another picture for you. <strong>Those who get good grades are the ultimate survivors</strong>. They enter an environment, evaluate it critically to figure out what skills they need to succeed and thrive in said environment. They then put in the effort to gain and/or sharpen these skills. At this point they can apply their knowledge and skills with precision to get to the top of their environment and stay there. Excellent academic results are just a side-effect. And you know what, it&rsquo;s not as if being a high achiever is black magic, all it takes is a little bit of work and practice (I am <a href="http://feeds.feedburner.com/softwaretechandmore" target="_blank">so going to cover that</a> in a later post).</p>
<p>So yeah, good grades make better programmers, hell, good grades make better anything. And<strong> there is nothing that stops a high achiever from being a passionate, free-thinking, risk-taker</strong>. When faced with the pressure of an important project high achievers won&rsquo;t get torn apart by their selfish desire for perfection, infact they will be better able to adapt and achieve superior results because that is what they do &ndash; evaluate their environment and figure out what is needed for them to succeed. Beautiful people (academically speaking) are not afraid of scars, but they do have the knowledge and skill to avoid the scars when they can and create superior scars when they have to.&nbsp;</p>
<p><span style="font-family: trebuchet ms; font-size: 10px;">Image by <a href="http://www.flickr.com/photos/gogdog/2990527788/" target="_blank">GogDog</a></span></p>


<p><strong>Related posts:</strong><ol><li><a href='http://www.skorks.com/2010/02/how-to-become-a-spammer-as-a-programmer-regardless-of-people-following-you-on-twitter/' rel='bookmark' title='Permanent Link: How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter'>How To Become A Spammer (as a programmer) Regardless Of People Following You On Twitter</a></li>
<li><a href='http://www.skorks.com/2009/08/building-software-development-expertise-using-the-dreyfus-model/' rel='bookmark' title='Permanent Link: Building Software Development Expertise &#8211; Using The Dreyfus Model'>Building Software Development Expertise &#8211; Using The Dreyfus Model</a></li>
<li><a href='http://www.skorks.com/2010/03/how-a-good-manager-is-like-a-ninja/' rel='bookmark' title='Permanent Link: How A Good Manager Is Like A Ninja'>How A Good Manager Is Like A Ninja</a></li>
</ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=bXoJzKwdhyc:A9p0gO4Uye8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/softwaretechandmore?a=bXoJzKwdhyc:A9p0gO4Uye8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/softwaretechandmore?i=bXoJzKwdhyc:A9p0gO4Uye8:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/softwaretechandmore/~4/bXoJzKwdhyc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.skorks.com/2010/02/high-academic-results-make-better-programmers/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic page generated in 7.441 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-03-11 19:53:26 -->
