<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>overwatering &#187; comp. sci.</title>
	<atom:link href="http://www.overwatering.org/blog/category/comp-sci/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.overwatering.org/blog</link>
	<description>Random musings on fish, books and occasionally programming.</description>
	<lastBuildDate>Sat, 04 Sep 2010 18:18:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Talk on Seph</title>
		<link>http://www.overwatering.org/blog/2010/09/a-talk-on-seph/</link>
		<comments>http://www.overwatering.org/blog/2010/09/a-talk-on-seph/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 11:09:18 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[work]]></category>
		<category><![CDATA[seph]]></category>
		<category><![CDATA[thoughtworks]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/?p=343</guid>
		<description><![CDATA[ThoughtWorks&#8216; resident language inventor Ola Bini will be visiting Sydney in September. Ola is one of the four committers on the JRuby project (now the fastest Ruby runtime) and the inventor of the highly experimental prototype-based language Ioke. And we&#8217;ve convinced him to give a talk about his latest language project Seph:


  So without [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.thoughtworks.com/">ThoughtWorks</a>&#8216; resident language inventor <a href="http://olabini.com/">Ola Bini</a> will be visiting Sydney in September. Ola is one of the four committers on the <a href="http://jruby.org/">JRuby</a> project (now the fastest Ruby runtime) and the inventor of the highly experimental prototype-based language <a href="http://en.wikipedia.org/wiki/Ioke_(programming_language)">Ioke</a>. And we&#8217;ve convinced him to give a talk about his latest language project Seph:</p>

<blockquote>
  <p>So without further ado, the big announcement is that I’m working on a new
  language called Seph. [&hellip;] Why? I already have Ioke and JRuby to care
  for, so it’s a very valid question to ask why I would want to take on
  another language project [&hellip;]. The answer is a bit complicated. I
  always knew [&hellip;] that Ioke was an experiment in all senses of the
  word. This means my hope was that some of the quirky features of Ioke would
  influence other languages. But the other side of it is that if Ioke seems
  good enough as an idea, there might be value in expanding and refining the
  concept to make something that can be used in the real world. And that is
  what Seph is really about.<br />
  <span class="byline">&mdash; <a href="http://olabini.com/blog/2010/07/preannouncing-seph/">Preannouncing Seph</a></span></p>
</blockquote>

<p>This will be an informal, and highly technical, talk on a really interesting new language. Come along for a chance to ask your questions. Also, to enjoy some free beer and pizza. There&#8217;s a pretty good chance that <a href="http://martinfowler.com/">Martin Fowler</a> may be in the room, though I&#8217;m not promising anything&hellip;</p>

<p><style>
dl {
  font-size: 0.875em;
}
dt {
  font-weight: bold;
}
</style></p>

<dl>
<dt>Where?</dt>
<dd>ThoughtWorks Sydney Office, Level 8, 51 Pitt St, Sydney</dd>
<dt>When?</dt>
<dd>Wednesday, 8th Sept; 6pm for a 6.30pm start</dd>
<dt>Who?</dt>
<dd>You! Assuming you&#8217;re a developer interested in learning about languages.</dd>
<dt>How?</dt>
<dd>RSVP to <a href="mailto:giles.alexander@thoughtworks.com">Giles Alexander</a> as I need some idea of numbers.</dd>
</dl>

<p>And that&#8217;s all you need to know, see you on Wednesday.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2010/09/a-talk-on-seph/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t Get Throttled</title>
		<link>http://www.overwatering.org/blog/2009/10/dont-get-throttled/</link>
		<comments>http://www.overwatering.org/blog/2009/10/dont-get-throttled/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 09:42:31 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[story]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/?p=323</guid>
		<description><![CDATA[The agile family of software development methodologies is now pretty firmly established. Developers have always been some of the most firm supporters of these approaches. And as developers, we like to focus on the good practices that produce better software: testing, story driven development, continuous integration, etc.

And these are all wonderful things. But, from the [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.agilemanifesto.org/">agile</a> family of software development methodologies is now pretty firmly established. Developers have always been some of the most firm supporters of these approaches. And as developers, we like to focus on the good practices that produce better software: testing, story driven development, continuous integration, etc.</p>

<p>And these are all wonderful things. But, from the inside I think we forget the single best thing about agile software development:</p>

<blockquote>
  <p>Agile means your customers no longer want to throttle you.</p>
</blockquote>

<p>Don&#8217;t forget this: it keeps everything in perspective.</p>

<p>My first real software development job out of <a href="http://www.anu.edu.au/">Uni</a> was at a small technology company. We had a core product, an expert system runtime, that the company was built around. We were organised into two major divisions: Products, who worked on the core technology; and Solutions, a traditional consulting division who delivered projects (usually) based around the core technology. Products would have been about 20% of the company&#8217;s employees. The rest, admin staff and Solutions.</p>

<p>I worked in Products. I like to think we did good work: during the four years I was there the product became much faster, finally ran on more than one OS, supported multiple platforms and countless other features were all delivered. Delivered on a three month release cycle. We had a roadmap of releases covering the next year and a half or so, with features allocated to each release. And every three months there&#8217;d be a new, mildly tested, release that had some of the planned features, some last minute features and a bunch of bug fixes and improvements for features from the last couple of releases.</p>

<p>At this point I would like to remind the uproariously laughing peanut gallery that this was my first job out of Uni and I knew no better. Clearly, neither did any of the managers.</p>

<p>I can still remember the moment of revelation when I discovered that all of Solutions hated us. Hated the Products staff, hated the product. One wag had joked that the company was divided into Solutions and Problems. How could this be? Our technology was great! Really! It was genuinely the best of its kind in the world. Why did they hate us so much? How could they hate us so much?</p>

<p>It&#8217;s obvious now: Solutions were trying to win new business and then deliver projects on time and budget. Invariably they&#8217;d find bugs in the product, or new features they needed. And our response? &#8220;It&#8217;s too late for this release; we&#8217;ll try to include it in the next one.&#8221; In four months time.</p>

<p>Now on an agile team what would I say? &#8220;OK, we&#8217;ll include that bug fix in the next iteration. You&#8217;ll have it Friday week.&#8221; That&#8217;s a bit glib of course. In reality there will have to be a discussion about what is going to get pushed out of the next iteration, and estimation of how long the new work will take. But when your answer can honestly be in terms of tested, working software and a couple of weeks delay, everyone is happy. And in particular your clients are not going to be frustrated and furious.</p>

<p>On only a couple of occasions since have I had to be the client to a waterfall team. And every time I&#8217;ve ended up wanting to throttle them: &#8220;How can it take as long to plan the work as it&#8217;s going to take to do, ferchrissakes?&#8221; And every time I have to remind myself that they&#8217;re not trying to be difficult &mdash; they genuinely want to help &mdash; it really is just this hard to turn the boat.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/10/dont-get-throttled/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing Technology around People</title>
		<link>http://www.overwatering.org/blog/2009/04/designing-technology-around-people/</link>
		<comments>http://www.overwatering.org/blog/2009/04/designing-technology-around-people/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 12:41:06 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[glove]]></category>
		<category><![CDATA[rant]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/?p=161</guid>
		<description><![CDATA[George Orwell&#8217;s 1984 is rightly a hugely famous novel of the twentieth century. His depiction of a totalitarian future was so griping and compelling that the words and phrases he coined in the creation of his vision have embedded themselves in popular language and culture. I wonder how many teenagers watching reality TV understand where [...]]]></description>
			<content:encoded><![CDATA[<p>George Orwell&#8217;s <em>1984</em> is rightly a hugely famous novel of the twentieth century. His depiction of a totalitarian future was so griping and compelling that the words and phrases he coined in the creation of his vision have embedded themselves in popular language and culture. I wonder how many teenagers watching reality TV understand where that catchy title came from?</p>

<p>There was one aspect that Orwell did get glaringly wrong: the impact of technology. the limited technology shown in <em>1984</em> is all very much in the service of the state: the newspaper re-writing tools and the continuously broadcasting screens for example. But these two are both very poor predictions of how technology actually evolved over the three and a half decades between writing <em>1984</em> and 1984. Photocopiers deeply limit the effectiveness of re-writing newspapers &#8211; people would have their own copies, not much point in changing the centrally stored version then? And a network of screens continuously streaming into everyone&#8217;s homes? That&#8217;s just crying out to be subverted as a peer-to-peer network.</p>

<p>But these are just details and a symptom: Orwell got something much more fundamental, and surprising, wrong.</p>

<p>Technology is inherently liberating, not controlling; equalising not oppressive.</p>

<p>How is this possibly so? Modern history is replete with examples of dictators using weapons technology to do pretty horrible things in stamping out rebellion and even more recent history shows huge corporations attempting to do exactly what Orwell predicted, to their customers. But these are just anecdotes. Other anecdotes show mobile phones and hand-held GPS units being of incalculable aid to rebels. Corporations are trying to spy on their customers precisely because they were completely blind-sided by developing technology. I want to address a more fundamental point than these anecdotes.</p>

<p>Technology is probably reasonably described as the output of humanity&#8217;s tool-making instinct. No one really thinks of it as broadly as that, especially now. It&#8217;s inconceivable to regard the chair and the kettle as technology even though they were both once cutting-edge. Instead, technology is regarded as the <em>recent</em> output of our tool-making instinct. There is a question going begging here though: how do recent technological developments migrate into that background of things we just have?</p>

<p>Going back beyond the kettle and the chair, the spear would have once been cutting edge technology, developed after extensive R&amp;D and in the face of punishing market conditions and intense competition by some family somewhere in the African savannah. The immediate effect of this new development <em>within that family</em> would have been stunning. Instead of only the elite runners capable of running down an antelope being the ones providing meat, anyone strong enough to wield a spear suddenly could. Given the very different physical requirements for the two hunting techniques this was certainly a different set of family members. And right there, the spear as a piece of technology has liberated some members of the family. Sure, hunting is still the domain of strong, young males, but this is the savannah of African a million years ago we&#8217;re talking about; it took until 1900 before we even gave women the vote. Equality is a luxury the ancient savannah could never afford.</p>

<p>This is still just a fascinating theory, but think on the implication: the spear was a valuable piece of technology because it helped overcome a physical limitation of the family. And this is generally true of all technology: it is valuable when it lets people do something they otherwise couldn&#8217;t. Technology is about placing the unobtainable within more people&#8217;s grasp &#8211; but not by devaluing the goal, instead by extending the grasp. As the spear placed more meat within the grasp of the family on the savannah, so the mobile phone places more of your friends within range of a chat or a helping hand now. Technology is leverage; it takes what you are already capable of and then by adding a little more in just the right way, makes you capable of something new. By it&#8217;s very nature technology is about raising the average standard of what can be achieved, leveling the field for all.</p>

<p>It is, in two words, inherently empowering. And to me, this is the answer to that question. When technology perfectly articulates its own empowerment it migrates into the background of society, no longer a big deal. Just there for everyone to enjoy.</p>

<p>Of course, that&#8217;s not to say all technological developments achieve this holy grail of leverage. Much development results in brand new technology that never sees widespread use. Many times this is the natural inefficiencies in a capitalist market. Frustrated technologists try to cope using open forums for ideas and development. Open source is a modern example, but public universities have always openly shared their work.</p>

<p>But still we see failures of technology.</p>

<p>Now, if you accept that technology has succeeded when it multiples out the abilities of humanity then the development of the technology is just part of the problem. Just as important is the interface between it and actual living, breathing humans. For technology to effectively leverage our abilities, it must become an invisible extension of ourselves; the interface, the line the technology draws around us, must be a perfect fit between humans and that goal, right there, the one they&#8217;re really after. Without something close to perfection, you&#8217;ve got just another disappointment, and worse: a waste of someone&#8217;s time spent thinking. There is a huge class of ignored and overlooked problems here in these interfaces. These are problems of design; not in the narrow &#8216;how-does-it-look&#8217; sense, but in a much deeper &#8216;how-is-the-functioning-of-this-going-to-interact-with-a-human&#8217; sense.</p>

<p>And I have come to realise that this is a question that I care deeply about. Technology is not an end-in-itself. It must be designed to be used. No, that&#8217;s too weak. Technology must be designed to make people&#8217;s lives better. When designing something don&#8217;t just think &#8216;how will this be used?&#8217; Instead, think &#8216;how will this make someone&#8217;s life better?&#8217; Don&#8217;t waste your life on simple, easy half goals: aim for the big one. Find your target market and work out how your idea will make their life better. And I mean, really make someone&#8217;s life better. Imagine your product fully integrated into their life. Can&#8217;t see it yet? Well, back to the design then. You&#8217;re aiming for a glove here. Accept nothing less.</p>

<p>Looking back at <a href="http://www.overwatering.org/blog/2009/01/perhaps-you-shouldnt-get-involved-in-free-software/">some</a> <a href="http://www.overwatering.org/blog/2008/11/the-worst-desktop-operating-system-evar/">of</a> <a href="http://www.overwatering.org/blog/2008/09/on-the-nature-of-my-damage/">my</a> <a href="http://www.overwatering.org/blog/2008/07/steve-jobs-the-jesusphone-will-save-us/">essays</a> I can see that I&#8217;ve been talking around this indirectly for some time. I recently listened to a <a href="http://www.43folders.com/2009/03/25/blogs-turbocharged">podcast</a> by Merlin Mann of <a href="http://43folders.com">43 Folders</a> and John Gruber of <a href="http://daringfireball.net">Daring Fireball</a> that managed to crystallise my obsession for me. So I&#8217;m now planning of focusing on this idea. I want to see technology designed first and foremost to interact with humans, to fit into their lives invisibly and to thus make their lives better.</p>

<p>There will still be book reviews, because I love to read and writing those makes me a better reader, but I will be attempting to focus my other writing on this central idea: Technology Designed around People. I have no idea if I&#8217;m going to succeed, but at least focusing my rants might make me less annoying to be around. I also believe that society has a fixed amount of attention, this will be an attempt to focus some of that attention where I think it should be.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/04/designing-technology-around-people/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>tel:</title>
		<link>http://www.overwatering.org/blog/2009/03/tel/</link>
		<comments>http://www.overwatering.org/blog/2009/03/tel/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 09:24:37 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[comp. sci.]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/?p=133</guid>
		<description><![CDATA[RFC 2806: a URL scheme for describing phone numbers. A URL looks like tel:+1-312-555-4589. Cute. I didn&#8217;t know this existed. But Mobile Safari on the iPhone does. It seems more immediately useful than hCards (browsers already understand it!) But much more limited in scope: its scope is expended on standards for modem and fax calls. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tools.ietf.org/html/rfc2806">RFC 2806</a>: a URL scheme for describing phone numbers. A URL looks like <a href="tel:+1-312-555-4589"><code>tel:+1-312-555-4589</code></a>. Cute. I didn&#8217;t know this existed. But Mobile Safari on the iPhone does. It seems more immediately useful than <a href="http://microformats.org/wiki/hcard">hCards</a> (browsers already understand it!) But much more limited in scope: its scope is expended on standards for modem and fax calls. Wow. Retro.</p>

<p>I&#8217;ll be keeping it in mind, I believe it will become more important.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/03/tel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Find Mutual Follows, Redux</title>
		<link>http://www.overwatering.org/blog/2009/03/find-mutual-follows-redux/</link>
		<comments>http://www.overwatering.org/blog/2009/03/find-mutual-follows-redux/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 13:49:31 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[application]]></category>
		<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/?p=125</guid>
		<description><![CDATA[Previously, I&#8217;ve mentioned that I&#8217;ve written a script that will show a Twitter user who they and another Twitter user both follow.

Well, a script isn&#8217;t much use to me or anyone else: you can&#8217;t run a script on an iPhone. So like all software wants to be, this script is now a simple little web [...]]]></description>
			<content:encoded><![CDATA[<p>Previously, I&#8217;ve <a href="http://www.overwatering.org/blog/2009/01/finding-mutual-follows/">mentioned</a> that I&#8217;ve written a script that will show a <a href="http://twitter.com">Twitter</a> user who they and another Twitter user both follow.</p>

<p>Well, a script isn&#8217;t much use to me or anyone else: you can&#8217;t run a script on an iPhone. So like all software wants to be, this script is now a simple little web application: <a href="http://mutual.overwatering.org">mutual</a>. Please be gentle, and I know I&#8217;m not a designer.</p>

<p>This should be the start of more useful little applications like this appearing. I&#8217;ll blog about that. Also, for the programmers out there, this is written using the <a href="http://www.sinatrarb.com">Sinatra</a> Ruby web application framework. If you thought writing apps using Rails was fast, well, you ain&#8217;t seen nothing til you&#8217;ve seen Ol&#8217; Blue Eyes take the stage.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/03/find-mutual-follows-redux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding Mutual Follows</title>
		<link>http://www.overwatering.org/blog/2009/01/finding-mutual-follows/</link>
		<comments>http://www.overwatering.org/blog/2009/01/finding-mutual-follows/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 10:52:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/2009/01/finding-mutual-follows/</guid>
		<description><![CDATA[When you&#8217;re a Twitter&#8217;er you will often be
in a situation where someone follows you, and you&#8217;re wondering, &#8216;Who
is this person? Do I know them?&#8217; Well, I can&#8217;t answer that question
for you. But, I have found that one thing that tells you about your
new follower is who they follow that you also follow. Follow?

I want to [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re a <a href="http://twitter.com/gga">Twitter&#8217;er</a> you will often be
in a situation where someone follows you, and you&#8217;re wondering, &#8216;Who
is this person? Do I know them?&#8217; Well, I can&#8217;t answer that question
for you. But, I have found that one thing that tells you about your
new follower is who they follow that you also follow. Follow?</p>

<p>I want to be able to ask the question &#8216;Who do we know in common?&#8217;, in
short. A useful question, but one that can take quite a while to
answer using the web site. I
<a href="http://twitter.com/gga/status/1122570805">asked</a> the lazy
twitterverse if there was already an app for this, but my twitterverse is too small to get an answer. So, I
wrote my own script. I don&#8217;t have any handy web space to run this
from, so you&#8217;ll have to grab it and run it yourself. You will need to
install the <code>twitter4r</code> gem first:</p>

<p><pre><code>sudo gem install twitter4r
</code></pre></p>

<p>Then paste the following code into a Ruby file, and run. It takes two
parameters, the names of the two users for who you want to find common
ground.</p>

<p><pre><code>require 'rubygems'
require 'open-uri'
require 'rexml/document'
require 'twitter'<br/>
class Twitter::User<br />
  def all_friends
    users = friends.map { |f| f.screen_name }
    # If there's more than one page of users, we've already got the
    # first one
    page = 2
    found_users = friends.length
    while found_users &gt;= 100
      found_users = 0
      open("http://twitter.com/statuses/friends/#{screen_name}.xml?page=#{page}") do |f|
        users_doc = REXML::Document.new(f.readlines.join(''))
        users_doc.elements.each('/users/user/screen_name') do |friend_name|
          users &lt;&lt; friend_name.text
          found_users += 1
        end
      end
      page += 1
    end
    users
  end<br/>
end<br/>
def in_common(my_friends, other_friends)
  my_friends.select { |m_n| m_n if other_friends.member? m_n }
end<br/>
def main(me, other)
  c = Twitter::Client.new
  me_friends = c.user(me).all_friends
  other_friends = c.user(other).all_friends
  in_common(me_friends, other_friends).each do |f|
    puts "  #{f}"
  end
end<br/>
main(ARGV.shift, ARGV.shift)
</code></pre></p>

<p>Enjoy, and please let me know how it works out for you, or if you make
any changes. And by the way, *this* is why RESTful APIs rock.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/01/finding-mutual-follows/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Perhaps You Shouldn&#8217;t Get Involved in Free Software</title>
		<link>http://www.overwatering.org/blog/2009/01/perhaps-you-shouldnt-get-involved-in-free-software/</link>
		<comments>http://www.overwatering.org/blog/2009/01/perhaps-you-shouldnt-get-involved-in-free-software/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 13:39:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[rant]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/2009/01/perhaps-you-shouldnt-get-involved-in-free-software/</guid>
		<description><![CDATA[Say you&#8217;re a bright young kid at Univeristy and you&#8217;ve decided that
computer science is what you want to do with your life. What should
you start doing with yourself to live that dream? One piece of advice
you will frequently hear is &#8216;Get involved with an open source/free
software project.&#8217; Should you?

Short answer: yes, with an if. Long [...]]]></description>
			<content:encoded><![CDATA[<p>Say you&#8217;re a bright young kid at Univeristy and you&#8217;ve decided that
computer science is what you want to do with your life. What should
you start doing with yourself to live that dream? One piece of advice
you will frequently hear is &#8216;Get involved with an open source/free
software project.&#8217; Should you?</p>

<p>Short answer: yes, with an if. Long answer: no, with a but.</p>

<p>If you want to be working in computer science, you&#8217;ll probably be
programming. A lot. And in fact, this is probably what you want to
do. Like all professional skills, programming takes a large amount of
practice before you become truly proficient. The commonly cited
figure is 10,000 hours of practice to become proficient in your chosen
profession. The sooner you get started on those 10,000 hours, the
sooner they&#8217;ll be over.</p>

<p>Becoming involved with an open source project is a great way of
getting your practice in. You could also practice on your own project
of course. But, you&#8217;ll get more satisfaction from contributing to an
open source project that others use. To become involved though, you&#8217;ll
need some level of proficiency. So hack around with your own projects;
write a game; then start reading the mailing lists of an open source
project you use and pick a simple bug from the tracker. There&#8217;s lots
of advice out there on how to become involved, I&#8217;ll leave that up to
you.</p>

<p>That&#8217;s a pretty good reason to become involved with an open source
project. And if that is your reason, head on out there kid, you&#8217;ll
do great.</p>

<p>That&#8217;s the &#8216;if&#8217;. Now for the &#8216;but&#8217;.</p>

<p>Notice above that I referred to getting involved with an open source
project? Not the open source <em>community</em>? If you&#8217;re a particularly
bright kid in your class, then please let me beg you to think deep and
long before becoming involved in the community.</p>

<p>Why are computers important? Step outside of your beloved field for a
moment and ask yourself, why do you think computers have been an
important and interesting invention? Why is writing software for
expensive, abstract machines to be used by the middle-class of the
first world a noble endeavour? How can better computer science help
people? I mean <em>really</em> help people. Not allow them to quickly find a
cheaper price on that expensive gadget they don&#8217;t need, but do the
really important things: cure malaria, educate the third world,
connect with strangers, fall in love. Whatever it is you think needs
solving.</p>

<p>Personally, I do think computer science has the potential to make the
world a better place. And I believe you don&#8217;t need to be working in
some research lab to achieve that. My definition of making the
world a better place is simple: find someone with a problem, solve it,
and leave them to find other problems in need of solutions. As an
organic, growing, network every individual has the ability to change
the world for the better by focusing on this question: where do I see
problems that my expertise can help solve?</p>

<p>And here lies my issue with the open source and free software
communities: being able to recompile the kernel to your operating
system is a problem that only other programmers have. The rest of the
world see computers and software as tools to solve their own sets of
problems. Anytime a computer or program does not do what they want, a
problem goes partially unsolved. And that particular unsolved problem
is a problem you&#8217;re simply unqualified to solve. You, as a programmer,
can only ever indirectly help with those problems.</p>

<p>Lifting our heads outside of our insular worlds of programmers and
computer scientists, we can see that the rest of the world has a
problem with computers. These supposedly powerful devices, that the
first world has invested a huge amount of resources in improving over
the last 20 or 30 years just don&#8217;t seem to have reached their
potential. Instead, rather than constant improvement with the goal of
improving the lives of real people, computing has become
insular. Insanely insular. Programmers either solve problems only
other programmers have, or they simply duplicate the work of other
projects, poorly. Very poorly. And this is most obvious in the free
software communities. In my opinion, the world does not need another
poor implementation of a 38 year old operating system. The world does
not need another poor duplicate of photo editing software. The world
does not need another poor duplicate of office productivity software.</p>

<p>The world needs the potential of computers applied to new
problems. Or, at the least, original solutions to already solved
problems. And in my opinion the free software community, in its
current incarnation, will never deliver on either of those. The free
software community is tackling what they see as a moral and ethical
problem: source code wants to be free. Their current solution to this
problem is to duplicate every popular piece of software with a
suitably free license. So entrance into the free software community
requires accepting this, and then duplicating existing commercial
software. To me, that sounds like a complete waste of my brain.</p>

<p>And if you&#8217;re as bright as I think you are, then it sounds like a
complete waste of your brain as well. Please, choose to advance our
industry, take it in new and interesting directions. Start your own
company, work for a large company. These are not immoral
decisions. You will be advancing the sum total of human knowledge, you
will be solving real problems of other people. People without the
expertise to solve these problems. Expertise you have.</p>

<p>And this is without even getting into the ethics of duplicating
someone else&#8217;s work.</p>

<p>The free software rhetoric can also damage both computing and free
software. Personally, I found the moral aim of the One Laptop Per
Child program repugnant. But, their efforts to re-imagine what
computers could be was exciting and full of potential. But, eventually
all for naught as the program has been tried, found guilty and
executed in the court of free software. Why? Because they chose to use
a non-free (gasp!) wireless network driver and because they chose to
allow Windows to run on the device. The project was found wanting, and
abandoned. Why does the choice of underlying operating system matter
that much? If the project believes their new approaches were of value,
why not try to improve Windows? It&#8217;s not as if these computers would
be powerful enough to re-compile Windows anyway, even if the code was
available.</p>

<p>You&#8217;re young, you have brains, you have energy. Please think about it
before deciding that the free software community is where you want to
devote your energy. Do not write off working for Google, <a href="http://silverbrookresearch.com/l-en/employment.html">Silverbrook
Research</a>, ThoughtWorks, or even Microsoft. There is nobility
there, I dare say more than there is to be found in holding back our
industry.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2009/01/perhaps-you-shouldnt-get-involved-in-free-software/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Satisfaction</title>
		<link>http://www.overwatering.org/blog/2008/12/satisfaction/</link>
		<comments>http://www.overwatering.org/blog/2008/12/satisfaction/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 07:35:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[career]]></category>
		<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/2008/12/satisfaction/</guid>
		<description><![CDATA[Working on projects or working on products? Which is for you? Both
provide for interesting, stimulating work with difficult problems to
solve. Which are you personally going to derive the most satisfaction
from? Well, I have a theory, or, a way of phrasing the question that
has helped others in the past and might help you.


When you are working [...]]]></description>
			<content:encoded><![CDATA[<p>Working on projects or working on products? Which is for you? Both
provide for interesting, stimulating work with difficult problems to
solve. Which are you personally going to derive the most satisfaction
from? Well, I have a theory, or, a way of phrasing the question that
has helped others in the past and might help you.</p>

<ul>
<li><p>When you are working on projects you will sit down with someone with a
problem. You&#8217;ll get to know that person and their problem intimately
and personally. Hopefully you&#8217;ll then solve their problem and leave
them in happier and better place. All thanks to the expertise you have
imparted.</p></li>
<li><p>When you are working on products you will not have this personal
connection with your customers. Instead you will attempt to imagine
how all the possible customers in the world could potentially want to
use your product. You&#8217;ll try to place yourself in an enormous range of
situations and attempt to make each of those a bit better. Hopefully,
if your product is completed and a success in the market then you will
have made the world a better place for a huge range of people. None of
whom you&#8217;ll ever know.</p></li>
</ul>

<p>So… satisfaction from helping just a few people you know well, or
satisfaction from helping a huge range of people you&#8217;ll never know? Of
course, if you do choose to work on projects then you&#8217;re guaranteed to
help people, whereas products succeed far less often.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2008/12/satisfaction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic Deployment for Rails</title>
		<link>http://www.overwatering.org/blog/2008/12/automatic-deployment-for-rails/</link>
		<comments>http://www.overwatering.org/blog/2008/12/automatic-deployment-for-rails/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 11:31:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[comp. sci.]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[recipe]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/2008/12/automatic-deployment-for-rails/</guid>
		<description><![CDATA[For the Rails applications we&#8217;re building at work, as well as all the
standard continuous integration features, we also automatically deploy
our applications. That is, every time we submit code a central server
is automatically updated with a new release. Before running tests.

We&#8217;re pretty happy with this set up. It&#8217;s already found a couple of
bugs in some plugins [...]]]></description>
			<content:encoded><![CDATA[<p>For the Rails applications we&#8217;re building at work, as well as all the
standard continuous integration features, we also automatically deploy
our applications. That is, every time we submit code a central server
is automatically updated with a new release. Before running tests.</p>

<p>We&#8217;re pretty happy with this set up. It&#8217;s already found a couple of
bugs in some plugins we&#8217;re using. More on that in an upcoming
post. Here&#8217;s how we made our automatic deployment work. We&#8217;re using
Capistrano for our deployment scripts, we&#8217;re deploying to Phusion
Passenger running under Apache on FreeBSD and our continuous
integration server runs an Ant script.</p>

<p>These instructions describe how to set up a Apache 2.2 web server with
Phusion Passenger on FreeBSD; the Ant script to automatically deploy
and how to configure a Rails app to be deployed like this.</p>

<p>This will give you two new environments for your apps: DEVTEST and
UAT. UAT is a user acceptance testing environment, our system testers
and analysts use and own this environment. We don&#8217;t automatically
deploy to here, we release to here. DEVTEST is the environment we
automatically deploy to.</p>

<h3>Setting up Your Server</h3>

<h4>Installing Phusion Passenger</h4>

<p>Installing Phusion Passenger on a FreeBSD server is no different to
installing anywhere else:</p>

<p><pre><code>$ sudo gem install passenger
$ sudo passenger-install-apache2-module
</code></pre></p>

<h4>Configuring Apache</h4>

<p>At the end of the second step, the installer tells you to add some
config to the end of your Apache config. On FreeBSD, edit this with:</p>

<p><pre><code>$ sudoedit /usr/local/etc/apache22/httpd.conf
</code></pre></p>

<p>And then add the following at the end:</p>

<p><pre><code>LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /usr/local/bin/ruby18
NameVirtualHost *:80
&lt;VirtualHost *:80&gt;
    ServerName devtest.example.com
    ServerAlias devtest
    DocumentRoot /usr/local/www/rails/devtest
    &lt;Directory "/usr/local/www/rails/devtest"&gt;
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
    &lt;/Directory&gt;
    RailsEnv "devtest"
&lt;/VirtualHost&gt;
&lt;VirtualHost *:80&gt;
    ServerName uat.example.com
    ServerAlias uat
    DocumentRoot /usr/local/www/rails/uat
    &lt;Directory "/usr/local/www/rails/uat"&gt;
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
    &lt;/Directory&gt;
    RailsEnv "uat"
&lt;/VirtualHost&gt;
</code></pre></p>

<p>Unless you want to use two different servers for the two environments,
you&#8217;ll need to use named virtual hosts, and ask your friendly
administrator to add CNAME records to your DNS server pointing devtest
and uat at the same physical server. They&#8217;ll know what you mean.</p>

<h4>Create a Local User</h4>

<p>You&#8217;ll need a local user on your server. This is the user that will
run the automatic deployments.</p>

<p><pre><code>$ sudo adduser
Username: deploy-robot
Full name: Deployment Robot
Uid (Leave empty for default):
Login group [deploy-robot]:
Login group is deploy-robot. Invite deploy-robot into other groups? []: www
Login class [default]:
Shell (sh csh tcsh zsh nologin) [sh]: 
Home directory [/home/deploy-robot]:
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : deploy-robot
Password   : ****
Full Name  : Deployment Robot
Uid        : 1001
Class      :
Groups     : 
Home       : /home/deploy-robot
Shell      : /usr/local/bin/sh
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (deploy-robot) to the user database.
Add another user? (yes/no): no
Goodbye!
</code></pre></p>

<h4>Deployment Directories</h4>

<p>Set up the directories to hold your applications.</p>

<p><pre><code>$ sudo mkdir -p /usr/local/www/rails/devtest
$ sudo mkdir -p /usr/local/www/rails/uat
</code></pre></p>

<p>These are the web roots for each of the environments, but applications
will not be deployed here. Instead, symlinks will be created from here
to where the applications are actually deployed.</p>

<p><pre><code>$ sudo mkdir -p /usr/local/app/rails/devtest
$ sudo mkdir -p /usr/local/app/rails/uat
</code></pre></p>

<p>These last two directories, and everything under them should be owned
by the deployment user you created above.</p>

<p><pre><code>$ sudo chown -R deploy-robot:www devtest uat
</code></pre></p>

<h4>Gems</h4>

<p>Finally, there are some gems you&#8217;ll need installed on the target
deployment server. Some of these depend on FreeBSD ports.</p>

<p><pre><code>$ cd /usr/ports/comms/ruby-termios
$ sudo make install clean
</code></pre></p>

<p>And then just a couple of gems.</p>

<p><pre><code>$ sudo gem install termios
$ sudo gem install capistrano
</code></pre></p>

<p>And that&#8217;s it for initial server configuration. There will be some
more configuration when first deploying an application.</p>

<h3>Preparing Your Application</h3>

<h4>Capistrano Config</h4>

<p>Capify your application:</p>

<p><pre><code>$ cd app
$ capify .
</code></pre></p>

<p>Edit your capistrano rules in <code>deploy.rb</code>. You&#8217;ll want them to look
something like the following. These rules use no source control
system to get the code. Our continuous integration server takes care
of checking out the code, so it&#8217;s easier to deploy from the local code
copy. And, this way we can be sure each deployment only contains one
changelist.</p>

<p><pre><code># Overall config
set :use_sudo, false
&#35; Application config
set :application, "app-name"
set :default_env, "production"
set :rails_env, ENV['RAILS_ENV'] || default_env
&#35; Deployment source and strategy
set :deploy_to, "/usr/local/app/rails/#{rails_env}/#{application}"
set :deploy_via, :copy
set :scm, :none
set :repository,  "."
&#35; Target servers
set :default_server, "localhost"
set :dest_server, ENV['SERVER'] || default_server
role :app, dest_server
role :web, dest_server
role :db,  dest_server, :primary =&gt; true
&#35; Phusion Passenger specific restart task
namespace :deploy do
    desc "Restart Application"
    task :restart, :roles =&gt; :app do
        run "touch #{current_path}/tmp/restart.txt"
    end
end
</code></pre></p>

<h4>Environment Configuration</h4>

<p>Set up the two new environments for your application.</p>

<p><pre><code>$ cp config/environments/production.rb config/environments/devtest.rb
$ cp config/environments/production.rb config/environments/uat.rb
</code></pre></p>

<p>Somewhere inside both those files you&#8217;ll need to set the
<code>RAILS_RELATIVE_URL_ROOT</code> as the application will be running at a
sub-URI on your server and Rails needs to know that. Something like:</p>

<p><pre><code>ENV['RAILS_RELATIVE_URL_ROOT'] = "/app-name"
</code></pre></p>

<p>The two new environments will also need to be described in your
<code>database.yml</code> file. This of course depends on your specific database
server setup, so I&#8217;ll leave that bit to you.</p>

<h4>Server-side Application Setup</h4>

<p>Apache needs to know about the applications, and there needs to be
symlinks from the web root to the application deployment folder. This
setup only needs to be done once for each application.</p>

<p>To add the application to Apache, edit
<code>/usr/local/etc/apache22/httpd.conf</code> again, and in the <code>VirtualHost</code>
section for the devtest environment, add a line like the following:</p>

<p><pre><code>RailsBaseURI /app-name
</code></pre></p>

<p>Now, set up the symlink:</p>

<p><pre><code>$ ln -s /usr/local/app/rails/devtest/app-name/current/public /usr/local/www/rails/devtest/app-name
</code></pre></p>

<p>And you&#8217;re done with the application configuration.</p>

<h3>Ant Deployment Scripts</h3>

<p>Our company has an in-house continuous integration server. We&#8217;d be too
embarrassed at cocktail parties if we didn&#8217;t have our own. Yes, yes, I
know this is completely ridiculous. And to make it even worse, it only
runs Ant scripts. Sigh. Anyway, here&#8217;s how you make Ant automatically
deploy an application to devtest.</p>

<p>In a file called <code>definitions.xml</code>:</p>

<p><pre><code>&lt;project name="definitions_rake"&gt;
    &lt;macrodef name="rake"&gt;
        &lt;attribute name="app" /&gt;
        &lt;attribute name="target" /&gt;
        &lt;element name="variables" optional="true" /&gt;
        &lt;sequential&gt;
            &lt;exec executable="rake" dir="@{app}" failonerror="true"&gt;
                &lt;arg value="@{target}" /&gt;
                &lt;variables /&gt;
            &lt;/exec&gt;
        &lt;/sequential&gt;
    &lt;/macrodef&gt;
    &lt;macrodef name="capistrano"&gt;
            &lt;attribute name="app" /&gt;
            &lt;attribute name="environment" /&gt;
            &lt;attribute name="task" /&gt;
            &lt;sequential&gt;
                &lt;exec executable="cap" dir="@{app}" failonerror="true"&gt;
                    &lt;env key="RAILS_ENV" value="@{environment}" /&gt;
                    &lt;env key="SERVER" value="${project.server}" /&gt;
                    &lt;arg value="@{task}" /&gt;
                    &lt;arg value="-s" /&gt;
                    &lt;arg value="user=${project.user}" /&gt;
                    &lt;arg value="-s" /&gt;
                    &lt;arg value="password=${project.password}" /&gt;
                &lt;/exec&gt;
            &lt;/sequential&gt;
    &lt;/macrodef&gt;
    &lt;macrodef name="deploy"&gt;
        &lt;attribute name="app" /&gt;
        &lt;attribute name="environment" /&gt;
        &lt;sequential&gt;
            &lt;capistrano app="@{app}" environment="@{environment}" task="deploy:setup" /&gt;
            &lt;capistrano app="@{app}" environment="@{environment}" task="deploy:migrations" /&gt;
        &lt;/sequential&gt;
    &lt;/macrodef&gt;
    &lt;macrodef name="test"&gt;
        &lt;attribute name="app" /&gt;
        &lt;sequential&gt;
            &lt;rake app="@{app}" target="db:migrate" /&gt;
            &lt;rake app="@{app}" target="test" /&gt;
            &lt;rake app="@{app}" target="spec" /&gt;
        &lt;/sequential&gt;
    &lt;/macrodef&gt;
&lt;/project&gt;
</code></pre></p>

<p>Ant macros, while quite insane, are generally a better way to define
new tasks than the complete insanity of trying to write a whole Ant
plugin in Java. These macros define low-level tasks to run <code>rake</code> and
<code>capistrano</code> tasks, and then use these to build up higher level tasks
like test and deploy. All these tasks assume that Ant has been run
from the directory immediately above your Rails app directory.</p>

<p>In a file called <code>project.properties</code>, set your server, user name and
password. Having the password here is unfortunate, but it is a local
account, with limited privileges on an internal server. Your call.</p>

<p><pre><code>user=deploy-robot
password=deploy-robot-password
server=deployment-server
</code></pre></p>

<p>In a file called <code>build.xml</code>:</p>

<p><pre><code>&lt;project name="aegean" default="build"&gt;
    &lt;import file="./definitions.xml" /&gt;
    &lt;property file="project.properties" prefix="project" /&gt;
    &lt;!-- Sample application.
         To add a new application:
         1. Copy the following targets.
         2. Replace 'depot' with your Rails app name.
         3. Add the 'app name' target as a dependency of the target 'build'.
    &lt;target name="depot.deploy.devtest"&gt;
           &lt;deploy app="depot" environment="devtest" /&gt;
    &lt;/target&gt;
    &lt;target name="depot.test"&gt;
           &lt;test app="depot" /&gt;
    &lt;/target&gt;
    &lt;target name="depot" depends="depot.deploy.devtest, depot.test" /&gt;
    --&gt;
    &lt;target name="example.deploy.devtest"&gt;
           &lt;deploy app="example" environment="devtest" /&gt;
    &lt;/target&gt;
    &lt;target name="example.test"&gt;
           &lt;test app="example" /&gt;
    &lt;/target&gt;
    &lt;target name="example" depends="example.deploy.devtest, example.test" /&gt;
    &lt;target name="build" depends="example" /&gt;
&lt;/project&gt;
</code></pre></p>

<p>The large comment block is just helpful for other developers trying to
add another application. From here, to try this out:</p>

<p><pre><code>$ ant
</code></pre></p>

<p>It should run the deployment, and then run the test suites. If that works as you expect, then just configure your continuous integration server to run Ant over that file on every submit.</p>

<p>Hopefully this is of use to someone. Though this is how our
environment is configured, I have written this all from memory, so I
might have missed a critical step somewhere. Please let me know if
there&#8217;s anything that needs to be changed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2008/12/automatic-deployment-for-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading News</title>
		<link>http://www.overwatering.org/blog/2008/12/reading-news/</link>
		<comments>http://www.overwatering.org/blog/2008/12/reading-news/#comments</comments>
		<pubDate>Tue, 02 Dec 2008 10:23:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[comp. sci.]]></category>

		<guid isPermaLink="false">http://www.overwatering.org/blog/2008/12/reading-news/</guid>
		<description><![CDATA[Previously, I&#8217;ve been a Google Reader fan for my RSS news
reading needs. Now that I&#8217;m a proper Apple fan boi with an iPhone and
a MacBook Pro, I&#8217;ve switched to NetNewsWire. Waaay better. The
Google Reader iPhone app was what really drove me away. I&#8217;m probably
going to have to turn off my blog for this, but desktop [...]]]></description>
			<content:encoded><![CDATA[<p>Previously, I&#8217;ve been a <a href="http://www.google.com/reader">Google Reader</a> fan for my RSS news
reading needs. Now that I&#8217;m a proper Apple fan boi with an iPhone and
a MacBook Pro, I&#8217;ve switched to <a href="http://www.newsgator.com/INDIVIDUALS/NETNEWSWIRE/">NetNewsWire</a>. Waaay better. The
Google Reader iPhone app was what really drove me away. I&#8217;m probably
going to have to turn off my blog for this, but desktop applications
are frequently better than web applications. Heresy, I know. Google&#8217;s
iPhone Reader app has two specific problems:</p>

<ol>
<li><p>It refreshes the page after you close a tab. This is pretty
irritating. Particularly if, like me, you only show unread
items. Things disappear while I&#8217;m still reading them. Aargh!</p></li>
<li><p>The big one: they &#8216;mobilize&#8217; web pages. That is, instead of linking
to the original version of every item Google has decided to link to a
rewritten version of the item. Supposedly this version will be more
readable on the iPhone. Well, the iPhone actually has a really good
browser. But they&#8217;ve actually significantly broken something: the
iPhone web browser recognises YouTube URLs and opens them in the
built-in YouTube app. Because the iPhone web browser can&#8217;t play
YouTube movies. The rewriting means that this doesn&#8217;t work. Thank you
Google, thank you.</p></li>
</ol>

<p>Anyway, there is one feature that I miss from Google Reader: sharing
items. But there&#8217;s the whole desktop application thing going on. I&#8217;m
now posting items I would have shared to my Twitter feed:
<a href="http://twitter.com/gga">gga</a>, look for items tagged <code>#feed</code>.</p>

<p>So how do I this? A pretty simple piece of AppleScript:</p>

<p><pre><code>tell application "NetNewsWire"
        set t to title of selectedHeadline
        set u to URL of selectedHeadline
end tell
tell application "Twitterrific"
        post update t &amp; ": " &amp; u &amp; " (#feed)"
end tell
</code></pre></p>

<p>A single click from NetNewsWire and I&#8217;ve posted an item to Twitter. If
you think you might be interested in items I&#8217;ve previously shared,
follow me on Twitter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.overwatering.org/blog/2008/12/reading-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
