<?xml version='1.0' encoding='UTF-8'?>
<!--  If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/  -->
<rss xmlns:media='http://search.yahoo.com/mrss/' version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/'>
<channel>
  <title>Anthony Bailey&apos;s blog</title>
  <link>http://anthonybailey.net/blog</link>
  <description>Anthony Bailey&apos;s blog - LiveJournal.com</description>
  <lastBuildDate>Wed, 29 Apr 2009 23:14:48 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <lj:journal>anthonybailey</lj:journal>
  <lj:journalid>927339</lj:journalid>
  <lj:journaltype>personal</lj:journaltype>
  <image>
    <url>http://l-userpic.livejournal.com/4100127/927339</url>
    <title>Anthony Bailey&apos;s blog</title>
    <link>http://anthonybailey.net/blog</link>
    <width>100</width>
    <height>100</height>
  </image>

<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/36131.html</guid>
  <pubDate>Wed, 29 Apr 2009 23:14:48 GMT</pubDate>
  <title>Review: Anathem</title>
  <link>http://anthonybailey.net/blog/2009/04/29/anathem</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2009-04-29T23:39:32+01:00&quot;&gt;29 April 2009&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Review is in the &lt;a href=&quot;http://creativecommons.org/licenses/publicdomain/&quot; rel=&quot;license&quot;&gt;public domain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://ecx.images-amazon.com/images/I/3138u-EGT5L.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.co.uk/gp/product/1843549166&quot;&gt;
    &lt;cite&gt;Anathem&lt;/cite&gt;
    by &lt;author&gt;Neal Stephenson&lt;/author&gt;
&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;
After the more historic &lt;a href=&quot;http://anthonybailey.net/blog/2009/02/21/the-baroque-cycle&quot;&gt;&lt;cite&gt;Baroque Cycle&lt;/cite&gt;&lt;/a&gt;, Stephenson returns to speculative sci-fi a la &lt;a href=&quot;http://www.amazon.com/Diamond-Age-Neal-Stephenson/dp/0553573314&quot;&gt;&lt;cite&gt;Diamond Age&lt;/cite&gt;&lt;/a&gt;, playing with the parallel evolution of language, culture, and quantum narratives.
&lt;/p&gt;&lt;p&gt;
I enjoyed this a lot. It oddly reminded me of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Riverworld&quot;&gt;&lt;cite&gt;Riverworld&lt;/cite&gt; saga&lt;/a&gt;, but with philosophical ideas rather than characters from history making their cameos against a densely detailed unfolding backdrop and story.
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/36131.html</comments>
  <category>hreview</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/35888.html</guid>
  <pubDate>Sat, 21 Feb 2009 20:42:36 GMT</pubDate>
  <title>Review: The Baroque Cycle</title>
  <link>http://anthonybailey.net/blog/2009/02/21/the-baroque-cycle</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2009-02-21T20:12:49+00:00&quot;&gt;21 February 2009&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.com/gp/series/88340&quot;&gt;
    &lt;cite&gt;The Baroque Cycle&lt;/cite&gt;
    by &lt;author&gt;Neal Stephenson&lt;/author&gt;
&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;
&lt;div&gt;&lt;a href=&quot;http://amazon.com/gp/product/0099410680&quot;&gt;
&lt;img style=&quot;margin-left: 2em&quot; alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://images.amazon.com/images/I/41D7NDBKXTL._SL150_.jpg&quot; /&gt;&lt;/a&gt;
&lt;p&gt;Size matters, here. &lt;cite&gt;The Baroque Cycle&lt;/cite&gt; is something of an epic, at around one million words long. (Workings: &lt;a href=&quot;http://amazon.com/gp/product/0099410680&quot; title=&quot;Quicksilver&quot;&gt;its&lt;/a&gt; &lt;a href=&quot;http://amazon.com/dp/0099410699&quot; title=&quot;The Confusion&quot;&gt;three&lt;/a&gt; &lt;a href=&quot;http://amazon.com/dp/0099463369&quot; title=&quot;The System of the World&quot;&gt;books&lt;/a&gt; end on page numbers 916 + 815 + 886 = 2617 pages * 45 lines/page * 10 words/line = 1.12Mwords, then round down some whitespace.) 
&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;&lt;a href=&quot;http://amazon.com/dp/0099410699&quot;&gt;
&lt;img style=&quot;margin-right: 2em&quot; alt=&quot;book cover&quot; align=&quot;left&quot; class=&quot;photo&quot; src=&quot;http://images.amazon.com/images/I/41835CNPV6L._SL150_.jpg&quot; /&gt;&lt;/a&gt;
&lt;p&gt;The trilogy is a &quot;behind the scenes&quot; saga spanning fifty years of scientific and economic alchemy, featuring characters from the pages of history but centered on three of their peers whose tales escaped the official record.
&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;&lt;a href=&quot;http://amazon.com/dp/0099463369&quot;&gt;
&lt;img style=&quot;margin-left: 2em&quot; alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://images.amazon.com/images/I/51HCQ1966SL._SL150_.jpg&quot; /&gt;&lt;/a&gt;
&lt;p&gt;In many ways this is the 17th/18th century version of the same author&apos;s more contemporary &lt;a href=&quot;http://amazon.com/dp/0060512806&quot;&gt;&lt;cite&gt;Cryptonomicon&lt;/cite&gt;&lt;/a&gt;, with which it shares the above approach, plenty of adventures colored by cryptography and computation, and &lt;a title=&quot;Insert spoiler here...&quot;&gt;more&lt;/a&gt;. However, I found its sprawling scope resulted in less value per page: its three books contain only a little more gold in total than &lt;cite&gt;Cryptonomicon&lt;/cite&gt;&apos;s one. 
&lt;/p&gt;&lt;/div&gt;
&lt;/blockquote&gt;&lt;/div&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/35888.html</comments>
  <category>hreview</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/35797.html</guid>
  <pubDate>Mon, 15 Dec 2008 23:38:46 GMT</pubDate>
  <title>Contacts: Let&apos;s keep all this between ourselves</title>
  <link>http://anthonybailey.net/blog/2008/12/15/lets-keep-all-this-between-ourselves</link>
  <description>&lt;p&gt;
I want to describe how I like contact(s) information on the Net to work.
&lt;/p&gt;
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;
I say &quot;contact(s)&quot; because I have complementary ideas regarding both the contact details for a person, and the details of who their contacts are - you can say &quot;friends&quot; or &quot;social graph&quot; for the latter if you like. To oversimplify: I want the information sources to be distributed, and to delegate to individuals as authorities for their own details. I find that most current technologies don&apos;t share this ideology; however, I can still use them to act in tune with it.
&lt;/p&gt;

&lt;p&gt;
An introductory note: I&apos;m going to talk about people &quot;owning&quot; a web page. What I mean is that they have significant control over the main content of the page, which is published under as permanent an URL as possible. They definitely don&apos;t have to serve the page from their own machine, or from a host that they rent - a page on a social network or in an ISP&apos;s basic web hosting area is fine. The URL can be under someone else&apos;s domain, so long as they have confidence it will last a while. (&lt;a href=&quot;#own_the_domain&quot;&gt;IMHO aside: own the domain.&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
My suggestion about contacts assumes some kind of a homepage/identity baseline: that people own some page that is about them - such as a blog, or a presence on a social network. Their homepage URL is then a decent identifier for their identity online. For bonus points, they can prove that they are the person who owns that page through OpenID, or Facebook Connect, or similar.  All this is standard for many people online already, and it can easily enough be true for anyone else who cares to make it so. 
&lt;/p&gt;

&lt;p&gt;
My stance is that &lt;strong&gt;I want to own my &lt;em&gt;contact&lt;/em&gt; information&lt;/strong&gt; - because I believe I&apos;m best placed to be the central authority it. I want to publish it as a resource located on or somewhere that is discoverable from my homepage, in a standard format. (Until the world stabilizes a bit, probably in multiple formats, all views of the same underlying data.) I&apos;d like others to do the same. It&apos;s up to them exactly which details they publish. If they care to, they can even restrict access to some information, making it &quot;friends only&quot;. (&lt;a href=&quot;#most_privacy_is_squeamish&quot;&gt;IMHO aside: most privacy is squeamish.&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;I also want to own my &lt;em&gt;contacts&lt;/em&gt; information&lt;/strong&gt; - the list of other people that I know. For each of them I want to store and publish a homepage URL, and also a name - given how neither or those identifiers is completely permanent. I also own how I personally would describe my relationship with these people. This perspective need not be reciprocated.
&lt;/p&gt;

&lt;p&gt;
But, &lt;strong&gt;I don&apos;t want to own my &lt;em&gt;contacts&apos;&lt;/em&gt; information&lt;/strong&gt;. I want to delegate that to them! In as much as my contacts list is an address book, it should be so only through indirection: to find out about a contact, go to the homepage I have linked for them, and discover the contact information that they themselves have published there.
&lt;/p&gt;

&lt;p&gt;
Most current systems do not assume such delegation: I am expected to own other people&apos;s contact information, as well as mine. I presume this is a deliberate compromise in order to gain critical mass (of contact details published online in general and on the vendors network in particular.) My own disdain for such practicality comes partly from not finding much need for an address book per se - perhaps if my network(ing) were better this would be otherwise. But, even allowing for that, I don&apos;t see the delegation I desire called out as an ideal or an aspiration anywhere in the design or implementation of current systems. Evangelizing this, and exploring how to get there from here, is the motivation for this and my next blog entry.
&lt;/p&gt;

&lt;p&gt;
There are a two main reasons I want things to work this way. 
&lt;ul&gt;
&lt;li style=&quot;padding-bottom: 1em&quot;&gt;
Firstly, there is the golden rule: if I want to own my contact details, I should should grant other people the right to own theirs.
&lt;/li&gt;
&lt;li&gt;
Secondly, I&apos;d rather not have the hassle of complicating my own records with other people&apos;s details. Let the person who knows best update their information in a single place, and I&apos;ll get their latest details by going there. This also avoids my having to take responsibility for choosing which of their details to publish. Given current preciousness about privacy, this side-steps a potential minefield.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
There is a yet more open approach that I have refrained from advocating. In a truly distributed wiki-wiki-world, one could argue that an individual&apos;s opinions on information about themself should not be sacrosanct - that we should seek a consensus of everyone&apos;s opinions. On most truths, I&apos;m all for this kind of emergence. But when it comes to how to contact an individual I think having them be the single authority is too useful a shortcut, and it may have psychologically benefit, too! Letting the rest of the world speak for those as yet offline, though, could be a decent strategy to cover the gaps between where we are and where I want us to be.
&lt;/p&gt;

&lt;p&gt;
Talking of such strategies: next time I&apos;ll write about my current implementation of the plan I advocate using existing contacts technologies - hCard, XFN, FoaF, PoCo, et al.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
I have some further opinions that are related to the discussion above but would have distracted from its core, so I&apos;ve moved them down here.
&lt;/p&gt;

&lt;p&gt;
&lt;a name=&quot;own_the_domain&quot;&gt;Own the domain&lt;/a&gt;: If you&apos;re going to own a page of significance to you, I would advocate controlling the domain name of the URL you publish it under. By all means have another party host the content, just point your own URL at where the page currently is. That way you can change the service/hosting provider without losing the URL by which people find the page.
&lt;/p&gt;

&lt;p&gt;
&lt;a name=&quot;most_privacy_is_squeamish&quot;&gt;Most privacy is squeamish&lt;/a&gt;: Although many are nervous about publishing it, I think much contact and other &quot;personal&quot; information is most naturally public: going ex-directory is weird. The impact of problems that might arise from publishing e-mail, mailing address or biography is overestimated. You&apos;re getting spam anyway. Stalkers are rare. The existence of the concept of &quot;identity theft&quot; occuring through knowledge of simple everyday facts - like a birthday, a hometown, a mother&apos;s maiden name - is a symptom of immature authentication procedures, a laughable security through not-even-obscurity. Lastly, contact details are useless without at least some users - and &lt;a href=&quot;http://anthonybailey.net/tumblelog/2007/09/30/digital-privacy-management-is-ineffable&quot;&gt;trying to control how others use and copy bits is a mug&apos;s game&lt;/a&gt;.
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/35797.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/35337.html</guid>
  <pubDate>Wed, 22 Oct 2008 19:50:10 GMT</pubDate>
  <title>Review: Implementation Patterns</title>
  <link>http://anthonybailey.net/blog/2008/10/22/implementation-patterns</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2008-10-22T20:21:25+0100&quot;&gt;22 October 2008&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://ecx.images-amazon.com/images/I/51JHn-6oNwL._AA180_.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.com/gp/product/0321413091&quot;&gt;
    &lt;cite&gt;Implementation Patterns (Addison-Wesley Signature Series)&lt;/cite&gt;
    by &lt;author&gt;Kent Beck&lt;/author&gt;
&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;
This book concerns the detailed choices we make minute-to-minute when implementing programs.
&lt;/p&gt;&lt;p&gt;
The first twenty pages express Beck&apos;s context and motivation in his usual fashion: some personal history and philosophy, some thoughts on cost, and a prioritized set of values (communication, simplicity and flexibility) and some principles (DRYness, symmetry, preferring declarative to procedural expression, plus three ways to group things that change together) that help in translating those values into specific practices or patterns.
&lt;/p&gt;&lt;p&gt;
The next hundred pages is a catalog of seventy-seven such patterns.
&lt;/p&gt;&lt;p&gt;
Two closing chapters offer an overview of collections, and sketch some ideas of how things change if you&apos;re coding a framework rather than a specific application.
&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;
I think those first twenty pages are excellent. Two of my previous favorite books by Beck outlined a core precept, asked &quot;what if we run with it?&quot;, then detailed how to extract far more value than you might initially expect. (To over-simplify: &lt;a href=&quot;http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658&quot;&gt;&lt;cite&gt;XP Explained&lt;/cite&gt;&lt;/a&gt; follows from keeping the cost-of-change curve as flat as possible, &lt;a href=&quot;http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530&quot;&gt;&lt;cite&gt;Test-Driven Development&lt;/cite&gt;&lt;/a&gt; follows from a belief that making code testable improves its design.)
&lt;/p&gt;&lt;p&gt;
The main idea in &lt;cite&gt;Implementation Patterns&lt;/cite&gt; is that making code readable is key in good implementation, and that turning those dials to eleven will provide similar unexpected insight. (For example: given that a good name for a variable describes its role in context, then if all good names seem long, you&apos;re probably missing an abstraction of context - i.e. there&apos;s a class waiting to be extracted.) Not quite as big an idea as in the other two books, but very plausible, and my appetite was whetted for the patterns where I hoped this idea, and all the values and principles, would be explored and discussed in context.
&lt;/p&gt;&lt;p&gt;
Alas, no. I was very disappointed. (The above was about the only example I could find.) There was very little exploration and discussion, and the patterns did not often refer back to the values and principles, even implicitly.
&lt;/p&gt;&lt;p&gt;
OK, since it doesn&apos;t build sufficiently on the introduction&apos;s abstractions, the meat of the book had better work well as a stand-alone catalog of patterns. 
&lt;/p&gt;&lt;p&gt;
Alas, a second no. One of the useful things explicit lists of patterns do is to give a name to a concept so we can communicate about it. Beck&apos;s list does do this useful thing. But, that is about the only useful thing it does. Once named, there is rarely additional insight in the pattern descriptions: they mostly do exactly what they say on the tin. You can read the &lt;a href=&quot;http://safari.oreilly.com/9780321413093?tocview=true&quot;&gt;table of contents&lt;/a&gt; to see how simple the concepts under discussion are.
&lt;/p&gt;&lt;p&gt;
The last two chapters are fine, but unremarkable.
&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;
My recommendation: borrow the book to read the material preceding the catalog. Then buy and read &lt;a href=&quot;http://anthonybailey.net/blog/2008/09/03/clean-code&quot;&gt;&lt;cite&gt;Clean Code&lt;/cite&gt;&lt;/a&gt;.
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/35337.html</comments>
  <category>software_development</category>
  <category>hreview</category>
  <lj:mood>disappointed</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/35207.html</guid>
  <pubDate>Sun, 19 Oct 2008 21:04:04 GMT</pubDate>
  <title>Minimal OpenID glue for Rails authentication</title>
  <link>http://anthonybailey.net/blog/2008/10/19/minimal-openid-glue-for-rails-authentication</link>
  <description>&lt;p&gt;
The Rails framework and culture offer a well-developed set of plug-ins and patterns for the authentication of users and the authorization of their actions. These are great for more sophisticated enterprise and social applications - but as a hobbyist, my own apps don&apos;t tend to need a database full of users and roles. Typically &lt;strong&gt;the only user I care about authenticating is me&lt;/strong&gt;, for write access to content that everyone else should view read-only without any hassle. I want something very &lt;strong&gt;lightweight&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
The app behind &lt;a href=&quot;http://anthonybailey.net&quot;&gt;my ego site&lt;/a&gt; is a good example. It presents pages based on a few sets of resources - contacts, and various flavors of &lt;a href=&quot;http://anthonybailey.net/tumblelog/2007/10/27/permanent-obsession&quot;&gt;permalinks for blog entries which are hosted elsewhere&lt;/a&gt;. Everybody should be able to access those pages. Behind the scenes there is some simple scaffolding for managing the resources. Only I should be accessing those.
&lt;/p&gt;

&lt;p&gt;
The simplest solution is security through obscurity - to keep quiet about the management URLs. It&apos;s not &lt;em&gt;that&lt;/em&gt; bad an approach for a low-stakes app, and I did rely on it for a while. Felt wrong, though.
&lt;/p&gt;

&lt;p&gt;
Having decided to do better, I still wanted to keep things as lightweight as I could. My first preference is to &lt;strong&gt;minimize the use of the Rails session&lt;/strong&gt;: I don&apos;t want people who visit my public pages to get lumbered with a pointless cookie, so I switch sessions off by default.
&lt;/p&gt;

&lt;p&gt;
One way to keep authenticated session management out of the way of users and apps is to &lt;strong&gt;place it in the HTTP layer&lt;/strong&gt;. I am a big fan of the &lt;a href=&quot;http://dev.rubyonrails.org/browser/plugins/http_authentication&quot;&gt;http_authentication&lt;/a&gt; Rails plug-in. The browser on the client side takes care of the session sign-on UI and state, getting users to log in once on first access to protected pages. In your app, you can use a before_filter with implementation as simple as: 
&lt;hr /&gt;&lt;b&gt;
&lt;pre&gt;authenticate_or_request_with_http_basic &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;do&lt;/span&gt; |ignore_user, password|
  password == &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;your secret&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/b&gt;&lt;hr /&gt;
&lt;/p&gt;

&lt;p&gt;
But, I have a second preference. &lt;strong&gt;I don&apos;t want arbitrary secrets in my apps, or in my brain.&lt;/strong&gt; I want single sign-on, please, and my web app just needs to know that I am who I say I am - let someone else do the verification of that identity. And I am already &lt;a href=&quot;http://anthonybailey.net/tumblelog/2007/12/09/open-id&quot;&gt;enthusiastic about a technology for authenticating identity&lt;/a&gt; in this way - it&apos;s &lt;strong&gt;&lt;a href=&quot;http://openid.net&quot;&gt;OpenID&lt;/a&gt;&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Following a &quot;gem install &lt;a href=&quot;http://openidenabled.com/ruby-openid&quot;&gt;ruby-openid&lt;/a&gt;&quot;, I still wanted as little Rails glue as possible. The &lt;a href=&quot;http://agilewebdevelopment.com/plugins/openidauthentication&quot;&gt;open_id_authentication&lt;/a&gt; plug-in is pretty compact given its power, but it does tend to assume that users will live in the database, and it provides all kinds of store machinery that I don&apos;t need.
&lt;/p&gt;

&lt;p&gt;
So I cut non-essentials away from the plug-in source and ended up with this &lt;strong&gt;minimal parent for my resource controllers&lt;/strong&gt;.
&lt;/p&gt;

&lt;hr /&gt;&lt;b&gt;
&lt;pre&gt;require &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;openid/consumer&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06; font-weight:bold&quot;&gt;ResourceProtectingController&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span style=&quot;color:#369&quot;&gt;@@PROTECTED_ACTIONS&lt;/span&gt; = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;%w(&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;new create edit update destroy&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  session &lt;span style=&quot;color:#A60&quot;&gt;:disabled&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;false&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:only&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#369&quot;&gt;@@PROTECTED_ACTIONS&lt;/span&gt;
  before_filter &lt;span style=&quot;color:#A60&quot;&gt;:protect&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:only&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#369&quot;&gt;@@PROTECTED_ACTIONS&lt;/span&gt;

  protected
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B; font-weight:bold&quot;&gt;protect&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; session[&lt;span style=&quot;color:#A60&quot;&gt;:authenticated&lt;/span&gt;]
    realm = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: #eee&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;#{&lt;/span&gt;request.protocol + request.host_with_port&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    requested_url = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: #eee&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;#{&lt;/span&gt;realm + request.relative_url_root + request.path&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    identity_url = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;http://anthonybailey.net&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    consumer = &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;OpenID&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Consumer&lt;/span&gt;.new(session, &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;nil&lt;/span&gt;)
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; params[&lt;span style=&quot;color:#A60&quot;&gt;:open_id_complete&lt;/span&gt;].nil?
      open_id_request = consumer.begin(identity_url)
      open_id_request.return_to_args[&lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;open_id_complete&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;] = &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
      redirect_to(open_id_request.redirect_url(realm, requested_url))
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;else&lt;/span&gt;
      returned_params = params.reject {|k, v| request.path_parameters[k] }
      returned_params.delete(&lt;span style=&quot;color:#A60&quot;&gt;:format&lt;/span&gt;)
      open_id_response = consumer.complete(returned_params, requested_url)
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;if&lt;/span&gt; open_id_response.status != &lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;OpenID&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;Consumer&lt;/span&gt;::&lt;span style=&quot;color:#036; font-weight:bold&quot;&gt;SUCCESS&lt;/span&gt;
        render &lt;span style=&quot;color:#A60&quot;&gt;:text&lt;/span&gt; =&amp;gt; &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Forbidden: got &lt;/span&gt;&lt;span style=&quot;background: #eee&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;#{&lt;/span&gt;open_id_response.class&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; +
                        &lt;span style=&quot;background-color:#fff0f0&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;on claiming &lt;/span&gt;&lt;span style=&quot;background: #eee&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;#{&lt;/span&gt;identity_url&lt;span style=&quot;font-weight: bold; color: #888&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:status&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#00D; font-weight:bold&quot;&gt;401&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;else&lt;/span&gt;
        session[&lt;span style=&quot;color:#A60&quot;&gt;:authenticated&lt;/span&gt;] = &lt;span style=&quot;color:#038; font-weight:bold&quot;&gt;true&lt;/span&gt;
      &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
    &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080; font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/b&gt;&lt;hr /&gt;

&lt;p&gt;
Some notes on the implementation:
&lt;ul&gt;
&lt;li&gt;Because OpenID involves a stateful request dance between the relying party and the identity provider, I had to reintroduce the Rails session. However, I can still keep cookies away from the public by only enabling it for the actions needing protection.&lt;/li&gt;
&lt;li&gt;Now I have a session, I ensure that only one dance is required, by stashing the authenticated status. This also works around the fact that OpenID can only return using the GET method: in regular use the client will GET a prelude page before it needs to POST, etc. a real change, at which point we&apos;ve finished dancing with the provider.&lt;/li&gt;
&lt;li&gt;Mostly as a conceptual indulgence, I left the read-only actions &lt;em&gt;unprotected&lt;/em&gt;. (To keep things GET-first, I moved scaffolding UI to delete resources off index pages and onto edit pages - but I kind of feel that&apos;s where it should be anyway.)
&lt;li&gt;Since if you&apos;re not me, you&apos;re not supposed to be here, I didn&apos;t friendly-up the content when access fails.&lt;/li&gt;
&lt;li&gt;Finally, as an aside, it amuses me that my identity URL actually &lt;em&gt;is&lt;/em&gt; the domain of the URLs I&apos;m protecting. (I don&apos;t run my own identity server, mind - I delegate.)
&lt;/ul&gt;

&lt;/p&gt;</description>
  <comments>http://anthonybailey.livejournal.com/35207.html</comments>
  <category>software_development</category>
  <category>rails</category>
  <lj:security>public</lj:security>
  <lj:reply-count>11</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/35069.html</guid>
  <pubDate>Wed, 01 Oct 2008 23:07:23 GMT</pubDate>
  <title>Review: Little Brother</title>
  <link>http://anthonybailey.net/blog/2008/10/01/little-brother</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2008-10-02T00:00:01+0100&quot;&gt;02 October 2008&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://ecx.images-amazon.com/images/I/514nirdG7IL._SL200_.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://craphound.com/littlebrother&quot;&gt;
    &lt;cite&gt;Little Brother&lt;/cite&gt;
    by &lt;author&gt;Cory Doctorow&lt;/author&gt;
&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;
This is a fun coming-of-age adventure telling a very contemporary tale of tech-savvy teenage righteous rebellion against a police state.
&lt;/p&gt;&lt;p&gt;
The plot is straightforward in the large, but the formula is well-executed, is written in a convincing voice, and features wonderful details. Doctorow regularly writes apparently futuristic science-fiction simply by basing his fiction on today&apos;s cutting edge, and the edge cuts keenly in this book - the politics and technologies are all here today or grown tomorrow.
&lt;/p&gt;&lt;p&gt;
I read the &lt;a href=&quot;http://craphound.com/littlebrother/download/&quot;&gt;free CC-licensed download&lt;/a&gt;, as I did with one of his previous &lt;cite&gt;Eastern Standard Tribe&lt;/cite&gt; - and the business model of this publishing approach (of which Doctorow is one of the earliest adopters and most passionate proponents) proves itself again: I&apos;ve just ordered &lt;a href=&quot;http://www.amazon.co.uk/Little-Brother-Cory-Doctorow/dp/0007288425&quot;&gt;a copy of the just released UK paperback&lt;/a&gt; to send as geek propaganda to my own &lt;a href=&quot;http://www.facebook.com/profile.php?id=774550437&quot;&gt;younger sibling&lt;/a&gt;.
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;</description>
  <comments>http://anthonybailey.livejournal.com/35069.html</comments>
  <category>hreview</category>
  <lj:mood>rejuvenated</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/34636.html</guid>
  <pubDate>Wed, 03 Sep 2008 19:43:22 GMT</pubDate>
  <title>Review: Clean Code</title>
  <link>http://anthonybailey.net/blog/2008/09/03/clean-code</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2008-09-01T18:37:18+0100&quot;&gt;01 September 2008&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://images.amazon.com/images/P/0132350882.01.THUMBZZZ.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.com/gp/product/0132350882&quot;&gt;
    &lt;cite&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/cite&gt;
    by &lt;author&gt;Robert C. Martin&lt;/author&gt;
&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;
I wouldn&apos;t usually have cared to read yet another book on the generics of good programming practice. But this one was by Bob Martin, &quot;Uncle&quot; of the first family of thoughtful contemporary coding, and whose &lt;a href=&quot;http://blog.objectmentor.com/articles/category/uncle-bobs-blatherings&quot;&gt;blog&lt;/a&gt; is high on my roll.
&lt;/p&gt;&lt;p&gt;
The book claims to be unusually hard work due to the substantial amount of code it contains. I disagree - you certainly want to dive deep into the examples, but I&apos;ve read plenty of texts containing more code and less value. (Although, for a book that encourages reading code, and that argues for the retirement of outdated formatting conventions, I am frankly mystified by the &lt;a href=&quot;http://anthonybailey.net/blog/2005/11/15/monospace-culture&quot;&gt;fixed-width&lt;/a&gt;, unhighlighted, vanishingly thin font used to present the examples: there might as well be tractor holes down both sides of the print-out.)
&lt;/p&gt;&lt;p&gt;
Martin makes the pragmatic simplifying choice of presenting everything in Java. That&apos;s fine; apart from some concurrency specifics, most of what is promoted will slip easily back and forth to e.g. C++ and Ruby - and if you can make Java pleasant to read, you&apos;ve earned my respect.
&lt;/p&gt;&lt;p&gt;
After an introduction featuring great abstract definitions of cleanliness from the near-godly, we get twelve solid chapters of concrete advice. An account of best practice should not be surprising to a decent practitioner - and I found much of &lt;cite&gt;Clean Code&lt;/cite&gt; to be a reassuring mix of the obvious (&quot;oh, I already know &lt;strong&gt;that&lt;/strong&gt;&quot;) and the nicely crystallized (&quot;oh, &lt;strong&gt;that&lt;/strong&gt;&apos;s what I already know&quot;.) &lt;abbr title=&quot;Test-Driven Development&quot;&gt;TDD&lt;/abbr&gt;, culling comments, careful naming, ultra-&lt;abbr title=&quot;Don&amp;#39;t Repeat Yourself&quot;&gt;DRY&lt;/abbr&gt;, breaking dependencies, small methods, yada yada yada.
&lt;/p&gt;&lt;p&gt;
There&apos;s also sufficient challenge (&quot;oh, you&apos;re going to push it that far?&quot;) and controversy (&quot;er, wtf? maybe...&quot;) to keep it interesting. Uncle Bob is illuminatingly obsessive about the law of Demeter and the single responsibility and open/closed principles. He particularly surprised me with his enthusiasm for keeping plain old data structures around within the object-oriented world. 
&lt;/p&gt;&lt;p&gt;
But the three large case studies that close the book are the real gold here - the summary list of smells drawn from them is no substitute for their glorious, odorous detail. They are very engaging: despite their final shininess, I bet you too will want to polish them a little further.
&lt;/p&gt;&lt;p&gt;
Recommended.
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/34636.html</comments>
  <category>software_development</category>
  <category>hreview</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/34471.html</guid>
  <pubDate>Sun, 20 Jul 2008 16:08:40 GMT</pubDate>
  <title>Review: Bulletproof Web Design</title>
  <link>http://anthonybailey.net/blog/2008/07/20/bulletproof-web-design</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;

&lt;ul style=&quot;display:none&quot;&gt;

&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;

&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2008-07-20T16:39:55+0100&quot;&gt;20 July 2008&lt;/abbr&gt;

by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;

&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;img alt=&quot;book cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://ecx.images-amazon.com/images/I/51KQNCvs0EL._SL200_.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.com/gp/product/0321346939&quot;&gt;

   &lt;cite&gt;Bulletproof Web Design: Improving flexibility and protecting against worst-case scenarios with XHTML and CSS&lt;/cite&gt;

   by Dan Cederholm

&lt;/a&gt;

&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;

This is a slim (270 spacey pages) primer on robust &lt;abbr title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;/abbr&gt; practice. It isn&apos;t a reference book, nor really a compendium of recipes; more a set of ransackable case studies through which runs a persuasive essay on how and why to do this stuff right. (The basic precept is a principled separation of concerns: define style for mark-up that is independently semantically sound, rather than hacking div after nested div into your page in order to kludge your target design.)
&lt;/p&gt;&lt;p&gt;
I bought it a couple of years ago to learn how to do CSS-based layout, and did so by coding through many of the examples. I recently read it through a second time and was again impressed by its clarity and cohesion, and by how its elegant solutions do not sacrifice practicality - hence this review and recommendation. (And apart from a few thankfully obsolete IE5-generation workarounds, the content had not dated at all: though it preaches graceful degradation, the book hasn&apos;t yet had to practise it.)
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;(If it seems strange that I broke blog silence this way - yes, usually I&apos;d put such a brief piece on &lt;a href=&quot;http://anthonybailey.net/tumblelog&quot;&gt;my tumblelog&lt;/a&gt;, but Tumblr eats the &lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; mark-up.)&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/34471.html</comments>
  <category>software_development</category>
  <category>hreview</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/34156.html</guid>
  <pubDate>Mon, 14 Apr 2008 00:06:30 GMT</pubDate>
  <title>What does BDD offer TDD die-hards?</title>
  <link>http://anthonybailey.net/blog/2008/04/14/what-does-bdd-offer-tdd-die-hards</link>
  <description>&lt;blockquote&gt;
&quot;As a &lt;var&gt;long-serving test-driven developer&lt;/var&gt;, I want to &lt;var&gt;understand how behavior-driven development differs&lt;/var&gt;, so that &lt;var&gt;I can decide whether or not to join the revolution&lt;/var&gt;.&quot;
&lt;/blockquote&gt;

&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;
A couple of years ago I was developing medical imaging software for diagnostic radiologists. The field exhibited an archetypal divide between non-coding experts who knew lots about the domain, and developers who did not. In the language of classical XP, we were coding from requirements supplied by a customer. Without a map, we explored many aspects of the customer/testing/developer relationship:
&lt;ul&gt;
&lt;li&gt;the importance of a ubiquitous language spoken across the whole team&lt;/li&gt;
&lt;li&gt;the connection between a spec and an executable test&lt;/li&gt;
&lt;li&gt;the automation of customer-written acceptance tests&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
Very near the end of that time, I attended &lt;a href=&quot;http://xpday5.xpday.org/&quot;&gt;XP Day 5 in London&lt;/a&gt;. Whilst there I talked some with &lt;a href=&quot;http://sirenian.livejournal.com/&quot;&gt;Elizabeth Keogh&lt;/a&gt;, who was assisting &lt;a href=&quot;http://dannorth.net/&quot;&gt;Dan North&lt;/a&gt; with the birth of &lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior_Driven_Development&quot;&gt;Behavior Driven Development&lt;/a&gt;. It sounded fascinating and &lt;em&gt;very&lt;/em&gt; relevant.
&lt;/p&gt;

&lt;p&gt;
But it became less of an immediate concern, because soon after I changed jobs. I moved to a new language and test suite in the context of a (simpler) domain and a culture where the devs were encouraged to internalize the expert/customer role.
&lt;/p&gt;

&lt;p&gt;
Now, over the past couple of years the BDD meme and tools have been surging in popularity. Meanwhile I&apos;m working well in a classical Test-Driven Development place some indeterminate distance away, catching occasional glimpses in my peripheral vision of what looks like a pleasant enough image in a slightly warped fun-house mirror, and trying to work out how the reflection differs.
&lt;/p&gt;

&lt;p&gt;
A couple of months back &lt;a href=&quot;http://tomtenthij.co.uk/&quot;&gt;Tom ten Thij&lt;/a&gt; gave &lt;a href=&quot;http://tomtenthij.co.uk/2008/1/25/rspec-plain-text-story-runner-on-a-fresh-rails-app&quot;&gt;a great BDD introduction&lt;/a&gt; at our &lt;a href=&quot;http://rubaidh.com/scotrug&quot;&gt;local Ruby Users Group&lt;/a&gt;. But he had to handle heckling from many of the audience who met the following spec:
&lt;dl&gt;
&lt;dt&gt;Given&lt;/dt&gt;
&lt;dd&gt;I&apos;m a software developer who loves TDD and communicating well with customers,&lt;/dd&gt;
&lt;dt&gt;When&lt;/dt&gt;
&lt;dd&gt;I hear a talk on BDD that seems to promise exactly what I get from TDD and good customer communication,&lt;/dd&gt;
&lt;dt&gt;Then&lt;/dt&gt;
&lt;dd&gt;I find myself wondering exactly what all the fuss is about.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;

&lt;p&gt;
I took the question back to Liz, and she had interesting things to say. I hope sometime she may write them up properly herself, but in the meantime she said it would be fine if I wrote something. So, here&apos;s an &lt;i&gt;[edited]&lt;/i&gt; transcript of parts of the e-mail conversation we had.
&lt;/p&gt;


&lt;h4&gt;Context&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
Yesterday at our local Ruby User Group here in Edinburgh we had a
presentation on RSpec and on BDD in general. The talk presented BDD from
first principles rather than assuming previous TDD experience. The
audience was mostly TDD old-timers, so a lot of the talk seemed like an
very familiar tale told in slightly different dialect.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
Our fuzzy consensus was acceptance that BDD is a nicer syntax; its
language is a better fit for the good things that test/spec-driven
development tries to do and hence the way it should be done from first
principles - but, is the change worth it for TDD die-hards who have
already completely internalized xUnit? What else do we get?
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
We realized none of us had ever come across a talk or article
evangelising BDD which particularly spoke to us; for example, by a
someone who&apos;d been very dedicated acolyte of TDD and had many wonderful
things to report once they&apos;d learned to Behave.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
I can&apos;t think of anything off the top of my head that addresses TDD gurus,
which is awful, because we should have sorted this out ages ago. Let me see
if I can help - please let me know if this is any use!
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
I&apos;ll devil&apos;s advocate some.
Personally, I&apos;m a big believer in the importance of language &lt;i&gt;[and]&lt;/i&gt;
I&apos;m simply not experienced enough to make any claim of
having seen it all before &lt;i&gt;[but]&lt;/i&gt;
I&apos;ll proxy for my peers who have been doing/teaching TDD for donkey&apos;s
years.
&lt;/p&gt;


&lt;h4&gt;Philosophy&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
BDD isn&apos;t just about reworking the syntax of testing, though it started out
that way. It&apos;s evolved into something more; a language of examples that&apos;s
relevant at both a unit and system level, which allows better communication
with the business, and less redundant code.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
DDD &lt;i&gt;[Domain-Driven Design]&lt;/i&gt; provides the nouns, verbs and adjectives,
and BDD provides all the other
words which let you make sentences out of them. (Dan North, Eric Evans and I
were chatting about this at OOPSLA; I can&apos;t remember the exact words they
used, but this is close.)
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
It&apos;s all about the language. You don&apos;t really get anything else... but
language is pretty powerful! Changing the words we use can change the way we
think, and we don&apos;t have to change our technology to do it.
&lt;/p&gt;


&lt;h4&gt;Territorial dispute&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
TDD is mostly about development - about taking a specification or acceptance
criteria, at either a system or unit level, and making the associated tests
pass. BDD assumes that it&apos;s not easy to get the right acceptance criteria in
the first place, so the language - including the famous &quot;should&quot; - is designed
to allow the original assumptions about the behaviour of the system to be
questioned; to have discussions about that behaviour without having to
translate from the technical world, either in speech (which helps us devs
talk to BAs and the business) or mentally (which helps us realise when we
need to ask a question). Of course, this is very closely aligned with DDD.
It&apos;s also why I prefer &quot;behaviour&quot; to &quot;spec&quot;; because it&apos;s easier to question
behaviour than a specification.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
I disagree with this characterization. Particularly at the lower levels
where the developer may be doing more of the work than the domain
expert, traditional TDD is very much about exploring and evolving the
behaviour of a system, one test at a time, asking questions rather than
blindly coding up an existing design or specification.
I completely buy the idea that the language of BDD helps make the
openness to change explicit, though.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
The best TDDers do BDD already, at least at a unit level. It&apos;s possible that
they don&apos;t think of elements of code as stakeholders, though; at least, I
haven&apos;t found any native TDDers with that mindset. It changes the names of
classes, at the very least. I am also aware that some die-hard, expert TDDers
concentrate more on the technology when they&apos;re teaching than the
conversations around tests.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
It helps my understanding if I consider BDD to
be taking a concept of TDD that fits particularly well with driving from
behaviors, and turning the dials on that concept up to ten. If not plain
wrong, this characterization may play well with an old guard XP/TDD
target audience.
&lt;/p&gt;


&lt;h4&gt;Frameworks&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
First off, let me put to rest something really important:
You can do BDD in xUnit.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
would you go so far as to say that if you aren&apos;t
starting from scratch there may not sufficient advantage to switch from
xUnit to a more well-Behaved framework even if one falls for BDD in a
big way?
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
Don&apos;t use JBehave. It&apos;s a great teaching tool, but sucks IRL. I tend to use
JUnit. JBehave 2.0 should (when it eventually comes out) be easier. It&apos;s
going to be more like RSpec&apos;s plain text story runner, and consist of a lot
of JUnit exensions.
&lt;/p&gt;


&lt;h4&gt;Talking to business&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
&lt;i&gt;[BDD offers]&lt;/i&gt; a language of examples that&apos;s relevant at both a unit
and system level, which allows better communication with the business
We use the word &apos;scenario&apos; or &apos;example&apos; because you don&apos;t go to the business
and say &apos;Give me an acceptance test&apos;. You say &apos;Give me an example&apos; or &apos;Give
me a scenario where that happens&apos;.
It becomes easier to maintain acceptance tests - and they become
human-readable!
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
Would you venture further? Non-developers can edit the acceptance test?
Non-developer can write the test when paired with developer as
translator? Non-developer can even write the test unambiguously without
direct developer assistance, given some further translation layer like a
plain-text story runner?
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
Absolutely. This has worked very well with our QAs.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
The last was a feature of the talk I attended. It drew attention from
the old TDD guard, who were all very XP-story-focussed and some of whom
had developed such translation layers themselves. It provoked both a
&quot;these BDD people sure have the right idea&quot; response as well as a &quot;and
it&apos;s an idea we had a while back, and is separable from the question of
changing terminology at the xUnit level&quot; one.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
Good. &quot;Should&quot; is trivial compared with the given / when / then language.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
Partly putting words in their mouths, and partly exploring something I
thought might be interesting: if you do end up with another layer
between the non-developer and the runnable test/behavior/spec - and our
experience is that perhaps this is worthwhile - then some of the
communication advantages of using BDD at the bottom layer are diluted.
If you have to use a translation
layer like a story runner to pre-process a more plain text description
of behavior, then using BDD terminology in the target code doesn&apos;t help
you so much with respect to communicating with the non-developer,
because they don&apos;t see that code, they see the source story. At that
point the BDD communication argument perhaps reduces to the DDD one
(albeit one I buy) that using business language as much as possible in
the code itself is worthwhile even when only the developer sees it.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
I guess I was wondering whether you&apos;d challenge the pre-condition - can
one make behaviors expressed in the production code language
sufficiently like plain English to be writeable by the non-developer?
(Perhaps it depends on the language?)
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
RSpec&apos;s stories now work in plain English. We hope JBehave 2.0&apos;s will be the
same. It&apos;s a nice little given / when / then DSL.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
I guess my point was that some long-time TDDers have so internalized
some of the translations from dev-centric terminology to plain English,
that they might consider a test very easy to read way before the
non-developers do. But purging such language habits would probably ease
indigestion nevertheless. And if BDD terminology becomes the standard,
there&apos;s also a communication benefit &lt;strong&gt;amongst&lt;/strong&gt; developers - the next
wave may well see &lt;code&gt;TestCase&lt;/code&gt;/test/assert as strange dinosaur language.
&lt;/p&gt;


&lt;h4&gt;Outside-in&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
&lt;i&gt;[The BDD spec]&lt;/i&gt; leads to the first piece of code which the human stakeholders need,
which is the UI - the mechanism through which users (or 3rd party apps, say)
interact with our system, and through which behaviour is perceived. So this
is how we develop with BDD - from the outside-in.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
This was a part of BDD missing from the talk we heard, and it sounds
interesting. 
I enjoyed your &lt;a href=&quot;http://sirenian.livejournal.com/42871.html&quot;&gt;real life example&lt;/a&gt;.
&lt;i&gt;[Re TDD]&lt;/i&gt; with &quot;the YAGNI of outside-in&quot; - whilst YAGNI itself is a TDD
cornerstone, I haven&apos;t heard the tenet that therefore one should always
start with the user interface layer.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
If you don&apos;t start with the interface, how do you know that you need it? How
do you know that the stakeholder code will be able to use what you&apos;re writing
in the way that you&apos;re writing it? You can pretend that you already have the
code, work out how you&apos;re going to use it, then code the real thing later -
this is exactly what we do with TDD anyway! Now we&apos;re taking that pattern
into production code too.
&lt;/p&gt;


&lt;h4&gt;Code has needs too!&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
We use the same language of examples, to describe behaviour that provides
some benefit, at both a unit and a system level. The stakeholder at a unit
level becomes the other piece of code which needs that behaviour - so unless
we have some code already, we can&apos;t start.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
This analogy between human and code clients is not one I&apos;d heard
advanced quite so strongly in this context - is it important to BDD?
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
Yes!
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
&lt;i&gt;[In TDD]&lt;/i&gt; this definitely isn&apos;t an angle I&apos;ve
seen pushed hard. Trying to make client use of the new code readable,
sure, but not the kind of anthropomorphism you&apos;re advocating.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
I&apos;m not thinking of the stakeholders as human, as such, though it&apos;s a good
analogy - code changes just as much as people do! BDD is very need-driven.
Why are you coding that? Who&apos;s it for? What is going to benefit from that
line of code? It changes the names of classes, at the very least.
&lt;i&gt;[...]&lt;/i&gt;
We&apos;ve started naming things based on the responsibility to its stakeholder,
or its job, instead of the design pattern. As an example, we&apos;ve started
calling repositories after the plurals of whatever you get out of them - so,
&quot;&lt;code&gt;Puzzles&lt;/code&gt;&quot; for my sudoku creator, as opposed to
&quot;&lt;code&gt;PuzzleRepository&lt;/code&gt;&quot;.
&lt;/p&gt;


&lt;h4&gt;Given/Then, When&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;Ant&lt;/b&gt;: 
Random aside... is it perhaps the case that most mocking layers for
xUnits (at least in languages that don&apos;t love closures) make given/when/then
expression harder? It seems that expressing the expectations of mocks
should go in the &quot;then&quot; section, but they usually assume they&apos;ll be set
up before you execute the code under test within the &quot;when&quot; section.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Liz&lt;/b&gt;: 
Check this new toy out: &lt;a href=&quot;http://mockito.googlecode.com/&quot;&gt;Mockito&lt;/a&gt;
My friend Szczepan Faber made it, based on EasyMock. It doesn&apos;t make you set
up any expectations unless you need something to return (eg: given three
fridges in stock). Instead, you get to ask it afterwards whether the
interactions needed happened. No &lt;code&gt;finishedRecording()&lt;/code&gt;, and it&apos;ll automatically
return null, 0 etc. if you haven&apos;t set up a particular stub.
&lt;/p&gt;


&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;
Well, I hope you found that as interesting as I did.I&apos;d love it if the &quot;TDD old guard&quot; (who I&apos;ve quite possibly
misrepresented) could comment below to take the conversation further...
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/34156.html</comments>
  <category>software_development</category>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/33958.html</guid>
  <pubDate>Mon, 04 Feb 2008 23:16:51 GMT</pubDate>
  <title>Credits where credits due</title>
  <link>http://anthonybailey.net/blog/2008/02/04/credits-where-credits-due</link>
  <description>(A &lt;a href=&quot;http://worldofmongoose.blogspot.com/2008/02/do-credits-on-tv-matter.html&quot;&gt;piece about TV credits on Mongoose World&lt;/a&gt; caused in turn by &lt;a href=&quot;http://news.bbc.co.uk/1/hi/entertainment/7222679.stm&quot;&gt;this piece from the BBC&lt;/a&gt; provoked a rant from me on that subject and particularly how it relates to machinima. &lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;It seems to have broken my writer&apos;s block, so I&apos;ve copied/pasted/edited it here.)&lt;br /&gt;&lt;br /&gt;Full screen credits on plain old broadcast television might still be reasonable, because how else do you get the information? But that medium is increasingly dead. We shall speak of it no more.&lt;br /&gt;&lt;br /&gt;Full screen credits on TV as we increasingly watch it (DVR, DVD, IP) seem anomalous. Pack them into an information burst: if I want to read them, I&apos;ll pause and advance through individual frames. If I&apos;m on a smart device, put the credits in metadata I can browse with that device. If the device is Net-enabled, put them on a page I can navigate to from the program. Don&apos;t make me sit through this stuff. Brand a little if you must, but if I care about obscure details, I&apos;ll seek out the information, and be very happy to read much more than you could cram into the credit footage.&lt;br /&gt;&lt;br /&gt;Full screen credits in typical machinima (and other YouTube-length pieces) are a sign the medium is far too indebted to its older media parents, and is too slavishly following their inappropriate conventions. See above: viewer is almost certainly watching on a Net-enabled device. And a minute of credits on a five minute piece is a real tax on my time!&lt;br /&gt;&lt;br /&gt;Further, there should be two default downloads/streams for episodic machinima:&lt;ul&gt;&lt;li&gt;There should be the new episode for returning viewers (without credits, of course - we already saw them so many times. You can do a &quot;previously&quot; if the plot so demands.)&lt;/li&gt;&lt;li&gt;And there should be everything from the first up to the new episode in a single download/stream for people coming to the story for the first time.&lt;/li&gt;&lt;/ul&gt;These are your two markets - cater to them. The second is particularly ill-served by having to watch umpteen short previous episodes in order to catch-up, where tedious credits/theme song prevent me getting into your wonderful art.&lt;br /&gt;&lt;br /&gt;(Sorry for the explosion of highly subjective opinion. I don&apos;t know why I care so much about it. I remember I tried and failed to convince Hugh to do this kind of thing with Bloodspell.)</description>
  <comments>http://anthonybailey.livejournal.com/33958.html</comments>
  <category>machinima</category>
  <lj:security>public</lj:security>
  <lj:reply-count>7</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/33734.html</guid>
  <pubDate>Tue, 23 Oct 2007 23:30:18 GMT</pubDate>
  <title>&apos;Spell is out</title>
  <link>http://anthonybailey.net/blog/2007/10/23/spell-is-out</link>
  <description>&lt;img src=&quot;http://ia351440.us.archive.org/0/items/BloodSpell_Feature_Film/BloodSpell_Feature_Mov.gif?cnt=0&quot; alt=&quot;BloodSpell stills&quot; align=&quot;right&quot; style=&quot;margin: 1em;&quot; /&gt;
&lt;p&gt;
Independent film outfit &lt;a href=&quot;http://strangecompany.org&quot;&gt;Strange Company&lt;/a&gt; have released their feature-length &lt;a href=&quot;http://wikipedia.org/wiki/Machinima&quot;&gt;machinima&lt;/a&gt; movie, the &quot;punk fantasy&quot; &lt;a href=&quot;http://bloodspell.com&quot;&gt;&lt;cite&gt;BloodSpell&lt;/cite&gt;&lt;/a&gt;.
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;
My opinions on the film are necessarily messy. I&apos;m an &lt;a href=&quot;http://anthonybailey.net/blog/2007/09/09/origins-of-the-word-machinima&quot;&gt;advocate&lt;/a&gt; of the medium (machinima is shooting movies within virtual worlds, often using video games), and a friend of the creators - indeed, I worked on one of the tools used to create the film. So I&apos;m unfairly biased. I&apos;m also not a great person to have on your side, because I don&apos;t let such things mellow my criticisms or get me hyped - at best I do faint praise, and damn you.
&lt;/p&gt;&lt;p&gt;
&lt;cite&gt;BloodSpell&lt;/cite&gt; hits a huge range of highs and lows. Almost every aspect - story, performance, cinematography, art, technology/effects, pacing, dialogue - has parts that are truly great, and parts that are pretty poor. (The exception is the audio: sound and soundtrack are good throughout.) A spread of quality is not unusual in a film, but the range is particularly wide here. There are many genius moments and scenes. There are many embarassing ones.
&lt;/p&gt;&lt;p&gt;
The film is strong at start and end, weak in the middle. This is partly due to the order of shooting: Strange Company learned heaps about their machinima technologies and about movie-making as they created the piece; originally released in episodic chunks, they returned to completely redo the opening scene when editing together this version. It&apos;s also partly due to happenstance - the second scene was already strong, whilst the film serves as an archetypal illustration of the cinema textbook tendency to have the story sag in the middle.
&lt;/p&gt;&lt;p&gt;
This is by a fair way the best machinima feature film I&apos;ve seen. The dated technology is necessarily distracting, but didn&apos;t spoil my enjoyment. Whilst previous machinima movies have excited me about the future potential of the medium, this one is real, now. It simply works as a decent movie in it&apos;s own right - I&apos;d watch it through if it came on TV the right midweek evening, probably whilst bestowing it the odd sarcastic aside because, you know, it&apos;s lucky to be on the channel I&apos;m indulging.
&lt;/p&gt;&lt;p&gt;
It&apos;s also probably the best budget independent film of its genre (epic action fantasy drama with nods to comedy and contemporary culture - the one word summary is &quot;Buffy&quot;.) This is almost by definition: you simply can&apos;t shoot real film (or TV) of this flavor for the few thousand pounds it took to make &lt;cite&gt;BloodSpell&lt;/cite&gt;. (Also this genre of film is not blessed with many success stories. This one can only have helped.)
&lt;/p&gt;&lt;p&gt;
The film was made by volunteers, is &lt;a href=&quot;http://bloodspell.com/commons&quot;&gt;licensed&lt;/a&gt; under a &lt;a href=&quot;http://creativecommons.org/licenses/by-nc-sa/2.5/&quot;&gt;BY-NC&lt;/a&gt; Creative Commons licence, and you can &lt;a href=&quot;http://www.bloodspell.com/film/list/&quot;&gt;download or stream it&lt;/a&gt; for free. I&apos;d even encourage fans of the genre to do so if it didn&apos;t contradict my disclaimer at the start!
&lt;/p&gt;</description>
  <comments>http://anthonybailey.livejournal.com/33734.html</comments>
  <category>machinima</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/33442.html</guid>
  <pubDate>Sun, 30 Sep 2007 21:27:20 GMT</pubDate>
  <title>Digital Privacy Management is inEFFable</title>
  <link>http://anthonybailey.net/blog/2007/09/30/digital-privacy-management-is-ineffable</link>
  <description>&lt;p&gt;
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
It&apos;s increasingly convenient to manage personal data up in the cloud. Eben Moglen &lt;a href=&quot;http://itc.conversationsnetwork.org/shows/detail1897.html&quot;&gt;worries&lt;/a&gt; that people entrust important data to organisations without thinking of the downside. Drawing an analogy with open source in software, he encourages people to store data themselves rather than pumping it into proprietary information silos.
&lt;/p&gt;

&lt;p&gt;
I am persuaded by the argument as I&apos;ve phrased it above. It&apos;s timely to consider investing in keeping copies of the personal data that is important to you, because otherwise you&apos;re going to lose it when the silo closes. Ideally you would keep &lt;em&gt;the&lt;/em&gt; copy rather than &lt;em&gt;a&lt;/em&gt; copy, - you would manage the canonical resource and publish it. This is because you have the most interest in and ability to ensure the ongoing correctness of the data. Because DIY is hard, third-party service providers will help you; but they should be neutral hosts rather than aggregators motivated by their own uses for the information.
&lt;/p&gt;

&lt;p&gt;
Actually Moglen seems to be making the stronger argument that you should hold the data because you need to be able to &lt;em&gt;control&lt;/em&gt; it, not just &lt;em&gt;publish&lt;/em&gt; it. Commercial entities will enter into contracts with you about what use they are allowed to make of this data that you own and are generously granting them access to. His argument is phrased in terms of privacy - your right to control the use of digital data about you. Maybe you&apos;ll even sell access and usage rights.
&lt;/p&gt;

&lt;p&gt;
And this is where I differ from him and a whole bunch of organizations with whom usually I find myself in agreement. Trading overzealous stereotyping for a reduced risk of misquoting, I will pick the &lt;a href=&quot;http://www.eff.org/&quot;&gt;Electronic Frontier Foundation&lt;/a&gt; as a specific example of what I find to be a widespread and questionable position. I find their stance on issues of &lt;a href=&quot;http://www.eff.org/Privacy/&quot;&gt;privacy&lt;/a&gt; to be very much at odds with the pragmatic approach they take to, say, &lt;a href=&quot;http://www.eff.org/IP/fairuse/&quot;&gt;DRM&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
On the latter, essentially they say: trying to control how digital information is copied and used doesn&apos;t work very well. The technologies are too easy to break, and they prevent unintended new uses of the content, restricting freedoms and stifling innovation. Therefore we should avoid purely technical solutions, and retire historic business models that now rely on them. Instead play nice with the world as it is, and try to nudge it in the directions you desire.
&lt;/p&gt;

&lt;p&gt;
That all sounds right to me. So how on Earth will we be able to use any kind of Digital Privacy Management mechanism to control how &lt;em&gt;personal&lt;/em&gt; information is copied and used? Bits are bits, and once you publish them you just don&apos;t get to control their copying and use. The hazily envisaged DPM is DRM, only without a law-buying cartel behind it. It&apos;s not going to work. Move on, and start discussing and tackling the problems that can arise in a space where there are plausible solutions, please.
&lt;/p&gt;

&lt;p&gt;
(You&apos;ll also find the open source analogies work better once technical controls are abandonned, I believe.)

&lt;/p&gt;</description>
  <comments>http://anthonybailey.livejournal.com/33442.html</comments>
  <category>copyfighting</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/33236.html</guid>
  <pubDate>Sun, 09 Sep 2007 17:58:52 GMT</pubDate>
  <title>Origins of the word &quot;machinima&quot;</title>
  <link>http://anthonybailey.net/blog/2007/09/09/origins-of-the-word-machinima</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;
Machinima was spelled slightly differently when first-born. The

first use of the term, as &quot;machinema&quot;, appeared in an e-mail I sent
on the &apos;&lt;code&gt;q2demos&lt;/code&gt;&apos; mailing list on 5 Jan 1998.
Here is the quote from the mail in question. Conveniently, it happened to
go on to explain the need to coin the term.
&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Anthony:&lt;/strong&gt;&lt;pre&gt;
I think with a new tool-set and a greater awareness of the skills
required to make a good piece of machinema[*] we can expect to see
some truly adventurous stuff being made. Fine and fun as they can be,
slapstick and B-movie action horror are just the start of what *could*
be done with this new medium. If I was a film student with some
technical savvie, I&apos;d be beginning to look at using this stuff as an
alternative to or prototype for an expensive real-world production.

[*]Machinema... yes, sorry, it&apos;s a bit of a contrived term... but what
in general *are* we going to call these pieces of cinema that are made
using 3D engines? Not only is &quot;Quake movie&quot; an ugly and confusing
term, it&apos;s also fast going to become outdated as other technologies
become relevant. (c: Any ideas?
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;

I chose &quot;machinema&quot; to rhyme with cinema. I used &quot;machine&quot; as a base

only because I didn&apos;t find an easy pun with &quot;engine&quot; in it. I spelled

it with the &apos;e&apos; because it made it look a bit like cinema. I don&apos;t

believe it to be the best neologism in the world, and I apologize for

that - I didn&apos;t know the term was going to get widespread.

&lt;/p&gt;

&lt;p&gt;

The word began to be used fairly regularly on the mailing list

and gradually in other related fora, but that was about
 all.
So far as I know, it&apos;s first &quot;public&quot; appearance is in a review

I wrote for GameSpy Industry&apos;s Quake portal site PlanetQuake.com,

first published on 02 Apr 1999. (&lt;a href=&quot;http://web.archive.org/web/20000104160349/http://planetquake.com/reviews/nightfall.shtm&quot;&gt;Slightly broken copy of now dead page courtesy of the
Internet Archive&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
Hugh Hancock of Strange Company wrote up some &quot;machinima&quot; techniques on 10 Jun
1999. We were already in e-mail contact so we discussed the new spelling.
&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Anthony:&lt;/strong&gt;&lt;pre&gt;
&amp;lt;pedantry&amp;gt;
I&apos;m very happy that you&apos;ve adopted my silly whimiscal term for cinema
generated by desktop machines, but is there any reason that you have
changed the spelling? The &apos;e&apos;s in both &quot;cinema&quot; and &quot;machine&quot; seem to
suggest the natural spelling for the mangled combination is
&quot;machinema.&quot; It&apos;s a pun rather than a derivation, so I don&apos;t see any
linguistic pressure to follow the path of e.g. &quot;machinist.&quot;
&amp;lt;/pedantry&amp;gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;strong&gt;Hugh:&lt;/strong&gt;&lt;pre&gt;
As a linguist I&apos;d prefer to use the &quot;ima&quot;, a more common suffix than &quot;ema&quot;,
and go with the normal derivation, but to be perfectly honest the main
reason we&apos;ve changed the spelling is I forgot how you originally spelled it
and &quot;ima&quot; looked more natural! Sorry...
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;strong&gt;Anthony:&lt;/strong&gt;&lt;pre&gt;
I didn&apos;t like &quot;machinima&quot; at first because it seemed to lose the
&quot;cinema&quot; pun, at least at the lexical level. But it&apos;s still there
phonically, and now I realise there is a genuine derivation from
&quot;anima&quot; going on as well, so the new spelling actually maybe combines
something plausible and word-play. Anyway, in the interests of
uniformity I&apos;ll adopt your spelling.
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;
&lt;a href=&quot;http://machinimafordummies.com/pages/machiniwhatnow&quot;&gt;Hugh tells the machinima
etymology story&lt;/a&gt; from his side in a far more self-deprecating and entertaining style 
within the book
&lt;a href=&quot;http://machinimafordummies.com/&quot;&gt;&lt;cite&gt;Machinima for Dummies&lt;/cite&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
The term crossed the chasm for certain when hub-site machinima.com was
launched at the start of 2000.
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/33236.html</comments>
  <category>machinima</category>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/32869.html</guid>
  <pubDate>Sun, 19 Aug 2007 18:07:58 GMT</pubDate>
  <title>Blipvert</title>
  <link>http://anthonybailey.net/blog/2007/08/19/blipvert</link>
  <description>&lt;p&gt;
I&apos;m wondering why there isn&apos;t more machinima on &lt;a href=&quot;http://blip.tv/&quot;&gt;blip.tv&lt;/a&gt;. There is &lt;a href=&quot;http://www.blip.tv/posts/?topic_name=machinima&quot;&gt;some&lt;/a&gt;, but this video publishing service seems like such a good fit with the needs of machers I would have expected more.
&lt;/p&gt;

&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;
I became aware of blip through &lt;a href=&quot;http://www.itconversations.com/shows/detail1895.html&quot;&gt;this recent interview with co-founder Mike Hudack&lt;/a&gt; by Jon Udell. (Good podcast - says some interesting things in general about web service businesses.) 
&lt;/p&gt;

&lt;p&gt;
The company seems to really get what a user-gen content aggregator and publisher needs to do to succeed by pleasing their users. You can read their own &lt;a href=&quot;http://blip.tv/about/http://blip.tv/about/&quot;&gt;overview&lt;/a&gt;, but items from the interview that impressed me included&lt;ul&gt;
&lt;li&gt;a strong distaste for service lock-in (for example, they will automatically mirror your upload to the Internet Archive if you want),&lt;/li&gt;
&lt;li&gt;being very open to working with other distributors and publishers (for example, building a system to share tags and download stats),&lt;/li&gt;
&lt;li&gt;staying in the background to let creators control branding (for example, they don&apos;t embed their logo),&lt;/li&gt;
&lt;li&gt;sensible advertising options (you can use their advertising and share the profits, or do your own, or none),&lt;/li&gt;
&lt;li&gt;providing a strong free service with professional upgrade.&lt;/li&gt;
&lt;/ul&gt;
The whole thing sounds like the right business model: provide a service which offers sustainable long-term value that supports creators.
&lt;/p&gt;

&lt;p&gt;
The disclaimer: I&apos;ve not used the service. (Anyone who has care to comment?)
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/32869.html</comments>
  <category>machinima</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/32763.html</guid>
  <pubDate>Thu, 19 Jul 2007 00:46:32 GMT</pubDate>
  <title>Regression Therapy - Contentful Testing</title>
  <link>http://anthonybailey.net/blog/2007/07/19/regression-therapy-contentful-testing</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;h1&gt;Regression Therapy - Contentful Testing&lt;/h1&gt;
&lt;img style=&quot;float: right; margin: 1.5em; margin-top: 0&quot; alt=&quot;Contentful bear&quot; src=&quot;http://contentful.rubyforge.org/bear.jpg&quot; /&gt;
&lt;p&gt;
This article is a fleshing out of a ten-slides-in-ten-minutes talk that
&lt;a href=&quot;http://anthonybailey.tumblr.com/post/5687247&quot;&gt;I originally gave in July 2007&lt;/a&gt; 
at &lt;a href=&quot;http://www.amazondc.com/&quot;&gt;work&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
Since then I talked on the same subject at the Scotland on Rails 2008 conference. &lt;a href=&quot;http://anthonybailey.net/tumblelog/2008/04/08/contentful-slides-from-my-talk-at-scotland-on-etc&quot;&gt;Slides and so forth are available.&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;1. Introduction&lt;/h2&gt;
&lt;p&gt;
Regression testing is usually seen as the poorer cousin of &quot;proper&quot; domain-abstracted assertion-based testing.
Often rightly so!
&lt;/p&gt;&lt;p&gt;
However, with the right support in place, I have found that this form of testing can work very well in certain contexts.
&lt;/p&gt;&lt;p&gt;
This article addresses one such context: testing the view content generated by a web app.
I discuss the background,
then present a concrete example in the form of a plug-in for &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt;.
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;2. Three reasons to test&lt;/h2&gt;
&lt;p&gt;
For the purpose of this discussion, I identify three overlapping but distinguishable uses of tests in software development.
&lt;/p&gt;

&lt;h3&gt;To preserve existing good behaviour&lt;/h3&gt;
&lt;p&gt;
Tests can be used to maintain known good behaviour, preventing accidental bad changes (also known as &quot;regressions&quot;.)

The tests provide a safety net during refactorings, and enfore a Hippocratic  &quot;first, do no harm&quot; oath during other work.
&lt;/p&gt;&lt;span style=&quot;background: #eee; font-size: 120%; font-weight: bold; color: green&quot;&gt;
....................................&lt;font color=&quot;red&quot;&gt;!&lt;/font&gt;..&lt;font color=&quot;red&quot;&gt;!&lt;/font&gt;...........................&lt;font color=&quot;red&quot;&gt;!&lt;/font&gt;...........
&lt;/span&gt;&lt;p&gt;
The test stays green whilst all is well. A red bar tells us that we&apos;ve messed up and broken something.
&lt;/p&gt;

&lt;h3&gt;To drive intended changes&lt;/h3&gt;
&lt;p&gt;
Tests can be used to change (often, to add) behaviour, providing context to an intended good change.

The archetypal example is classic &lt;abbrev title=&quot;Test-driven development&quot;&gt;TDD&lt;/abbrev&gt;,
creating tests first in order to define the problem,
and to guide the design and implementation of a solution.
&lt;/p&gt;&lt;span style=&quot;background: #eee; font-size: 120%; font-weight: bold; color: green&quot;&gt;
&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;&lt;font color=&quot;red&quot;&gt;&amp;gt;&lt;/font&gt;&amp;gt;
&lt;/span&gt;&lt;p&gt;
New tests flash red and are put back to green by introducing production code.
&lt;/p&gt;

&lt;h3&gt;To understand emergent change&lt;/h3&gt;
&lt;p&gt;
A less often discussed use of testing is to explore and validate emergent behaviour.
&lt;/p&gt;&lt;p&gt;
In a complex system it can be hard to prejudge or predict every knock-on effect
of a deliberate change to one part of that system.
Tests can provide a context for understanding and controlling such changes and consequences.
&lt;/p&gt;&lt;span style=&quot;background: #eee; font-size: 120%; font-weight: bold; color: green&quot;&gt;
.....&lt;font color=&quot;red&quot;&gt;!!??&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;...................&lt;font color=&quot;red&quot;&gt;!!??&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;............&lt;font color=&quot;red&quot;&gt;!!??&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;small&gt;?&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;..............
&lt;/span&gt;&lt;p&gt;

In this way of working, changes cause flashes of red that are observed
and then often approved,
updating expectations to recolor things back to green again.
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;3. Three ways to test&lt;/h2&gt;
&lt;p&gt;
Next I&apos;ll categorize three methods of testing,
paying particular attention to their use in the context of testing view content.
&lt;/p&gt;

&lt;h3&gt;Live testing&lt;/h3&gt;
&lt;p&gt;
In a scandalously unrepeatable manner that sacrifices reliable coverage, we can test by hand and verify by eye.
&lt;/p&gt;&lt;p&gt;
Drive the web app through the browser and see if looks right.
We all do this.
It shouldn&apos;t be sniffed at; it is genuinely useful because it is so cheap.
However, once the system gets sufficiently complex, it doesn&apos;t hold
&lt;abbrev title=&quot;Does WATIR hold it? Perhaps! I&amp;#39;m not the right person to ask.&quot;&gt;water&lt;/abbrev&gt;.
I won&apos;t consider manual testing further in this article.
&lt;/p&gt;

&lt;p style=&quot;margin-top: 2em&quot;&gt;
To automate testing, we have to be able to provoke the generation of view content that we can then test.
Assuming a good web app framework that allows us to do this (no small thing, but not the topic of interest today),
there are then two means of testing the content.
&lt;/p&gt;

&lt;h3&gt;Assertion testing&lt;/h3&gt;
&lt;p&gt;
We can explcitly check individual desired properties of the the resulting content.
&lt;/p&gt;

&lt;h3&gt;Regression testing&lt;/h3&gt;
&lt;p&gt;
Or, we can compare the content in its entirety against a previously validated known good copy.
&lt;/p&gt;

&lt;p style=&quot;margin-top: 2em&quot;&gt;
I&apos;ll now discuss in greater detail the relative merits of testing view content through assertion and regression.
&lt;/p&gt;
 
&lt;hr /&gt;

&lt;h2&gt;4. &lt;code style=&quot;font-size: 120%&quot;&gt;assert_equals(expected, test_method)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;
Assertion tests are prevalent in contemporary developer testing, with good reason.
They tend to be very effective, given sufficient investment &amp;ndash;
we need to express the properties that care about succinctly,
and at an appropriate level of abstraction within the domain.
&lt;/p&gt;&lt;p&gt;
The Rails web framework has evolved a best-of-breed solution for assertion testing view content
in the form of &lt;code&gt;assert_select&lt;/code&gt;.
It uses CSS selectors to locate content, and neatly expresses the conditions it should satisfy.
Here&apos;s a simple example:
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: #0dd; color: black&quot;&gt;&lt;pre&gt;
class CartExampleTest
  def test_total
    get &quot;/store/add_to_cart&quot;, :id =&amp;gt; rails_book.id
    &lt;span style=&quot;background: #cff; font-weight: bold&quot;&gt;assert_select &quot;div#cart tr.total td:last-of-type&quot;, &quot;$39.95&quot;&lt;/span&gt;
  end
end
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
This is pretty nice.
But it doesn&apos;t escape some downsides of assertion testing
which happen to be particularly troublesome for view content.
&lt;/p&gt;

&lt;h3&gt;Coverage is selective&lt;/h3&gt;
&lt;p&gt;
We can only capture the behaviors that we think to test for.
The importance of many properties of view content are not obvious until we&apos;ve accidentally changed them.
&lt;/p&gt;

&lt;h3&gt;Exploration is expensive&lt;/h3&gt;
&lt;p&gt;
Assertion tests are generally great for catching regressions and for driving changes.
But they are poor for my third type of test use, that of exploring change.
The developer has to run around rebalancing the books,
fixing up test expectations to agree with the unexpected consequences of a change.
&lt;/p&gt;

&lt;h3&gt;Explicitness is verbose&lt;/h3&gt;
&lt;p&gt;
Many aspects of the view are worth caring about.
It takes too much code to express them all explicitly;
translation, even into a well-designed and succinct language, still takes time.
The most concise summary of all the properties of a piece of content is the content itself&amp;hellip;
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;5. Regression (past life)&lt;/h2&gt;
&lt;p&gt;
&amp;hellip;which leads us to our next alternative.
&lt;/p&gt;&lt;p&gt;
Regression tests work by checking current content against expected content.
We test by comparing the entirety of what we generate against some previously approved copy.
The expected content might be quoted verbatim in the test; more often it is stored in a file.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: #0dd; color: black&quot;&gt;&lt;pre&gt;
class CartExampleTest
  def test_total
    get &quot;/store/add_to_cart&quot;, :id =&amp;gt; rails_book.id
    &lt;span style=&quot;background: #cff; font-weight: bold&quot;&gt;assert_equals File.new(&apos;expected.html&apos;).read, @response&lt;/span&gt;
  end
end
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
This is clearly very cheap to express, and capturing existent good behaviour needs no translation: just a copy and paste of the current results.
&lt;/p&gt;&lt;p style=&quot;margin-top: 2em&quot;&gt;
But like assertion testing, regression testing view content comes with some downsides.
&lt;/p&gt;

&lt;h3&gt;Tests don&apos;t come first&lt;/h3&gt;
&lt;p&gt;
Again this form of testing is good for two of the three uses of testing that I identified.
It is ideal for exploring changes,
and unsurprisingly it catches regressions.
But, it is very awkward to drive new behavior.
&lt;/p&gt;&lt;p&gt;
However, this problem is not serious in the context of view content.
Although it would not be plausible to test-drive the generation of content through regression testing,
it is not clear that one would ever want to.
View content tends to come into existence in a concrete form,
designed or composed in toto
rather than being built up one abstract essence at a time.
Even for those who usually love to test first, test-last of view content does not seem so detestable.
&lt;/p&gt;&lt;p style=&quot;margin-top: 2em&quot;&gt;
The main problem with regression testing is that it is very expensive if we act naively in response to diffs.
There are two common pain points.
&lt;/p&gt;
 
&lt;h3&gt;Tests are brittle and fragile&lt;/h3&gt;
&lt;p&gt;
Comparing against a complete text copy means that we see every change, even ones we don&apos;t actually care about.
Every difference needs explicit attention.
&lt;/p&gt;

&lt;h3&gt;Tests are usually noisy&lt;/h3&gt;
&lt;p&gt;
Because there is no abstraction, one change may break many tests.
Similar differences need attention in multiple places.
&lt;/p&gt;&lt;p&gt;
These workflow costs multiply as the system under regression test grows.
Investing in the abstraction of assertion tests is usually preferrable.
Even in the domain of view content, regression tests will prove too costly if we do not work to make them less so.
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;6. &lt;strike&gt;Regression&lt;/strike&gt; Contentful testing&lt;/h2&gt;
&lt;p&gt;
So: let&apos;s attempt to address the problems, and turn regression testing into contentful testing.
&lt;/p&gt;

&lt;h3&gt;Lessen the noise&lt;/h3&gt;
&lt;p&gt;
Information can be defined as any difference that makes a difference.
The diffs that don&apos;t are the noise in regression tests that we want to reduce.
&lt;/p&gt;&lt;dl&gt;
&lt;dt&gt;Ignore insignificant change&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;
Some textual changes in HTML source
(for example, certain whitespace in content;
and formatting, quoting, capitalization and attribute order within the mark-up itself)
won&apos;t affect how the content is displayed.
&lt;/p&gt;&lt;p&gt;
These can be ignored by allowing a little abstraction back in.
We can still use standard text-based diff tools,
but to compare unique text representations of &lt;abbrev title=&quot;Document Object Model&quot;&gt;DOM&lt;/abbrev&gt;-normalized content.
&lt;/p&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;abbrev title=&quot;Don&amp;#39;t repeat yourself&quot;&gt;DRY&lt;/abbrev&gt; up which content is tested&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;
Rather than see the same diff to the same repeated content over and over,
we can focus regression tests on those parts of content that vary across our testcases.
&lt;/p&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3&gt;Smooth the workflow&lt;/h3&gt;
&lt;p&gt;
In good automation fashion, we will make the common tasks in the workflow as cheap and as easy as we can.
&lt;/p&gt;&lt;p&gt;
It has to be simple
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;to create a new regression test,&lt;/li&gt;
&lt;li&gt;to inspect diffs from the expected content when changes occur, and&lt;/li&gt;
&lt;li&gt;to accept the changes once they have been checked over and seen to be OK.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
And, this needs to work well in batch.
We should be able to detect, review and accept changes in many tests at a time when need be.
&lt;/p&gt;

&lt;h3&gt;The Contentful Rails plug-in&lt;/h3&gt;
&lt;p&gt;
I put together a plug-in that tries to do these things within Rails.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% script/plugin install svn://rubyforge.org/var/svn/contentful
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
The plug-in was evolved in, then extracted from, a small spare-time web application.
I&apos;ve since re-used it successfully in other Rails projects.
If you write Rails applications, you can read more and download the plug-in at the
&lt;a href=&quot;http://contentful.rubyforge.org/&quot;&gt;Contentful website&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
For this discussion, Contentful is simply a single concrete example
of a general approach I believe should translate across language boundaries,
or from my Rake automation commands into your favorite &lt;abbrev title=&quot;Interactive development environement&quot;&gt;IDE&lt;/abbrev&gt;.
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;7. Capturing content to create tests&lt;/h2&gt;
&lt;p&gt;
With Contentful plugged-in, we can check the content generated in a test by saying &lt;code&gt;assert contentful&lt;/code&gt;.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: #0dd; color: black&quot;&gt;&lt;pre&gt;
class CartExampleTest
  def test_total
    get &quot;/store/add_to_cart&quot;, :id =&amp;gt; rails_book.id
    &lt;span style=&quot;background: #cff; font-weight: bold&quot;&gt;assert_contentful&lt;/span&gt;
  end
end
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
Then when we run the test for the first time, the test passes
- and it generates the expected content from the current content, as a side effect.
In accord with Rails&apos; culture of convention over configuration,
we locate the expected content in a standard place,
derived from the name of the test.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rake test
Started
...................................!...............
Finished in 3.487022 seconds.

  1) Contentful Notification:
test_total(CartExampleTest):
Generated /depot/&lt;span style=&quot;color: #cff; font-weight: bold&quot;&gt;test/contentful/cart_example/total/expected.html&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
To avoid duplication, we can focus on a particular subset of the content using a &lt;abbrev title=&quot;Cascading Style Sheet&quot;&gt;CSS&lt;/abbrev&gt; selector. This allows us to ignore components that are common across all our views, such as navigation sidebars and the like.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: #0dd; color: black&quot;&gt;&lt;pre&gt;
class CartExampleTest
  def test_total
    get &quot;/store/add_to_cart&quot;, :id =&amp;gt; rails_book.id
    &lt;span style=&quot;background: #cff; font-weight: bold&quot;&gt;select_contentful &quot;div#cart&quot;&lt;/span&gt;
  end
end
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rake test
Started
...................................!...............
Finished in 3.494442 seconds.

  1) Contentful Notification:
test_total(CartExampleTest):
Generated /depot/test/contentful/cart_example/total/&lt;span style=&quot;color: #cff; font-weight: bold&quot;&gt;div#cart.&lt;/span&gt;expected.html
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2&gt;8. Detecting changes and inspecting diffs&lt;/h2&gt;
&lt;p&gt;
Now our tests are up, we should set them running.
(Running everything is the norm,
but Contentful will build and execute a suite containing only its own tests if asked.
I&apos;ll show that here.)
&lt;/p&gt;&lt;p&gt;
Here&apos;s what happens when we&apos;ve broken something:
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rake test:content
Testing expectations in test/contentful
Started
..F.....
Finished in 0.808864 seconds.

  1) Failure:
test_total(CartExampleTest)
&lt;span style=&quot;color: #cff; font-weight: bold&quot;&gt;diff test/contentful/cart_example/total/*.to_diff&lt;/span&gt;
to see the content change
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
The failing test will have written a temporary &lt;code&gt;changed.html&lt;/code&gt; file next to &lt;code&gt;expected.html&lt;/code&gt;.
Additionally it generates a second pair of files
(&lt;code&gt;expected.to_diff&lt;/code&gt; and &lt;code&gt;changed.to_diff&lt;/code&gt;)
which are the same HTML DOMs,
but with some added line-breaks and other normalization to make them usefully comparable using a standard text diff.
&lt;p&gt;&lt;/p&gt;
(Whenever a test passes, the stale three files get cleaned away.)
&lt;/p&gt;&lt;p&gt;
As well as using the suggested command-line to examine an individual failure,
we can inspect all current diffs by running a single command.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rake test:diff
Finding changes in test/contentful
! Diff in cart_example/total/changed.html
91c91
&amp;lt; &amp;lt;td id=&quot;total&quot;&amp;gt;
&amp;lt; Total
---
&amp;gt; &amp;lt;td id=&quot;total&quot; class=&quot;grand&quot;&amp;gt;
&amp;gt; Grand Total
! Diff in another_example/something_else/changed.html
&lt;var&gt;[etc...]&lt;/var&gt;
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
(Additionally, if we want to focus on a subset of all the current changes,
we can do so by running within a subdirectory of &lt;code&gt;test/contentful&lt;/code&gt;.)
&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;9. Accepting change&lt;/h2&gt;
&lt;p&gt;
If a set of changes are good,
then often we can tell this by casting an eye over the diffs and observing a plausible pattern.
&lt;/p&gt;&lt;p&gt;
(Sometimes one can grep the diffs for extra certainty.
For bonus points, script anything you find yourself doing by hand three times!)
&lt;/p&gt;&lt;p&gt;
If all looks good, we want to accept a bunch of changes.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rake test:accept
Finding changes in test/contentful/cart_example
! Accepting cart_example/total/changed.html
! Accepting another_example/something_else/changed.html
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
That was a bit better than opening up an editor and copying and pasting the content, right?
&lt;/p&gt;&lt;p&gt;
(Again we can refine our acceptance to a subset of changes by running within a subdirectory.)
&lt;/p&gt;&lt;p&gt;
Also, since expected content is generated when absent,
we can alternatively use the file system to our advantage,
and update expectations by removing particular subdirectories and then re-running tests.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% rm test/contentful/further/specific/*
&lt;var&gt;[etc...]&lt;/var&gt;
Generated /depot/test/contentful/further/specific/expected.html
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2&gt;10. Making a vice out of a virtue&lt;/h2&gt;
&lt;p&gt;
Personally, I really like my content tests to be a permanent part of the test suite.
Once the workflow is smooth, I find them well worth their maintenence cost.
I like the total coverage; they allow serendipidous discovery of changes I didn&apos;t consider.
&lt;/p&gt;&lt;p&gt;
However, even if you won&apos;t buy the entire bridge that I&apos;m trying to sell you, perhaps I can interest you in a strut:
use the virtues of contentful testing as a &lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=171323&quot;&gt;vice&lt;/a&gt;.
(Sorry for the UK spelling. Translate it into the US &quot;vise&quot; if you like, but you&apos;ll spoil my pun.)
&lt;/p&gt;&lt;p&gt;
Suppose we want to perform a pervasive refactoring. For example,
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;to &lt;a href=&quot;http://anthonybailey.livejournal.com/29792.html&quot;&gt;change&lt;/a&gt; the templating framework we&apos;re using, or&lt;/li&gt;
&lt;li&gt;to factor out a set of view helpers and partials.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
Big changes are risky.
It would be nice to temporarily pin everything about current content tightly down in place whilst we work.
When using Contentful, then we can add a bonus content assertion to every existing functional and integration test
by setting a single Rails config flag in &lt;code&gt;environment.rb&lt;/code&gt;:
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: #0dd; color: black&quot;&gt;&lt;pre&gt;
CONTENTFUL_AUTO = true
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
Running tests once generates expectations and locks down all the current content.
Then we can perform our refactoring under their full protection.
When done, we unset the config flag and delete the temporary expectations before checking in the safely refactored code.
&lt;/p&gt;&lt;blockquote style=&quot;font-family: monospace; font-size: 120%; padding: 1em; background: black; color: cyan&quot;&gt;&lt;pre&gt;
% wget &lt;a style=&quot;color: cyan&quot; href=&quot;http://contentful.rubyforge.org/&quot;&gt;http://contentful.rubyforge.org/&lt;/a&gt;
&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;
Thanks for reading! Comments are most welcome.
&lt;/p&gt;

&lt;hr /&gt;</description>
  <comments>http://anthonybailey.livejournal.com/32763.html</comments>
  <category>software_development</category>
  <category>rails</category>
  <lj:mood>content</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>6</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/32421.html</guid>
  <pubDate>Mon, 04 Jun 2007 18:14:04 GMT</pubDate>
  <title>The views expressed here...</title>
  <link>http://anthonybailey.net/blog/2007/06/04/the-views-expressed-here-etc</link>
  <description>Something I forgot to do on &lt;a href=&quot;http://anthonybailey.livejournal.com/26347.html&quot;&gt;joining my current employer&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The views I express here on my blog do not necessarily reflect the views of Amazon.com.&lt;/b&gt;&lt;br /&gt;</description>
  <comments>http://anthonybailey.livejournal.com/32421.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/31984.html</guid>
  <pubDate>Fri, 25 May 2007 21:48:37 GMT</pubDate>
  <title>A Feedsum Engine</title>
  <link>http://anthonybailey.net/blog/2007/05/25/a-feedsum-engine</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;
A couple of weeks ago I noticed that I was avoiding subscribing to some informative feeds because they were a bit &lt;em&gt;too&lt;/em&gt; informative. I don&apos;t want to see as many as a dozen separate news items across the course of a single day, because it makes too much noise in the feed aggregator and gets in the way of rarer, more valuable entries. (In my case, the aggregator takes the form of &lt;a href=&quot;http://anthonybailey.livejournal.com/friends/&quot;&gt;my LJ Friends page&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
&lt;img src=&quot;http://feedsum.com/images/feed-icon-128x128.png&quot; alt=&quot;Feed icon&quot; align=&quot;left&quot; style=&quot;padding: 2em&quot; /&gt;
I realized I wanted the equivalent of a digest e-mail for feeds - a daily summary or similar. This sounded like a job for a web service, so after failing to find any existing solution, I registered &lt;a href=&quot;http://feedsum.com/&quot;&gt;&lt;code&gt;feedsum.com&lt;/code&gt;&lt;/a&gt; and coded up a little Rails app that sucks in a source feed, collates items into daily batches, and generates a derived feed in which each item summarizes all the source items for one day.
&lt;/p&gt;

&lt;p&gt;
At first this was simply a stateless service, but I found that source feeds often dried up very quickly - by the end of the day, the earliest items could already have been pushed out. So now I stash source items in a database whenever the source feed is pulled. I also found that syndicators such as LiveJournal were not sufficiently patient to wait for my app to spin up in clunky development mode, starting up a fresh Ruby before pulling the source and generating a summary - they often timed out before the service was done. So finally I have had to learn how to deploy a proper production Rails app using mongrel proxies and all that. There were some fiddly one-time set-up details, but once up and running Capistrano is pure deploy joy.
&lt;img src=&quot;http://feedsum.com/images/feedsum-icon-128x128.png&quot; alt=&quot;Feed icon&quot; align=&quot;right&quot; style=&quot;padding: 2em&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;
Currently I&apos;m using the service to source three LJ syndications: &lt;span class=&apos;ljuser&apos; lj:user=&apos;slashdot_daily&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://syndicated.livejournal.com/slashdot_daily/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/syndicated.gif&apos; alt=&apos;[info]&apos; width=&apos;16&apos; height=&apos;16&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://syndicated.livejournal.com/slashdot_daily/&apos;&gt;&lt;b&gt;slashdot_daily&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span class=&apos;ljuser&apos; lj:user=&apos;machinifeedaily&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://syndicated.livejournal.com/machinifeedaily/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/syndicated.gif&apos; alt=&apos;[info]&apos; width=&apos;16&apos; height=&apos;16&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://syndicated.livejournal.com/machinifeedaily/&apos;&gt;&lt;b&gt;machinifeedaily&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; and &lt;span class=&apos;ljuser&apos; lj:user=&apos;arstechnicdaily&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://syndicated.livejournal.com/arstechnicdaily/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/syndicated.gif&apos; alt=&apos;[info]&apos; width=&apos;16&apos; height=&apos;16&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://syndicated.livejournal.com/arstechnicdaily/&apos;&gt;&lt;b&gt;arstechnicdaily&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;. The service can probably handle a further light load yet so others (LJ users or any other feed consumer) are welcome to give it a beta test.
It&apos;s easy to use: to get a daily summary of some feed
&lt;blockquote&gt;&lt;strong&gt;&lt;code&gt;http://example.com/path/index.xml&lt;/code&gt;&lt;/strong&gt;&lt;/blockquote&gt;
simply request
&lt;blockquote&gt;&lt;strong&gt;&lt;code&gt;http://feedsum.com/daily/example.com/path/index.xml&lt;/code&gt;&lt;/strong&gt;&lt;/blockquote&gt;
(You can do other neat stuff like &lt;strong&gt;&lt;code&gt;http://feedsum.com/every/8/hours/...&lt;/code&gt;&lt;/strong&gt; and so forth but the daily summaries tend to be the useful ones.)
&lt;/p&gt;

&lt;p&gt;
Do try it out and please tell me if e.g. it completely chokes on any source feeds.
(And to avoid a rush of dupes, could anyone who uses it to register further LJ syndication accounts add a link in a comment below.)
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/31984.html</comments>
  <category>software_development</category>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/31383.html</guid>
  <pubDate>Sat, 12 May 2007 10:48:36 GMT</pubDate>
  <title>Happy Fun Content Surprise</title>
  <link>http://anthonybailey.net/blog/2007/05/12/happy-fun-content-surprise</link>
  <description>&lt;abbreviation title=&quot;Home Box Office&quot;&gt;HBO&lt;/abbreviation&gt; &lt;abbreviation title=&quot;Chief Technology Officer&quot;&gt;CTO&lt;/abbreviation&gt; Bob Zitter &lt;a href=&quot;http://www.broadcastingcable.com/article/CA6440876.html&quot;&gt;claims&lt;/a&gt; &lt;abbreviation title=&quot;Digital Rights Management - or, Digital Restrictions Management&quot;&gt;DRM&lt;/abbreviation&gt; only has &lt;abbreviation title=&quot;E.g. RMS - damn, ran out of Show The Expanded Acronym Mechanisms&quot;&gt;detractors&lt;/abbreviation&gt; because of the branding - he suggests &quot;&lt;abbreviation title=&quot;DCE - sounds dicey to me&quot;&gt;Digital Consumer Enablement&lt;/abbreviation&gt;&quot; instead. Ars technica say: &lt;a href=&quot;http://arstechnica.com/news.ars/post/20070511-hey-hbo-a-turd-by-any-other-name-smells-just-as-foul.html&quot;&gt;why stop there&lt;/a&gt;?</description>
  <comments>http://anthonybailey.livejournal.com/31383.html</comments>
  <category>copyfighting</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/31083.html</guid>
  <pubDate>Sat, 28 Apr 2007 22:29:15 GMT</pubDate>
  <title>Hacking it for the kids</title>
  <link>http://anthonybailey.net/blog/2007/04/28/hacking-it-for-the-kids</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;
I remember reading &lt;a href=&quot;http://whytheluckystiff.net/articles/theLittleCodersPredicament.html&quot;&gt;&lt;cite&gt;The Little Coder&apos;s Predicament&lt;/cite&gt;&lt;/a&gt; some years back. I agreed strongly with the essay: many of my generation were encouraged to code because our home computers et al, bought for games, made it so easy and rewarding to play and experiment. Machines are now much more powerful, and the Net makes the potential rewards far greater, but today&apos;s generation lacked such an immediately accessible path into programming.
&lt;/p&gt;

&lt;img src=&quot;http://hacketyhack.net/images/design/App-256x256.png&quot; align=&quot;right&quot; alt=&quot;Hacky Mouse&quot; /&gt;

&lt;p&gt;
The &lt;a href=&quot;http://www.whytheluckystiff.net&quot;&gt;author of the article&lt;/a&gt; has since become something of a &lt;a href=&quot;http://redhanded.hobix.com/&quot;&gt;Ruby guru&lt;/a&gt; with a track record of turning dreams into code. Recently he&apos;s addressed his &lt;cite&gt;Predicament&lt;/cite&gt; and with a little help from his &lt;a href=&quot;http://redhanded.hobix.com/cult/theOriginalFifty.html&quot;&gt;friends&lt;/a&gt; brought &lt;a href=&quot;http://hacketyhack.net/&quot;&gt;Hackety Hack&lt;/a&gt; into being. It&apos;s in an early phase (Windows only, and not quite bug-free) but I think this will be a great playground. 
&lt;/p&gt;

&lt;p&gt;
When I was thirteen, my ZX Spectrum let me make beeps, plot pixels and clash colors. Its contemporary equivalent HH lets you work directly with the things that matter today: web pages, feeds, audio, images, video. It&apos;s a bit like &lt;a href=&quot;http://pipes.yahoo.com/&quot;&gt;Pipes&lt;/a&gt; without the annoying drag &apos;n&apos; drop (or Yahoo ID.) The underpinnings are rather too indistinguishable from magic to trust with anything you&apos;d get paid for, but what a great way this would be to write your first real-time networking web app:
&lt;pre&gt;
chat = Hacker(&apos;anthony&apos;).channel(&apos;test&apos;)
Web.popup do
  title(&apos;Chat Client&apos;)
  box = scrollbox
  editline(&apos;Say&apos;)
  buttons(&apos;Send&apos;) { |popup| chat.say(popup[&apos;Say&apos;]) }
  every(1) { chat.hear.each { |message| add_to_scrollbox message } }
end
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
Hackety&apos;s hackers can share programs and data across the Net very easily - much better than getting the computer to squeal into a tape that you take round to your mate&apos;s house! I really hope that this thing will take off and get some people programming.
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/31083.html</comments>
  <category>software_development</category>
  <lj:mood>jealous</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/30922.html</guid>
  <pubDate>Mon, 16 Apr 2007 06:57:30 GMT</pubDate>
  <title>New angles</title>
  <link>http://anthonybailey.net/blog/2007/04/16/new-angles</link>
  <description>&lt;a href=&quot;http://fotowoosh.com/&quot;&gt;Fotowoosh&lt;/a&gt; is a service to extract 3D models from 2D images, seeking beta users.&lt;br /&gt;&lt;br /&gt;This kind of math is not new, but I&apos;ve not seen it productized and sold before - seems to be a pretty exciting technology development for machinima-makers. Model asset generation is probably the biggest remaining expense in our medium, expecially films that want to be set outside the virtual world the engine they were made in comes with. (Seen at &lt;a href=&quot;http://www.techcrunch.com/&quot;&gt;TechCrunch&lt;/a&gt; - the &lt;a href=&quot;http://www.techcrunch.com/2007/04/15/fotowoosh-will-turn-any-picture-into-3d-image/&quot;&gt;article&lt;/a&gt; there has a good pictorial summary)</description>
  <comments>http://anthonybailey.livejournal.com/30922.html</comments>
  <category>machinima</category>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/30671.html</guid>
  <pubDate>Sun, 15 Apr 2007 21:04:14 GMT</pubDate>
  <title>How to disenchant the pedantic voter</title>
  <link>http://anthonybailey.net/blog/2007/04/15/how-to-disenchant-the-pedantic-voter</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;img src=&quot;http://anthonybailey.net/images/dumb_headline_and_graph.png&quot; align=&quot;right&quot; alt=&quot;It could not be closer (sic): Labour 34%, LibDem 29%, Con 19%, SNP 10%.&quot; style=&quot;padding: 1em;&quot; /&gt;

&lt;p&gt;
There are local elections here soon. Here&apos;s some really dumb propaganda from a party I&apos;m feeling somewhat embarassed to admit I usually vote for.
&lt;/p&gt;

&lt;p&gt;
Three fish in one barrel:
&lt;ul&gt;
&lt;li&gt;That&apos;s sure some excitingly non-linear y-axis you&apos;ve got going on there.&lt;/li&gt;
&lt;li&gt;These are the results from the previous election. Alas, they bear little resemblance to current polling.&lt;/li&gt;
&lt;li&gt;&quot;It could not be closer.&quot; Yes, of course, because there &lt;em&gt;are&lt;/em&gt; no numbers less than five.&lt;/li&gt;
&lt;/ul&gt;
Way to push away the constituents with half a brain, local Lib Dems.
&lt;/p&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/30671.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/30291.html</guid>
  <pubDate>Wed, 11 Apr 2007 19:38:24 GMT</pubDate>
  <title>Tumbled</title>
  <link>http://anthonybailey.net/blog/2007/04/11/tumbled</link>
  <description>&lt;strong&gt;I continue to be rather too precious about posting to my main (LiveJournal) blog.&lt;/strong&gt;&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;small&gt;(That&apos;s &lt;span class=&apos;ljuser&apos; lj:user=&apos;anthonybailey&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://anthonybailey.livejournal.com/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/userinfo.gif&apos; alt=&apos;[info]&apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://anthonybailey.livejournal.com/&apos;&gt;&lt;b&gt;anthonybailey&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; on LJ.)&lt;br /&gt;(Others should bookmark &lt;a href=&quot;http://anthonybailey.net/blog&quot;&gt;&lt;code&gt;anthonybailey.net/blog&lt;/code&gt;&lt;/a&gt;, since that should survive any change of blog provider.))&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Extravagant essays get drafted, edited and binned before publication. The posts that make it through my filters are often thoughtful, but long and infrequent. And they are quite often &lt;strike&gt;dull&lt;/strike&gt; technical in content.&lt;br /&gt;&lt;br /&gt;Most people post all kinds of junk on their blogs. They write quickly and more often. They do quick links and jokes and half-baked ideas and ephemera. They let the reader take care of extracting the signal from the noise.&lt;br /&gt;&lt;br /&gt;When its the right person, I like reading these blogs. I don&apos;t mind my friends being noisy, and I find the diamonds in the rough.&lt;br /&gt;&lt;br /&gt;So I&apos;m trying one of those kind of blogs too...&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;If you want a noisier, uncut Anthony, you may want to read this instead:&lt;/strong&gt;&lt;br /&gt;&lt;a href=&quot;http://anthonybailey.net/tumblelog&quot;&gt;&lt;big&gt;&lt;code&gt;anthonybailey.net/tumblelog&lt;/code&gt;&lt;/big&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It will get copies of everything I post to the existing blog, so you shouldn&apos;t need to read both. &lt;a href=&quot;http://anthonybailey.tumblr.com/rss&quot;&gt;Here&apos;s the feed&lt;/a&gt;. LJ people can friend &lt;span class=&apos;ljuser&apos; lj:user=&apos;antbailey_uncut&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://syndicated.livejournal.com/antbailey_uncut/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/syndicated.gif&apos; alt=&apos;[info]&apos; width=&apos;16&apos; height=&apos;16&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://syndicated.livejournal.com/antbailey_uncut/&apos;&gt;&lt;b&gt;antbailey_uncut&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;(If the terminology confuses: a &lt;a href=&quot;http://en.wikipedia.org/wiki/Tumblelog&quot;&gt;tumblelog&lt;/a&gt; is a deliberately less formal blog. It encourages posting all kinds of junk, fast! Although it doesn&apos;t stop said junk from being &lt;strike&gt;dull&lt;/strike&gt; technical in content, or physically hurt me if I don&apos;t post; so don&apos;t expect too much.)&lt;/small&gt;</description>
  <comments>http://anthonybailey.livejournal.com/30291.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/30142.html</guid>
  <pubDate>Wed, 28 Mar 2007 19:27:48 GMT</pubDate>
  <title>Quick Link: GeekDad</title>
  <link>http://anthonybailey.net/blog/2007/03/28/geekdad</link>
  <description>Sensibly, I have not myself offsprung. But, various of those who read this might be interested in &lt;a href=&quot;http://blog.wired.com/geekdad/&quot;&gt;Wired&apos;s new GeekDad blog&lt;/a&gt;.</description>
  <comments>http://anthonybailey.livejournal.com/30142.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/29792.html</guid>
  <pubDate>Thu, 08 Feb 2007 01:19:09 GMT</pubDate>
  <title>Slim Builder - an Untangled Template View</title>
  <link>http://anthonybailey.net/blog/2007/02/08/slim-builder-an-untangled-template-view</link>
  <description>&lt;p&gt;
I&apos;d like to draw attention to a pleasant way to implement the view
in &lt;abbr title=&quot;Model, View and Controller&quot;&gt;MVC&lt;/abbr&gt; web apps that
is emerging in suitably reflective and dynamic frameworks. &lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
 It doesn&apos;t
seem to have a name yet - I&apos;d suggest &quot;slim builder&quot; and/or
&quot;untangled template view&quot;. 
&lt;/p&gt;

&lt;p&gt;
The technique combines the strengths of two traditionally
distinct approaches - builders, and server page templates - and
thereby solves some of their usual problems. I&apos;ll illustrate it through an
example drawn from Rails, although you don&apos;t need to know the details
of this framework or the underlying Ruby language to get the point.
&lt;/p&gt;

&lt;p&gt;
If you do know Rails and its canon then the
example will be very familiar: it&apos;s the bookstore index page from the
&quot;depot&quot; tutorial in
&lt;a href=&quot;http://www.pragmaticprogrammer.com/title/rails2/&quot;&gt;&lt;cite&gt;Agile
Web Development with Rails&lt;/cite&gt;&lt;/a&gt;,
as of the end of section B.
&lt;/p&gt;

&lt;p&gt;
(As context for the rest of you,
&lt;a href=&quot;http://anthonybailey.net/images/pragprog_store.png&quot;&gt;here&apos;s how the page renders&lt;/a&gt;
once its style is wired up. It&apos;s simple, but will suffice for our purposes. The approaches described
all extend smoothly to more complicated layouts, Ajax updates, and so forth.)
&lt;/p&gt;

&lt;h3&gt;Templates - mark-up and code entangled in a server page&lt;/h3&gt;

&lt;p&gt;
The traditional template view works by embedding executable code fragments into
concrete mark-up. The default Rails view system uses &lt;code&gt;rhtml&lt;/code&gt;
templates processed by &lt;abbr title=&quot;embedded ruby&quot;&gt;ERb&lt;/abbr&gt;.
&lt;/p&gt;

&lt;p&gt;
Here&apos;s how we&apos;d implement the store page view. In the tutorial - as in real Rails apps
- the page gets split into different modular parts (layouts, partials, etc.) For the
sake of this example I&apos;ll inline everything into one template:
&lt;/p&gt;

&lt;div style=&quot;margin-left: 2em; border: black solid 1px; padding: 1em;&quot;&gt;
&lt;pre&gt;
&amp;lt;?xhtml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Pragprog Books Online Store&amp;lt;/title&amp;gt;
  &amp;lt;%= stylesheet_link_tag &amp;quot;depot&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot; %&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body id=&amp;quot;store&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;banner&amp;quot;&amp;gt;
    &amp;lt;img src=&amp;quot;/images/logo.png&amp;quot; alt=&amp;quot;Logo&amp;quot;/&amp;gt;
    &amp;lt;%= @page_title || &amp;quot;Pragmatic Bookshelf&amp;quot; %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div id=&amp;quot;columns&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;side&amp;quot;&amp;gt;
      &amp;lt;a href=&amp;quot;http://www....&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;a href=&amp;quot;http://www..../faq&amp;quot;&amp;gt;Questions&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;a href=&amp;quot;http://www..../news&amp;quot;&amp;gt;News&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;a href=&amp;quot;http://www..../contact&amp;quot;&amp;gt;Contact&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id=&amp;quot;main&amp;quot;&amp;gt;
      &amp;lt;h1&amp;gt;Your Pragmatic Store&amp;lt;/h1&amp;gt;
      &amp;lt;% for product in @products -%&amp;gt;
        &amp;lt;div class=&amp;quot;entry&amp;quot;&amp;gt;
          &amp;lt;img src=&amp;quot;&amp;lt;%= product.image_url %&amp;gt;&amp;quot; alt=&amp;quot;Cover&amp;quot; /&amp;gt;
          &amp;lt;h3&amp;gt;&amp;lt;%= h(product.title) %&amp;gt;&amp;lt;/h3&amp;gt;
          &amp;lt;%= product.description %&amp;gt;
          &amp;lt;span class=&amp;quot;price&amp;quot;&amp;gt;&amp;lt;%= number_to_currency(product.price) %&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;%= button_to &amp;quot;Add to Cart&amp;quot;, :action =&amp;gt; :add_to_cart, :id =&amp;gt; product %&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;% end %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
To my eyes, this kind of &lt;abbr title=&quot;Java server page&quot;&gt;JSP&lt;/abbr&gt;-inspired template is
rather ugly - it is the dirtiest plate in the default Rails stack. Angle-bracketed
web mark-up is not pretty to start with, and mixing code into it under the protection of
even more punctuation does not help matters, forming uglies such as &lt;code&gt;&amp;lt;%&lt;/code&gt;,
&lt;code&gt;&amp;lt;%=&lt;/code&gt;, and &lt;code&gt;-%&amp;gt;&lt;/code&gt;. Further, the resulting template is neither
fish nor flesh; it isn&apos;t validating mark-up, nor is it directly compilable code. Two worlds
have been messily ent-angled.
&lt;/p&gt;

&lt;p&gt;
To be fair, if you need to directly mix the two, then having the mark-up around
the code is probably a better choice than the converse. Templates rightly ousted
sequences of print statements that cobbled together strings of explicit mark-up.
Traditional entangled server page templates have a sufficient similarity to straight HTML that
tag-aware tools will do a decent job of pretty-printing and coloring them. Similarly tag-aware
but non-programming web folk can work with the template directly, especially when helper
objects have been used to minimize the size of the scary code fragments and tuck the details
safely away.
&lt;/p&gt;

&lt;p&gt;
Still, it&apos;s messy. Please do better.
&lt;/p&gt;

&lt;h3&gt;Builders - code that casts a mark-up shadow&lt;/h3&gt;

&lt;p&gt;
When I first ran across the Template View pattern in Martin Fowler&apos;s
&lt;a href=&quot;http://www.martinfowler.com/books.html#eaa&quot;&gt;&lt;cite&gt;Patterns
of Enterprise Application Architecture&lt;/cite&gt;&lt;/a&gt; I imagined it to cover exactly the case above
and no more; template views &lt;em&gt;were&lt;/em&gt; server pages.
&lt;/p&gt;

&lt;p&gt;
But a refinement of the &quot;cobbling&quot; procedure described above brings us to the builder,
which inverts the server page relationship between the tags and the code. By encapsulating all the opening
and closing of tags within helper methods, we can hide the actual mark-up whilst persisting its structure in
that of the program that knows how to build it, so that the code itself looks something like a template.
Fowler&apos;s account of the view template shows he considers builders to be a valid variant; the veteran builder
from those days was Perl&apos;s &lt;code&gt;CGI.pm&lt;/code&gt;, which is referenced (albeit briefly) in the pattern.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;CGI.pm&lt;/code&gt; builder brews tag soup by recursively nesting expressions each of which
evaluate to strings. A set of helper methods that are named after the tags they build
take a hash of options followed by further string-returning expressions to concatenate
together and enclose. Glossing over a few Perl/Rails gaps, here&apos;s how we can get &lt;code&gt;CGI.pm&lt;/code&gt;
to build up and print an expression that evaluates to the store page.
&lt;/p&gt;

&lt;div style=&quot;margin-left: 2em; border: black solid 1px; padding: 1em;&quot;&gt;
&lt;pre&gt;
#!/usr/local/bin/perl
use CGI &apos;:standard&apos;;

print(header,
  start_html(&amp;quot;Pragprog Books Online Store&amp;quot;),
             # I couldn&apos;t figure out how to supply the stylesheet
  div({-id=&amp;gt;&apos;banner&apos;},
    img({-src=&amp;gt;&amp;quot;http://localhost:3000/images/logo.png&amp;quot;, -alt=&amp;gt;&amp;quot;Logo&amp;quot;}),
    $page_title || &amp;quot;Pragmatic Bookshelf&amp;quot;
  ),
  div({-id=&amp;gt;&apos;columns&apos;},
    div({-id=&amp;gt;&apos;side&apos;},
      a({-href=&amp;gt;&amp;quot;http://www....&amp;quot;}, &amp;quot;Home&amp;quot;), br,
      a({-href=&amp;gt;&amp;quot;http://www..../faq&amp;quot;}, &amp;quot;Questions&amp;quot;), br,
      a({-href=&amp;gt;&amp;quot;http://www..../news&amp;quot;}, &amp;quot;News&amp;quot;), br,
      a({-href=&amp;gt;&amp;quot;http://www..../contact&amp;quot;}, &amp;quot;Contact&amp;quot;), br
    ),
    div({-id=&amp;gt;&apos;main&apos;},
      h1(&amp;quot;Your Pragmatic Store&amp;quot;),
      join &apos;&apos;, map {
        $product = $_;
        div({-id=&amp;gt;entry},
          img({-src=&amp;gt;$product-&amp;gt;{image_url}, -alt=&amp;gt;&amp;quot;Cover&amp;quot;},
            h3($product-&amp;gt;{title}),
            $product-&amp;gt;{description},
            span({-id=&amp;gt;&apos;price&apos;}, number_to_currency($product-&amp;gt;{price})),
            button({-action=&amp;gt;&amp;quot;add_to_cart/$product-&amp;gt;{id}&amp;quot;}, &amp;quot;Add to Cart&amp;quot;)
          )
        )
      } (@products)
    )
  ),
  end_html
);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This builder is very Perlish. It achieves high-level brevity at the cost of some low-level heavy
punctuation, as well as dragging its helpers into the global scope. We got to use some semi-functional
programming cuteness to iterate over the products within the innards of a huge expression.
This is charming if, like me, you have an old affection for the language; but even if you find Perl
distasteful I hope you&apos;ll agree &lt;code&gt;CGI.pm&lt;/code&gt; seems to have hit upon a good idea.
&lt;/p&gt;

&lt;p&gt;
The Ruby version most directly descended from &lt;code&gt;CGI.pm&lt;/code&gt; is XmlBuilder, and it&apos;s the
default builder within Rails. One change in approach is that rather than building a page as
one big expression that nests method calls and string concatenation, instead we let the building
occur as a side effect and hence write a regular sequential program with guards and iterators.
&lt;/p&gt;

&lt;p&gt;
Here&apos;s the &lt;code&gt;rxml&lt;/code&gt; template to get Rails to render the store page:
&lt;/p&gt;

&lt;div style=&quot;margin-left: 2em; border: black solid 1px; padding: 1em;&quot;&gt;
&lt;pre&gt;
xml.instruct! :xhtml, :version=&amp;gt;&amp;quot;1.0&amp;quot;, :encoding=&amp;gt;&amp;quot;UTF-8&amp;quot;
xml.html do
xml.head do
  xml.title(&amp;quot;Pragprog Books Online Store&amp;quot;)
  xml&amp;lt;&amp;lt;(stylesheet_link_tag &amp;quot;depot&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot;)
end
xml.body :id=&amp;gt;&amp;quot;store&amp;quot; do
  xml.div :id=&amp;gt;&amp;quot;banner&amp;quot; do
    xml.img :src=&amp;gt;&amp;quot;/images/logo.png&amp;quot;, :alt=&amp;gt;&amp;quot;Logo&amp;quot;
    xml.text!(@page_title || &amp;quot;Pragmatic Bookshelf&amp;quot;)
  end
  xml.div :id=&amp;gt; &amp;quot;columns&amp;quot; do
    xml.div :id=&amp;gt;&amp;quot;side&amp;quot; do
      xml.a(&amp;quot;Home&amp;quot;, :href=&amp;gt;&amp;quot;http://www....&amp;quot;); xml.br
      xml.a(&amp;quot;Questions&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../faq&amp;quot;); xml.br
      xml.a(&amp;quot;News&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../news&amp;quot;); xml.br
      xml.a(&amp;quot;Contact&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../contact&amp;quot;); xml.br
    end
    xml.div :id=&amp;gt;&amp;quot;main&amp;quot; do
      xml.h1(&amp;quot;Your Pragmatic Store&amp;quot;)
      @products.each do |product|
        xml.div :class=&amp;gt;&amp;quot;entry&amp;quot; do
          xml.img :src=&amp;gt;product.image_url, :alt=&amp;gt;&amp;quot;Cover&amp;quot;
          xml.h3(product.title)
          xml&amp;lt;&amp;lt;(product.description)
          xml.span(number_to_currency(product.price), :class=&amp;gt;&amp;quot;price&amp;quot;)
          xml&amp;lt;&amp;lt;(button_to &amp;quot;Add to Cart&amp;quot;, :action =&amp;gt; :add_to_cart, :id =&amp;gt; product)
        end
      end
    end
  end
end
end
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This is looking OK, but it isn&apos;t nice enough to move me from &lt;code&gt;rhtml&lt;/code&gt; - it&apos;s
still a bit hard to read, just from a different angle. We haven&apos;t yet reached a
&lt;abbr title=&quot;Domain Specific Language&quot;&gt;DSL&lt;/abbr&gt; for writing pages
 - web people probably couldn&apos;t work with this directly. My &lt;abbr title=&quot;Don&amp;#39;tRepeat Yourself&quot;&gt;DRY&lt;/abbr&gt; eyes are offended by some remaining duplication.
What with introducing the &lt;code&gt;xml&lt;/code&gt; builder object to scope its helpers,
this is actually more verbose as the server page.
And, there&apos;s too much punctuation (although I confess I&apos;ve not suppressed everything
I could - I&apos;m leaving some tricks for our big finish...)
&lt;/p&gt;

&lt;p&gt;
Still too massive. Let there be light.
&lt;/p&gt;

&lt;h3&gt;Slim builder untangles the template&lt;/h3&gt;

&lt;p&gt;
What happens if we throw further Ruby magic at the problem so as to slim down the 
builder?
&lt;/p&gt;

&lt;p&gt;
Markaby happens:
&lt;/p&gt;

&lt;div style=&quot;margin-left: 2em; border: black solid 1px; padding: 1em;&quot;&gt;
&lt;pre&gt;
xhtml_strict {
head {
  title &amp;quot;Pragprog Books Online Store&amp;quot; 
  stylesheet_link_tag &amp;quot;depot&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot;
}
body.store! {
  div.banner! {
    img :src=&amp;gt;&amp;quot;/images/logo.png&amp;quot;, :alt=&amp;gt;&amp;quot;Logo&amp;quot;
    text @page_title || &amp;quot;Pragmatic Bookshelf&amp;quot;
  }
  div.columns! {
    div.side! {
      a &amp;quot;Home&amp;quot;, :href=&amp;gt;&amp;quot;http://www....&amp;quot;; br
      a &amp;quot;Questions&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../faq&amp;quot;; br
      a &amp;quot;News&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../news&amp;quot;; br
      a &amp;quot;Contact&amp;quot;, :href=&amp;gt;&amp;quot;http://www..../contact&amp;quot;; br
    }
    div.main! {
      h1 &amp;quot;Your Pragmatic Store&amp;quot;
      @products.each do |product|
        div.entry {
          img :src=&amp;gt;product.image_url, :alt=&amp;gt;&amp;quot;Cover&amp;quot;
          h3 product.title
          text product.description
          span.price number_to_currency(product.price)
          button_to &amp;quot;Add to Cart&amp;quot;, :action =&amp;gt; :add_to_cart, :id =&amp;gt; product
        }
      end
    }
  }
}
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&quot;http://markaby.rubyforge.org/&quot;&gt;Markaby&lt;/a&gt; is &quot;mark-up as Ruby.&quot; It&apos;s real pretty.
&lt;/p&gt;

&lt;p&gt;
Punctuation noise is minimal. As a matter of style we&apos;ve used curlies rather than
&quot;&lt;code&gt;do ... end&lt;/code&gt;&quot; for the tag blocks, and managed to suppress almost
every bracket. This is about as clean as the structure representation could be whilst
remaining executable code. (&lt;a href=&quot;http://haml.hamptoncatlin.com/reference&quot;&gt;HAML&lt;/a&gt;
gets briefer still, including Pythonesque semantic indentation, but it only
manages this through going back to the being a template that needs
pre-processing - using a better &lt;code&gt;rhtml&lt;/code&gt; like this is an interesting alternative, though.)
&lt;/p&gt;

&lt;p&gt;
There&apos;s much handling of &lt;code&gt;method_missing&lt;/code&gt; so that method invocations can be used to
build the basic &lt;abbr title=&quot;Cascading Style Sheet&quot;&gt;CSS&lt;/abbr&gt; &lt;code&gt;class&lt;/code&gt;es and
&lt;code&gt;id&lt;/code&gt;s without needing hashes. (Like many
builders Markaby is also using further reflection to more cheaply create the tag helper
methods that these modify.)
&lt;/p&gt;

&lt;p&gt;
The builder is made implicit again by using &lt;code&gt;instance_eval&lt;/code&gt; to carry
the object&apos;s context through to its inner blocks - this avoids scope pollution without
incurring a character tax. (XmlBuilder used to turn this trick too, but because it builds
general XML the chance of confusion was considered too high and the technique was retired. As an HTML builder
Markaby suffers less, and we also get to enforce a restricted builder context so as to control
which models can be referenced by the view.)
&lt;/p&gt;

&lt;p&gt;
The code flow has been designed so that natural idioms tend to do the right thing;
appropriate encodings are implicitly applied to appropriate string arguments.
The inner details can be mysterious, but &lt;a href=&quot;http://whytheluckystiff.net/&quot;&gt;why&lt;/a&gt;
would you expect helpful magic to be otherwise?
&lt;/p&gt;

&lt;p&gt;
Talking of doing the right thing by default... Markaby was the only one of the
builders I tried that generated completely (i.e. &lt;a href=&quot;http://validator.w3.org/&quot;&gt;W3C&lt;/a&gt;)
validating mark-up out the box without any tuning. Further, it also complains if you
attempt to build such things as elements with duplicate &lt;code&gt;id&lt;/code&gt;s, or tags that
aren&apos;t allowed to self-close - this validation is a nice benefit of builders. Once armed
with a decent Ruby-aware editor working in Markaby can provide plenty of warning of
mistakes in either code or tags - the best of both worlds, keeping programmer and web designer happy.
&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;
I think this is the right approach for view building. To repeat my proposed
terminologies:
&lt;ul&gt;
&lt;li&gt;
It&apos;s an &lt;strong&gt;untangled template view&lt;/strong&gt; - all the flexibility of your regular server page
view template, but less of the mess. We&apos;ve disent&lt;strike&gt;angle&lt;/strike&gt;d the template
by collapsing mark-up into the code and outlawed all distressing pointy brackets.
&lt;/li&gt;
&lt;li&gt;
And it&apos;s a &lt;strong&gt;slim builder&lt;/strong&gt; - all the power of your regular builder but less of the mass.
The result is a &lt;abbr title=&quot;Domain Specific Language&quot;&gt;DSL&lt;/abbr&gt; for authoring web pages.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
What are the slimmest builders in other languages and frameworks?

&lt;/p&gt;</description>
  <comments>http://anthonybailey.livejournal.com/29792.html</comments>
  <category>software_development</category>
  <category>rails</category>
  <lj:mood>impressed</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>5</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://anthonybailey.livejournal.com/29525.html</guid>
  <pubDate>Sat, 27 Jan 2007 16:31:16 GMT</pubDate>
  <title>Burning time in a virtual world</title>
  <link>http://anthonybailey.net/blog/2007/01/27/burning-time-in-a-virtual-world</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;p&gt;
I had three whole weeks of holiday over Christmas/New Year, so I thought I&apos;d indulge myself enough time to play through some computer game. I was intending to catch up with a random well-regarded &lt;abbr title=&quot;First Person Shooter&quot;&gt;FPS&lt;/abbr&gt; such as &lt;a href=&quot;http://www.microsoft.com/games/halo/&quot;&gt;&lt;cite&gt;Halo&lt;/cite&gt;&lt;/a&gt;, but I couldn&apos;t seem to get into it - &lt;cite&gt;Half-Life 2&lt;/cite&gt; has made me very demanding, and I&apos;ll wait for &lt;a href=&quot;http://ep2.half-life2.com/&quot;&gt;&lt;cite&gt;Episode 2&lt;/cite&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Instead I ended up downloading a game through &lt;a href=&quot;http://www.steampowered.com/&quot;&gt;Steam&lt;/a&gt;. (This delivery system suits my lazy shop-averse needs, and seems to be working as intended: I downloaded a trailer, then the free demo, and finally bought the complete game.)
&lt;/p&gt;

&lt;div class=&quot;hreview&quot; style=&quot;width:90%&quot;&gt;
&lt;ul style=&quot;display:none&quot;&gt;
&lt;li&gt;(&lt;a href=&quot;http://microformats.org/wiki/hreview&quot;&gt;hreview&lt;/a&gt; version &lt;span class=&quot;version&quot;&gt;0.2&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;(Reviewed on &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2007-01-27T15:28:18Z&quot;&gt;27 January 2007&lt;/abbr&gt;
by &lt;a class=&quot;url fn n&quot; href=&quot;http://anthonybailey.net/&quot;&gt; &lt;span class=&quot;reviewer fn&quot;&gt;Anthony Bailey&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;type&quot; style=&quot;display:none&quot;&gt;product&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;a href=&quot;http://anthonybailey.net/images/darwinia_vector_aesthetic.jpg&quot;&gt;&lt;img alt=&quot;vector/retro graphics aesthetic&quot; align=&quot;right&quot; src=&quot;http://anthonybailey.net/images/darwinia_vector_aesthetic-thumb.jpg&quot; /&gt;&lt;/a&gt;&lt;img alt=&quot;game box cover&quot; align=&quot;right&quot; class=&quot;photo&quot; src=&quot;http://images.amazon.com/images/P/B000FDN3HE.01.THUMBZZZ.jpg&quot; /&gt;&lt;a class=&quot;item url fn&quot; href=&quot;http://www.amazon.com/gp/product/B000FDN3HE&quot;&gt;
    &lt;cite&gt;Darwinia&lt;/cite&gt;
&lt;/a&gt;
    by &lt;a href=&quot;http://www.introversion.co.uk/&quot;&gt;Introversion Software&lt;/a&gt;
&lt;blockquote class=&quot;description&quot;&gt;&lt;p&gt;
&lt;cite&gt;Darwinia&lt;/cite&gt; is a very fun and involving real-time strategy / god-game combination with a unique vector/retro graphic aesthetic.
&lt;/p&gt;

&lt;p&gt;
The evolving back story concerns a virus-infected &lt;abbr title=&quot;Artificial Intelligence&quot;&gt;AI&lt;/abbr&gt;-inhabited virtual world run on a cluster of unsellable 1980&apos;s computers (think &lt;a href=&quot;http://en.wikipedia.org/wiki/Sinclair_QL&quot;&gt;Sinclair QLs&lt;/a&gt;.) You get to wipe out the virus through various means (usually involving lasers and explosives), to gradually resurrect the world&apos;s citizens, and to direct them to work and fight to save their world.
&lt;/p&gt;

&lt;p&gt;
The game is by &lt;a href=&quot;http://www.introversion.co.uk/aboutus.html&quot;&gt;a small team&lt;/a&gt; who clearly cared a lot about it. Apart from the &lt;a href=&quot;http://www.igf.com/2006finalistswinners.html&quot;&gt;award-winning&lt;/a&gt; visual design, there&apos;s a good soundtrack and a plethora of start-up sequences. And, on completing the game you unlock its editor...
&lt;/p&gt;

&lt;p&gt;
See, I started writing this review more than a week ago, and went browsing around for background material. (There are lots of extras on the &lt;a href=&quot;http://www.darwinia.co.uk/&quot;&gt;game&apos;s official site&lt;/a&gt; - the &lt;a href=&quot;http://www.darwinia.co.uk/extras/development.html&quot;&gt;tortuous development history&lt;/a&gt; is particularly fascinating.) I found a large list of community mods. I&apos;m still playing through the first I downloaded - &lt;a href=&quot;http://forums.introversion.co.uk/darwinia/viewtopic.php?t=2753&quot;&gt;Insurrection&lt;/a&gt; - and am enjoying it as much as the original game. Involving to the point of life-consuming, then.
&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;
</description>
  <comments>http://anthonybailey.livejournal.com/29525.html</comments>
  <category>hreview</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
</channel>
</rss>
