<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
   <channel>
      <title>Zuhlke London Blogs</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=5o_exyjW3BG0F2LRCB2yXQ</link>
      <pubDate>Sat, 21 Nov 2009 19:55:51 -0800</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Innovation Games</title>
         <link>http://peripateticaxiom.blogspot.com/2009/11/innovation-games.html</link>
         <description>Next Tuesday there will be a special &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday-london.editme.com/eXtremeTuesdayClub&quot;&gt;XtC&lt;/a&gt; event at Zuhlke's office in London. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.lukehohmann.com/blog/index.php&quot;&gt;Luke Hohmann&lt;/a&gt; will be demonstrating his &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.innovationgames.com/&quot;&gt;innovation games&lt;/a&gt; for Agile teams. Should be good. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Details &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday-london.editme.com/XTC20091117&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-9149063043224656262?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-9149063043224656262</guid>
         <pubDate>Thu, 12 Nov 2009 07:16:00 -0800</pubDate>
      </item>
      <item>
         <title>Places remain at XP Day London 2009</title>
         <link>http://peripateticaxiom.blogspot.com/2009/11/places-remain-at-xp-day-london-2009.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xpday.org/&quot;&gt;XP Day London&lt;/a&gt; is filling up, but places remain. The &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xpday.org/programme&quot;&gt;programme&lt;/a&gt; is looking very good. Register &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://booking.xpday.org/registration.php&quot;&gt;here&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-7226528979665693405?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-7226528979665693405</guid>
         <pubDate>Mon, 09 Nov 2009 02:17:00 -0800</pubDate>
      </item>
      <item>
         <title>Darren on Flex: Flexins, Drag 'n' Drop Mixin now without sticky cursor and with selectable text</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/mHvpXPCjBAk/darren-on-flex-flexins-drag-n-drop.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/mHvpXPCjBAk&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-2423415475082593751</guid>
         <pubDate>Sat, 07 Nov 2009 06:39:00 -0800</pubDate>
      </item>
      <item>
         <title>Sketches</title>
         <link>http://peripateticaxiom.blogspot.com/2009/11/sketches.html</link>
         <description>One of the things I like to do in my free time is to dabble, in the most unschooled fashion imaginable, in music composition. Composing is hard. About as hard (and remarkably similar to) programming. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.schoenberg.at/default_e.htm&quot;&gt;Arnold Schoenberg&lt;/a&gt; offers this &quot;advice for self-criticism&quot; to students of composition:&lt;blockquote&gt;6. MAKE MANY SKETCHES&lt;br /&gt;Join the best sketches to produce others and improve them until the result is satisfactory.&lt;p&gt;To make sketches is a humble and unpretentious approach toward perfection. &lt;/p&gt;—&lt;em&gt;Fundamentals of Musical Composition, Ch XII&lt;/em&gt;&lt;/blockquote&gt;I think that this applies equally well to programming.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-9198354732297973865?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-9198354732297973865</guid>
         <pubDate>Tue, 03 Nov 2009 09:51:00 -0800</pubDate>
      </item>
      <item>
         <title>XP Day London 09: Programme</title>
         <link>http://peripateticaxiom.blogspot.com/2009/10/xp-day-london-09-programme.html</link>
         <description>After a lot of wrangling the almost-but-not-quite final &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday.org/programme&quot;&gt;programme for XP Day London&lt;/a&gt; is now available. Because of illness and other asynchronous distractions some of the presenters had to change at the last minute we still have to nail down one session, but this will be pretty much it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This year we have a lot of excellent experience reports from a range of practitioners who've been doing exiting new things and some really &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday.org/2009/keynotes&quot;&gt;outstanding keynotes&lt;/a&gt;.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday.org/register&quot;&gt;Register now!&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-7055025867114965092?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-7055025867114965092</guid>
         <pubDate>Mon, 19 Oct 2009 15:14:00 -0700</pubDate>
      </item>
      <item>
         <title>Scheduling by value?</title>
         <link>http://peripateticaxiom.blogspot.com/2009/10/scheduling-by-value.html</link>
         <description>David Peterson has started &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kanbanblog.com/&quot;&gt;a new blog&lt;/a&gt; on Kanban (and snaffled a very tasty URL for it). He presents &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kanbanblog.com/article/time-at-bottleneck.html&quot;&gt;this discussion&lt;/a&gt; of scheduling features into a development team. The case the David presents is related to a behaviour I sometimes see with inexperienced teams who's just had someone go learn Scrum. Comes the next planning meeting and this idea pops up that the backlog needs to be ordered by &quot;business value&quot; so that the &quot;most valuable&quot; features can be delivered earliest.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This can easily lead to some very nasty scenes where the Scrum Master demands that the Product Owner produce a &quot;value&quot; for each story—actually write a number on the card. The problem comes to a head when it turns out that the Product Owner not only doesn't know the value of the stories they are putting on the backlog, but they also have no way of finding out what they value of a story is. And this isn't because they are stupid, nor incompetent, nor malicious. It's because finding that value is far, far too difficult and time consuming an activity. And there's a good chance that any answer that came out of it would be so well hedged as to be meaningless.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes the Product Owner does know, or can find out at reasonable cost, a value for a story or feature. Being able to trade a new asset class probably can be valued. Changing a flow to give 10% high conversion probably can be valued. Improving a model to get 1% higher efficiency in the machines it's used to design can probably be valued. These valuations will be functions of time time and various other parameters. If you really have to, you could get a number of them that's valid today (and perhaps only today). David makes the point that even if you do know that number for a feature, scheduling the next one simply on the basis of highest value might not be the smartest move. There are other variables to consider. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a case to be made that within the context of a project value isn't the best figure of merit to use anyway, since someone should have made a go/no-go decision at some point that the planned budget and planned value seemed reasonable. That decision should be re-assessed frequently (far too little of this goes on) based on progress to date, and action taken if the actuals have come too far adrift, but in-between those times trying to optimise on value is perhaps not worth it. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another option is to indeed demand (and obtain) those value numbers and then &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://legalizeadulthood.wordpress.com/2009/09/04/agile-roundtable-notes-september-3rd-2009/&quot;&gt;schedule work &lt;/a&gt;&lt;i&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://legalizeadulthood.wordpress.com/2009/09/04/agile-roundtable-notes-september-3rd-2009/&quot;&gt;primarily&lt;/a&gt;&lt;/i&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://legalizeadulthood.wordpress.com/2009/09/04/agile-roundtable-notes-september-3rd-2009/&quot;&gt; on the basis of business value&lt;/a&gt; and dispense with effort estimates, so-called &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://agiletoolkit.libsyn.com/index.php?post_id=400364&quot;&gt;naked planning&lt;/a&gt;&quot;. This has &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://alistair.cockburn.us/Internal+versus+commercial+value&quot;&gt;caused eyebrows to be raised&lt;/a&gt;. The underlying claim is that&lt;/div&gt;&lt;blockquote&gt;value varies along an exponential scale while development costs vary along a linear scale. Therefore delivering the most valuable features trumps any consideration of whether or not the most valuable feature is cheap or easy to develop&lt;/blockquote&gt;whihc, if true of your environment, might give pause for though. How this interacts with the desire to schedule so as to maximise throughput at the bottleneck is an open question, for me at least.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-956763838570467765?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-956763838570467765</guid>
         <pubDate>Sun, 18 Oct 2009 06:51:00 -0700</pubDate>
      </item>
      <item>
         <title>Service-Oriented Architecture</title>
         <link>http://peripateticaxiom.blogspot.com/2009/09/service-oriented-architecture.html</link>
         <description>I'm currently embroiled in the long and fraught process of having telephony and data services installed in a certain location. One supplier steadfastly and consistently refused to respond to my offers to become a paying customer, so I selected another who were very responsive at first, but have become less and less so over time. In fact, it's about two months since I signed and still no service has been provided (although bills have been sent). &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Part of my frustration with this is that it's very hard to find out what's going on. The company, a British telecoms provider and let's leave it at that, was once a monolithic monopoly but now has been dissected into multiple different business units, components, we might almost call them, each—I suppose—focussing on its so–called Core Competence (and more on that in a later post). Each of these components has its various workflows that it does and one or more contracts with other components for services it supplies or consumes and the components communicate by passing electronic messages to one another. Sometimes they pass electronic messages to me, complete with the URL of some other component where I have to go and do some action. It's all very slick and automated and orchestrated and, indeed, seems to have a mind of its own. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For instance, the putting-in-wires component received a message telling it to come to my location and do just that. Unfortunately, the agent of the no-I-mean-really-putting-in-wires component to which they delegated implementation of that action was not able to complete it. He sent a message saying so and various exception flows kicked off, requiring a &lt;i&gt;lot&lt;/i&gt; of manual intervention, oh yes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Meanwhile, the arrange-for-telephony component turned out to have a clock running and when a certain (unpublicised) duration had elapsed without it receiving a notification of success from the putting-in-wires component (which was busy with some recovery actions on the no-I-mean-really-putting-in-wires component) it triggered a flow that cancelled my original request to have some services. A notification was received by one (but not all) of the taking-money-off-you components and one of them sent me a message telling me that my order for some services had been cancelled. A good thing, because otherwise I would have been blissfully unaware of the situation. On the other hand I am now angrily aware of the situation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, here's the fun bit: irrespective which component sends me a message, no agent working for that component can explain to me what the message means, because whatever it means that meaning belongs to whatever other component sent the earlier message that lead the the message I received being sent. And no, they can't put me through to an agent in that component. There is no interoperability layer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I spoke with five agents in three different components. One of them gave me quite the run–around because although I had contacted him through the callback given in the message I'd received from his component I had mis–configured part of my message header leading to my message being dispatched to the wrong agent because I had misunderstood the published specification for that header which he freely admitted was itself a shoddy piece of work with unreasonable and misleading contents but it was still my problem that I'd botched the message send.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, I've learned that to get to speak to an agent at all I have to go twice around the loop of failing a handshake because I can't provide a piece of data that the protocol requires but that I won't get until the request succeeds. After two failures in a row a supervisory process notices and I'm failed over to a more generic service through which I can contact an agent, but that service is not exposed on a public URL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To all of which I say: bring back the mainframe.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-2942335547606177056?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-2942335547606177056</guid>
         <pubDate>Wed, 09 Sep 2009 12:51:00 -0700</pubDate>
      </item>
      <item>
         <title>Observations on Estimation</title>
         <link>http://peripateticaxiom.blogspot.com/2009/09/observations-on-estimation.html</link>
         <description>Teams following a process like Scrum tend to estimate the &quot;size&quot; of stories as an aid to figuring out a commitment for a sprint. My view is that this is a transitional practice, and that the aim should be to learn how to make stories all roughly the same size so that commitments (also a transitional practice) can be determined by counting.&lt;br /&gt;&lt;br /&gt;While all of that is going on teams that want to use a numerical scale to estimate (rather than, say, &quot;t-shirt&quot; sizing) tend to choose a scale, a sequence of licit values from which estimates must be drawn. The various planning tools that demand a numerical field be filled in tend to force this issue.&lt;br /&gt;&lt;br /&gt;I've noticed a tendency for &quot;expert&quot; level practitioners to want to use some clever non-linear scale, maybe Fibonacci numbers (1,2,3,5,8,13), maybe a geometric series (1,2,4,8,16) and they will have some sophisticated reason why this or that series is preferred. And I've noticed that a lot of teams aren't comfortable with this. They want to use a linear scale.&lt;br /&gt;&lt;br /&gt;It seems to be traumatic enough that the estimates don't have units, or even dimensions. The idea that estimates are dimensionless but also structured can be a double cause of confusion.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Anecdote:&lt;/span&gt; a team had been estimating and planning and delivering consistently for a good long time. Their velocity was fairly constant, but drifted over time (fair enough). One day it turned out that their velocity happened to be numerically equal to the number of team members times the number of days to the next planning horizon. Someone noticed this and with a huge sigh of relief the team concluded that these mysterious &quot;units&quot; in which they estimated were actually man-days in disguise. Now they finally understood what they were estimating! And they promptly lost the ability to estimate: their next planning session was all over the place and it took some time for their planning activities to converge again. My inference was that it's actually quite important that estimates are dimensionless.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Anecdote:&lt;/span&gt; a User Experience expert at a client had been involved in some research whereby (as a side effect) members of the general public had to create a scale that made sense to them within which to rank the usability of features. These folks were presented with different generic objects and asked to give them a &quot;size&quot;, and then to give a corresponding &quot;size&quot; to some other generic objects in order to create a scale that made sense to them, which would then be applied to the merit of the system features that were the actual target of the research. They created linear scales. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[After seeing this he added the observation that this process was in aid of avoiding what often happens with the strongly disagree, disagree, no preference... type of scale which is either polarised or bland results, neither of which is that useful]&lt;br /&gt;&lt;br /&gt;That surprised me at first, since I know that the physics of our sensory apparatus are generally non-linear, and memory is non-linear and so forth. But thinking about it some more I realised that our &lt;span style=&quot;font-style:italic;&quot;&gt;experience&lt;/span&gt; tends to seem to be linear, even if the underlying phenomena aren't.&lt;br /&gt;&lt;br /&gt;Meanwhile, if one did want to use a particular scale for estimating the size of stories, why not use one of the series of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Preferred_number#Renard_numbers&quot;&gt;prefered values&lt;/a&gt;? They are very well established in engineering and product design and offer interesting error-minimising properties. On the other hand, it might be a real struggle to get a team to decide if a story was a 1.6 or a 3.15&lt;br /&gt;&lt;br /&gt;I don't have a grand narrative into wich to fit these observations, but &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/cellfish/archive/2009/10/23/never-convert-your-story-points-to-time.aspx&quot;&gt;here&lt;/a&gt; is another related anecdote about estimation.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-8251069171736387238?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-8251069171736387238</guid>
         <pubDate>Tue, 08 Sep 2009 03:09:00 -0700</pubDate>
      </item>
      <item>
         <title>Another space tourist - so what?</title>
         <link>http://aspsp.blogspot.com/2009/09/another-space-tourist-so-what.html</link>
         <description>I've just read about Guy Laliberté's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.onedrop.org/en/mission_space/poetic_social_mission.aspx&quot;&gt;Poetic Social Mission&lt;/a&gt; for the One Drop Foundation. The seventh private space traveller is doing more with his once-in-a-lifetime opportunity than just enjoying himself - he plans to stage a worldwide music and arts event involving himself aboard the ISS, to draw attention to the worldwide need for fair and equitable access to water.&lt;br /&gt;&lt;br /&gt;The guest list sounds brilliant (Peter Gabriel, U2, Shakira and many others) - the downside is that the two-hour spectacular is due to kick off at 8pm Eastern on October 9th, which makes it about 1am in our time zone. I think it's being broadcast via YouTube, so perhaps we'll be able to watch it later on? Details about this are a bit sketchy at the moment - the site just says &quot;broadcast right here&quot;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-5118194936665305394?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-5118194936665305394</guid>
         <pubDate>Sat, 05 Sep 2009 14:47:00 -0700</pubDate>
      </item>
      <item>
         <title>My Google Wave Client</title>
         <link>http://21ccw.blogspot.com/2009/08/my-google-wave-client.html</link>
         <description>Google released a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/wave-protocol/&quot;&gt;reference implementation&lt;/a&gt; of a Wave client and server in July, written in Java, that you can download and experiment with. When Mickaël Rémond wrote about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.process-one.net/en/blogs/article/using_google_wave_reference_implementation_with_ejabberd/&quot;&gt;using the reference implementation with ejabberd&lt;/a&gt;, I decided that it was time to get my hands dirty.&lt;br /&gt;&lt;br /&gt;I got the reference implementation working, and I could chat with multiple participants in the console clients. However, I wanted to know more about what was happening behind the scenes in the client, and more importantly, the server (and how operation tranforms work).&lt;br /&gt;&lt;br /&gt;So I decided to write my own client in Erlang that communicates with the reference server. This way I could investigate what was happening in the client and the server, and gain more knowledge about Wave. It required a bit of reverse engineering, and messing around with protocol buffers (the client communicates with the server using these), but it works nicely.&lt;br /&gt;&lt;br /&gt;I've created a video to demonstrate it. Happy watching!&lt;br /&gt;&lt;br /&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://vimeo.com/moogaloop.swf?clip_id=6233461&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;/iframe&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://vimeo.com/6233461&quot;&gt;Vimeo link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;P.S. I used ngerakines's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://github.com/ngerakines/erlang_protobuffs/tree/master&quot;&gt;implementation&lt;/a&gt; of Erlang prototocol buffers, and the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nitrogenproject.com/&quot;&gt;Nitrogen Web Framework.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;P.P.S. I'm going on holiday for 2 weeks, so if I don't reply to comments, please be patient. I will do so when I get back...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nitrogenproject.com/&quot;&gt; &lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-3951992122970155328?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-3951992122970155328</guid>
         <pubDate>Sun, 23 Aug 2009 01:40:00 -0700</pubDate>
      </item>
      <item>
         <title>Real Engineers</title>
         <link>http://peripateticaxiom.blogspot.com/2009/08/real-engineers.html</link>
         <description>There's a recurring fashion for beating up those who would build software for a living with tales of how &quot;real&quot; engineers do it. This started with the woefully misguided &quot;Software Engineering&quot; conferences of the late 1960's and continues on-and-off to this day.&lt;br /&gt;&lt;br /&gt;As a response to this I like to collect examples of &quot;real&quot; engineers screwing up. Not out of malice, but out of a desire to ground certain aspects of my professional life in something resembling fact. Here are&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.washingtonpost.com/wp-dyn/content/article/2009/07/09/AR2009070903020.html&quot;&gt; some reported facts&lt;/a&gt; about the Lockheed Martin F-22 &quot;Raptor&quot; fighter aircraft:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;the aircraft has recently required more than 30 hours of maintenance for every hour in the skies&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the canopy needs refurbishing after 331 hours of flying, less than half the design goal of 800 hours, and this costs $120,000 a pop&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the aircraft is almost twenty thousand dollars more expensive to fly &lt;i&gt;per hour&lt;/i&gt; than its predecessor (which costs an already eye-watering 30+ grand per hour—what do they run on, Chanel No 5? Single malt whisky?)&lt;/li&gt;&lt;/ol&gt;And so on. Just to add to the fun, the development cycle for this aircraft was so long that the class of mission for which it was designed &lt;i&gt;no longer takes place&lt;/i&gt;.Is this the fault of the folks at Lockheed Martin? Not really. It's the fault of a system that put politics ahead of engineering, a circumstance under which no-one can be successful.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-6747627483747581074?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-6747627483747581074</guid>
         <pubDate>Mon, 17 Aug 2009 14:22:00 -0700</pubDate>
      </item>
      <item>
         <title>Change</title>
         <link>http://peripateticaxiom.blogspot.com/2009/08/change.html</link>
         <description>We aim to keep all our offices ISO 9000 certified. This means updating the procedures to reflect our increasing tendency to run software development projects under an Agile process. It's fallen to me to update our existing &quot;Change Control&quot; procedure which of its kind is very good, but does build up from the assumption that to have a change to control is an exceptional (although expected) event. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I keep wanting to turn that inside out and say—deal with &lt;i&gt;every&lt;/i&gt; requirement this way, make this the default, make the threshold of cost/schedule/risk impact for triggering change control be 0.0 in all cases, have the Change Control Board meet every week, have them assess the impact of every item and decide whether or not to schedule it, have no other way to schedule any activity than via the change log. And bingo! Your project would pretty much be agile.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In fact, I might just do that.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-3762170785622192226?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-3762170785622192226</guid>
         <pubDate>Tue, 11 Aug 2009 01:34:00 -0700</pubDate>
      </item>
      <item>
         <title>Save Bletchley Park with Boffoonery!</title>
         <link>http://aspsp.blogspot.com/2009/08/save-bletchley-park-with-boffoonery.html</link>
         <description>&lt;p&gt;The title says it all really.&lt;/p&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.codemanship.com/&quot;&gt;Jason Gorman&lt;/a&gt; has managed to get some amazing events off the ground in the past couple of years and this one should be absolutely excellent. It's called &lt;b&gt;Boffoonery!&lt;/b&gt; (&quot;buffoonery for boffins&quot;) - a once-only comedy benefit gig to raise money for the extremely important &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.bletchleypark.org/&quot;&gt;wartime heritage site&lt;/a&gt; (Station X) and unique &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tnmoc.org/&quot;&gt;computing museum&lt;/a&gt; that is &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boffoonery.com/about.html&quot;&gt;Bletchley Park&lt;/a&gt; near Milton Keynes.&lt;/p&gt;&lt;p&gt;Jason's partners in crime are comedy writer James Cary, whose credits include hit TV comedies like My Hero and My Family and who also writes the cult BBC Radio 4 sitcom Hut 33, which is set at Bletchley Park, and veteran TV and radio comedy producer David Tyler.&lt;/p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tnmoc.org/UserFiles/image/home-img2.png&quot;&gt;&lt;img style=&quot;float:right;margin:0 0 10px 10px;cursor:pointer;cursor:hand;width:99px;height:99px;&quot; src=&quot;http://www.tnmoc.org/UserFiles/image/home-img2.png&quot; border=&quot;0&quot; alt=&quot;&quot;/&gt;&lt;/a&gt;&lt;p&gt;The show is still taking shape, but Jason is delighted to be able to confirm that Robert Llewellyn (Red Dwarf), Richard Herring (Fist Of Fun, This Morning With Richard Not Judy) and cerebral stand-up Robin Ince are on the bill. More big name comedians and comedy writers are TBA, so keep en eye out for updates.&lt;/p&gt;&lt;p&gt;The best way we can support Bletchley Park is to send a message to government and funding bodies about how much we care. If the show were to sell out, and sell out quickly, that would send a very clear message indeed.&lt;/p&gt;&lt;p&gt;And since you ask - yes, you can help. Tickets go on sale on Wednesday Aug 12th at 9am. Please help to spread the word and create a splash on Wednesday. Here are some of the ways you can help:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Buy your tickets on Aug 12th&lt;/li&gt;&lt;li&gt;Tell your friends and colleagues about Boffoonery!, and encourage them to buy their tickets on Aug 12th&lt;/li&gt;&lt;li&gt;Print off copies of the show's A4 poster, which you can download from &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boffoonery.com/&quot;&gt;www.boffoonery.com&lt;/a&gt;, and stick them up on your noticeboards at work&lt;/li&gt;&lt;li&gt;Blog about Boffoonery, and pass on these suggestions about how people can help save Bletchley Park&lt;/li&gt;&lt;li&gt;If you're a Twitter user, on the morning of Aug 12th send a tweet about #boffoonery and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boffoonery.com/&quot;&gt;www.boffoonery.com&lt;/a&gt;, and RT any #boffoonery tweets that cross your path&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It's going to be brilliant evening, and your kindness and generosity will ensure that generations to come will be able to see and experience the achievements of those brilliant boffins whose ingenuity saved 22 million lives and ushered in the information age.&lt;/p&gt;&lt;p&gt;You can find out more by visiting &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boffoonery.com/&quot;&gt;www.boffoonery.com&lt;/a&gt;, or following #boffoonery on Twitter or &quot;boffoonery&quot; on Facebook.&lt;/p&gt;&lt;div&gt;A pity there isn't a theatre big enough in Bletchley Park itself to host this event! That said, the Bloomsbury Theatre is easier for me to get to...&lt;/div&gt;&lt;p&gt;Don't forget: tickets go on sale on 12th August 2009 at 9am and the show takes place on Tuesday Nov 3rd.&lt;/p&gt;&lt;p&gt;PS other efforts to support the National Museum of Computing at Bletchley Park include this amazing &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://stnx.at/&quot;&gt;URL Shortener&lt;/a&gt; called &lt;b&gt;Station X&lt;/b&gt;. Keep up the good work, guys!&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-8153034482690004216?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-8153034482690004216</guid>
         <pubDate>Wed, 05 Aug 2009 14:58:00 -0700</pubDate>
      </item>
      <item>
         <title>De–skilling through Technology: friend and foe</title>
         <link>http://peripateticaxiom.blogspot.com/2009/08/deskilling-through-technology-friend.html</link>
         <description>Once, and for a mercifully short time, I lived on the very western edge of Bournemouth. You might recall that Ford considered his article for the &lt;i&gt;Guide&lt;/i&gt; describing how to have a good time in Bournemouth to be one of his finest pieces of fiction. So, I was often wanting to go away, farther away than I could sensibly go on my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.royal-enfield.com/&quot;&gt;pseudo-vintage motorcycle&lt;/a&gt; in what time was available. That meant going&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://maps.google.com/maps?f=d&amp;amp;source=s_d&amp;amp;saddr=Westbourne+Park+Rd&amp;amp;daddr=Unknown+road&amp;amp;hl=en&amp;amp;geocode=FcrnBQMd4-ni_w%3BFRcIBgMdr43j_w&amp;amp;mra=ls&amp;amp;sll=50.722791,-1.888833&amp;amp;sspn=0.016763,0.033345&amp;amp;ie=UTF8&amp;amp;z=14&quot;&gt; from the County Gates to Bournemouth railway station&lt;/a&gt;. This could be done on the cramped, slow local bus or at great expense by taxi. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But I noticed that the long–distance coaches coming in from the even further south and west of England made one last stop before Bournemouth Coach Station (adjacent to the railway station) in Westbourne, just around the corner from me. These coaches are large, have luggage space and go fast on major roads. And the on–line booking system did not blink an electronic eye at me buying and downloading to print out a 90 pence ticket to ride from Westbourne to Bournemouth. The drivers of the coaches did blink when I got on there, but I had a ticket so they shrugged and went about their business. That's nice. Imagine the counter–arguments that would likely come from a human ticket agent who knows only too well the various alternatives to doing so preposterous a thing as riding a long–haul coach half–way across the town where you live.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, much more recently I was on the very edge of the very agreeable city of Charlotte, North Carolina. I had been down–town to check out the excellent &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mintmuseum.org/&quot;&gt;Mint Museum&lt;/a&gt;. Being a citizen of the Socialist People's Republic of Europe I naturally tried to do the journey by public transport. Charlotte has a pretty good public transport system, C.A.T.S. However, it turned out that the bus service that would otherwise run from exactly the last stop of the light rail system (the &quot;Lynx&quot;) to exactly my hotel was not running that day. Nice try, but I have to do the last few miles by cab. Now, I am a stranger to the city and am in any case in a fairly obscure part of it. I call a cab company and while I can explain with a certain degree of accuracy where I want to &lt;i&gt;go&lt;/i&gt;, I don't know where I &lt;i&gt;am&lt;/i&gt;. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And that's a problem. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The cabs are guided by GPS, so they need an exact street address for pickup and set down. This is so that the drivers do not need to know their way around. That's a pretty shocking concept for a resident of London, where cab drivers &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tfl.gov.uk/businessandpartners/taxisandprivatehire/1412.aspx&quot;&gt;know their way around&lt;/a&gt; so well &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pnas.org/content/97/8/4398.full&quot;&gt;it changes their brains&lt;/a&gt;. Troublesome de–skill #1.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All I know is that I'm at the last stop of the Blue Line, but I don't know where that is. And neither does the dispatcher at the cab company—after all, all they do is pass on the co–ordinates of two places they don't know the location of to drivers who don't know the route between them. De–skill #2. Luckily for me, the dispatcher thought that they knew someone who might be able to figure out where this Lynx station was. I should call back in a few minutes. I do so, and by virtue of the elevated situation of the station I can call off enough landmarks (that is, names of shopping malls) for this person at the other end to work out where I am. My hotel, for some reason, they can look up very easily.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some time later a cab rolls up. And it turns out that all this marvellous de–skilling has been wasted because the guy is a veteran driver and knows the district like the back of his hand.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, once I'm seated and strapped in, his first question is: &lt;i&gt;so, where are we going?&lt;/i&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-6456101729279924044?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-6456101729279924044</guid>
         <pubDate>Tue, 04 Aug 2009 13:37:00 -0700</pubDate>
      </item>
      <item>
         <title>Gimme Shelter</title>
         <link>http://aspsp.blogspot.com/2009/07/gimme-shelter.html</link>
         <description>A friend has been made homeless - as a result of a bout of illness, he got behind with his rent payments. One morning his landlord just turned up with a heavy friend and dumped him and most of his belongings outside without a key.&lt;br /&gt;&lt;br /&gt;While this is clearly an illegal eviction (the landlord should have taken the court route), my friend is unable to defend himself because he's still not well and besides, he's sure that no-one will believe his version of events. Well, it is fairly monstrous.&lt;br /&gt;&lt;br /&gt;Today he rang &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.shelter.org.uk/&quot;&gt;Shelter&lt;/a&gt; to try to obtain help (having already had a pretty hopeless interview with the emergency housing office in his borough - they took the attitude that since he didn't have a court order evicting him, he must have made himself intentionally homeless). He reports that he got an answerphone message that began &quot;Welcome to Shelter. Please note that &lt;span style=&quot;font-weight:bold;&quot;&gt;we cannot provide accommodation&lt;/span&gt;...&quot;&lt;br /&gt;&lt;br /&gt;Well, what on Earth is Shelter for then?&lt;br /&gt;&lt;br /&gt;I am also disappointed that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.salvationarmy.org.uk/&quot;&gt;The Salvation Army&lt;/a&gt; was unwilling to help him - I have been supporting it with a regular monthly donation for years as I was under the impression that it provided help to the homeless.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-4160166869086850417?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-4160166869086850417</guid>
         <pubDate>Mon, 27 Jul 2009 02:36:00 -0700</pubDate>
      </item>
      <item>
         <title>Passwords passé?</title>
         <link>http://aspsp.blogspot.com/2009/07/passwords-passe.html</link>
         <description>I've just read a highly amusing and (for Twitter) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.basexblog.com/2009/07/16/google-apps-twitter-hack-raises-red-flags-on-password-security/&quot;&gt;embarrassing story&lt;/a&gt; about the loss of confidential information stored by a Twitter staffer under Google Apps.&lt;br /&gt;&lt;br /&gt;The article closes by trotting out the usual advice about making usernames and passwords secure - make them long and cryptic, don't use the same credentials for more than one service, and don't write them down. However, I heard a piece on BBC Radio 4 not long ago in which Damian Grammaticus investigated computer security and hacking. It showed that any Windows password under 14 characters long could be cracked in seconds, regardless of how many punctuation characters and digits it contained. Since we're all forced to register with dozens, if not hundreds of different IT services on the Internet and our employers' networks, it simply isn't possible for standard-issue mortals to memorise that many cryptic usernames and passwords (particularly where IT policy demands that the password be changed regularly).&lt;br /&gt;&lt;br /&gt;Common approaches to overcome these wetware limitations include&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Writing usernames and passwords down - not recommended because anyone could find them and steal your precious secret information&lt;/li&gt;&lt;li&gt;Using a standard username and password for many different sites - again not recommended because if a thief finds out one valid combination, (s)he can access all your accounts&lt;/li&gt;&lt;li&gt;Generating usernames and passwords by means of some function, which you can compute mentally without too much effort and which preferably takes the current month and/or the URL of the service as parameters - this works OK in certain situations, but because the algorithm can't be terribly complicated, someone could reverse-engineer it and have access to all your accounts&lt;/li&gt;&lt;li&gt;Using a password manager application: something that you install on your laptop (say) and which stores all your usernames and passwords for you, encrypted of course, so that you can only gain access using a master password or even biometric authentication - disadvantages may include the risk of losing the device or the master access key, as well as the inconvenience of having to have the device to hand whenever you need one of your account credentials (not to mention the cost of the password manager itself)&lt;/li&gt;&lt;li&gt;Trusting an Internet service such as DataInherit to manage the keys for you, which has the advantage that should you die or be incapacitated, a nominated person or persons can automatically be given access to selected accounts in your portfolio - disadvantages include the price and the number of steps you have to go through to retrieve any given username and password&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Surely the time is ripe for a security architecture that fully separates authentication from authorisation. Depending on your spending power and level of paranoia, you could procure authentication services from any reputable trust authority of your choosing, which could make use of a single very secure identifier and pass phrase, optionally combined with more stringent authentication factors such as digital certificates, RSA SecurID devices, or even biometrics. The identity thus established would be securely and trustworthily conveyed to whatever service you were trying to access - regardless of whether it is on a company intranet, the public Internet or your ATM network.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Unfortunately the Twitters and Googles of this world, not to mention the myriad online shopping sites, still want you to register with them directly and not with some third-party authentication provider. This is because they believe that there's value in knowing your real world (meatspace) name and address, age, marital status and what have you so that they can push targeted marketing at you. It doesn't seem to bother them that the majority of the data thus gathered is probably untrue, because most Internet users are paranoid about giving away such information.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I want single sign-on to be ubiquitous, effortless, virtually unhackable and foolproof (as well as heritable, as directed by me, when I leave this world, so that my digital assets are not locked away forever). By &quot;ubiquitous&quot;, I mean that I should be able to use the same sign-on for my employer's network as for any client's network which wants to authorise me to access some selection of their IT services, for Internet services on which I register and preferably at the bank's ATM too. By &quot;effortless&quot;, I mean that authenticating myself to all these services is necessary only once per computer per day and ideally doesn't require me to memorise anything, or at most one thing. A physical token in addition, or a biometric, would be acceptable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The theoretical foundations already exist, underpinning such standards as &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Kerberos_(protocol)&quot;&gt;Kerberos&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/WS-Trust&quot;&gt;WS-Trust&lt;/a&gt;. But to make it work in the real world of competing and highly disparate IT services, the community of service providers would need to discover some kind of shared interest in implementing it as standard. A &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bcs.org/server.php?show=conWebDoc.2844&quot;&gt;grand computing challenge&lt;/a&gt; for the new millennium, perhaps?&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-1083907608671303711?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-1083907608671303711</guid>
         <pubDate>Mon, 20 Jul 2009 06:48:00 -0700</pubDate>
      </item>
      <item>
         <title>HOWTO: Configure Apache+Passenger with HTTPS/SSL</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/WNYQBf2FjxE/howto-configure-apachepassenger-with.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/WNYQBf2FjxE&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-4992435604832384068</guid>
         <pubDate>Tue, 14 Jul 2009 08:21:00 -0700</pubDate>
      </item>
      <item>
         <title>Finish-start Dependencies: just say no!</title>
         <link>http://peripateticaxiom.blogspot.com/2009/07/finish-start-dependencies-just-say-no.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://1.bp.blogspot.com/_itmSz8f6ak4/SlkqxDXtYVI/AAAAAAAAABk/gJv-IboEpCY/s1600-h/serial.png&quot; style=&quot;text-decoration:none;&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:258px;height:259px;&quot; src=&quot;http://1.bp.blogspot.com/_itmSz8f6ak4/SlkqxDXtYVI/AAAAAAAAABk/gJv-IboEpCY/s320/serial.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5357360253940621650&quot;/&gt;&lt;/a&gt;I'm working with a team that have (as do we all) a tendency when under stress to fall back upon what they are comfortable with—in particular, to serialising their activities. &quot;We can't &lt;i&gt;x&lt;/i&gt; because they haven't finished &lt;i&gt;y&lt;/i&gt; because they're waiting for &lt;i&gt;z&lt;/i&gt;...&quot;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To help them remember that this isn't the best move they can make, I've devised this symbol to display in the team area. You are welcome to use it yourself.&lt;/div&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://creativecommons.org/licenses/by-nc-sa/2.0/uk/&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width:0;&quot; src=&quot;http://i.creativecommons.org/l/by-nc-sa/2.0/uk/88x31.png&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;span&gt;No Serialised Activities&lt;/span&gt; by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/2009/07/finish-start-dependencies-just-say-no.html&quot;&gt;Keith Braithwaite&lt;/a&gt; is licensed under a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://creativecommons.org/licenses/by-nc-sa/2.0/uk/&quot;&gt;Creative Commons Attribution-Noncommercial-Share Alike 2.0 UK: England &amp;amp; Wales License&lt;/a&gt;.&lt;br /&gt;Based on a work at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://1.bp.blogspot.com/_itmSz8f6ak4/SlkqxDXtYVI/AAAAAAAAABk/gJv-IboEpCY/s1600-h/serial.png&quot;&gt;1.bp.blogspot.com&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-5934617020963863030?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-5934617020963863030</guid>
         <pubDate>Sat, 11 Jul 2009 18:00:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://1.bp.blogspot.com/_itmSz8f6ak4/SlkqxDXtYVI/AAAAAAAAABk/gJv-IboEpCY/s72-c/serial.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Google OS - I believe I was right</title>
         <link>http://21ccw.blogspot.com/2009/07/google-os-i-believe-i-was-right.html</link>
         <description>&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size:small;&quot;&gt;disclosure: I own Google shares&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;I'm not one for blowing my own trumpet, but sometimes it feels good to be right. A month ago I &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2009/06/look-out-rias-html5-is-coming.html&quot;&gt;blogged&lt;/a&gt; about HTML5, and I said the following:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&quot;I believe it is part of Google's long term strategy to make the browser the de-facto application platform. To displace Windows as the dominant aplication platform. You can see it already with Chrome, how the tabs on the browser have become the new taskbar, and the integration of browser tabs as &quot;applications&quot; into the host OS. For example, features like local file storage and the canvas provide a path for Google Docs to become more like MS Office. You can be sure that some of the drive behind the HTML5 standard is coming from the Google docs team.&quot;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;Yesterday Google announced Google OS: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://googleblog.blogspot.com/2009/07/introducing-google-chrome-os.html&quot;&gt;http://googleblog.blogspot.com/2009/07/introducing-google-chrome-os.html&lt;/a&gt;. Google OS will be based on Chrome and a Linux kernel. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the announcement:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&quot;For application developers, the web is the platform. All web-based applications will automatically work and new applications can be written using your favorite web technologies. And of course, these apps will run not only on Google Chrome OS, but on any standards-based browser on Windows, Mac and Linux thereby giving developers the largest user base of any platform.&quot;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;I will admit that I didn't think they would actually write an OS to support this strategy, but the strategy is clear. Unfortunately we'll have to wait at least a year to see it in action...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-6202057611761079672?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-6202057611761079672</guid>
         <pubDate>Tue, 07 Jul 2009 19:04:00 -0700</pubDate>
      </item>
      <item>
         <title>How can I set up an editor to work with Git on Windows?</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/oWmeQDcTpNk/how-can-i-set-up-editor-to-work-with.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/oWmeQDcTpNk&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-6942170621710034785</guid>
         <pubDate>Sun, 05 Jul 2009 03:57:00 -0700</pubDate>
      </item>
      <item>
         <title>Learning from Architects</title>
         <link>http://peripateticaxiom.blogspot.com/2009/07/learning-from-architects.html</link>
         <description>From dog–houses to skyscrapers, the discipline of the building architect has long been a rich source of metaphor for system architects. I don't disagree, indeed in one of my contributions to the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.co.uk/Things-Every-Software-Architect-Should/dp/059652269X&quot;&gt;97 Things Every Software Architect Should Know&lt;/a&gt; I recommended that software architects should &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki/Learn%20from%20Architects%20of%20Buildings&quot;&gt;learn from architects of buildings&lt;/a&gt;. So, you can imagine that my eye was caught by Matthew Frederick's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.co.uk/101-Things-Learned-Architecture-School/dp/0262062666/&quot;&gt;101 Things I Learned in Architecture School&lt;/a&gt;. This small book contains the eponymous count of hints, tips and tricks from a qualified architect to architecture students. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a good resource for those of us who would learn from architects of buildings, as it is advice to would–practitioners from a practitioner and as such relates to what building architects actually do, rather than what someone who isn't a practitioner thinks they must, surely, do. This latter is a common failure mode of software professionals seeking inspiration from other disciplines—all the way back to the very first Software Engineering conferences of the late 1960's, in which an hallucinatory notion of what &quot;engineers&quot; do was foisted upon us. But I digress.&lt;div&gt;&lt;br /&gt;&lt;div&gt;Some of the 101 are very low level and very specific (eg &lt;b&gt;Number 90&lt;/b&gt; &quot;Roll your drawings for transport or storage with the image side facing out&quot;), others are much broader and seem to me to have relevance for any sort of design work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 15&lt;/b&gt; tells us that &quot;A &lt;i&gt;parti&lt;/i&gt; is the central idea or concept of a building.&quot; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Parti&quot;&gt;Wikipedia&lt;/a&gt; tells us that &lt;i&gt;parti&lt;/i&gt; is from the French &lt;i&gt;prendre parti&lt;/i&gt; &quot;to make a decision&quot;. The &lt;i&gt;parti&lt;/i&gt; captures, presents and summarises the highest level decision that has been made about the organising principle of an entire building or building project, and examples are given where the &lt;i&gt;parti&lt;/i&gt; expresses all that in one, highly abstract, diagram. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A &lt;i&gt;parti&lt;/i&gt; sounds to me a lot like a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://c2.com/xp/SystemMetaphor.html&quot;&gt;system metaphor&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 100&lt;/b&gt; tells us that the &lt;i&gt;parti &lt;/i&gt;should have a name, such as &quot;half–eaten donut&quot; or &quot;meeting of strangers&quot;. Could the nominal (or de facto [&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.blogger.com/post-edit.g?blogID=23912478&amp;amp;postID=2196042387143936336#arch&quot;&gt;*&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; id=&quot;arch-back&quot;&gt;&lt;/a&gt;]) architect of the system that you are working on draw such a diagram? Would it tell anyone anything if they did? Could they name the &lt;i&gt;parti&lt;/i&gt;, the very highest level design decision from which the rest of the system design flows?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 28&lt;/b&gt; tells us that a good designer isn't afraid to throw away a good idea. Notice: a &lt;i&gt;good&lt;/i&gt; idea. An idea can be good and not fit with the &lt;i&gt;parti&lt;/i&gt;, in which case it has no place in the design. We are advised to &quot;save [...] good but ill–fitting ideas for another time and project—and with the knowledge that they might not work then, either.&quot; When was the last time you (or your team) threw out a good idea? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 46 &lt;/b&gt;tells us to &quot;Create architectural richness through &lt;i&gt;informed simplicity&lt;/i&gt; or an &lt;i&gt;interaction of simples &lt;/i&gt;rather than through unnecessarily busy agglomerations&quot;. Frederick warns particularly against &quot;busying up a project with doodads because it is boring without them; agglomerating many unrelated elements without concern for their unity because they are interesting in themselves.&quot; What interesting doodads does your current project have?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One reason to follow the guidance of Number 46 is given in &lt;b&gt;Number 51&lt;/b&gt;, which observes that &quot;Beauty is due more to the harmonious relationships among the elements of a composition than to the elements themselves&quot;. One achieves this beauty through a design process, or system.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 77&lt;/b&gt; cautions that &quot;No design system is or should be perfect. Designers are often hampered by a well–intentioned by erroneous belief that a good design solution is perfectly systematic [...] but nonconforming oddities can be enriching, humanising aspects of your project.&quot; 77 also observes that &quot;exceptions to the rule are often more interesting that the rules themselves.&quot;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 81&lt;/b&gt; notes that &quot;Properly gaining control of the design process tends to feel like one is &lt;i&gt;losing&lt;/i&gt; control of the design process&quot; 81 advises that the designer should &quot;accept uncertainty. Recognise as normal the feeling of lostness that attends to much of the process. Don't seek to relieve your anxiety by marrying yourself prematurely to a design solution; design divorces are never pretty&quot; No, they never are. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Number 99&lt;/b&gt; can help. It says &quot;Just do something. [...] don't wait for clarity to arrive before beginning to draw. Drawing is not simply a way of depicting a design solution; it is itself a way of learning about the problem you are trying to solve.&quot; I think that much the same can be said for coding. Are the design procedures in your team aligned with these principles? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[&lt;a rel=&quot;nofollow&quot; id=&quot;arch&quot;&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.blogger.com/post-edit.g?blogID=23912478&amp;amp;postID=2196042387143936336#arch-back&quot;&gt;*&lt;/a&gt;] Even the most self–organised, most cross–functional, most Agile, most collectively–code–owning software development team will have one individual who knows most about (and likely has most influence over) the architecture of the system. You can pretend otherwise, or you can take advantage of it.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-2196042387143936336?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-2196042387143936336</guid>
         <pubDate>Sat, 04 Jul 2009 14:14:00 -0700</pubDate>
      </item>
      <item>
         <title>Erlang Factory 2009 - New Kids on the Erlang Block</title>
         <link>http://21ccw.blogspot.com/2009/07/erlang-factory-2009-new-kids-on-erlang.html</link>
         <description>&lt;div style=&quot;text-align:left;&quot;&gt;I went to Erlang Factory again this year thanks to my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.zuhlke.co.uk/&quot;&gt;employer&lt;/a&gt;, and it was even more exciting than &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2008/07/notes-from-erlang-exchange.html&quot;&gt;last year's&lt;/a&gt; event. There were some great speakers (Joe Armstrong - entertaining as ever, Simon Peyton Jones), I got to meet some interesting people (e.g. Rusty Klophaus, creator of the Nitrogen web framework) and I got to see some awesome projects. Although Erlang is experiencing a surge of interest, it is by no means &quot;new&quot;. it has been used for years in robust and highly scalable applications. That is why I refer to the &quot;new&quot; - as opposed to the solid Erlang VM, tools, libraries and frameworks that have been around for at least a decade.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, wo are these the New Kids on the Block? These guys?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;http://1.bp.blogspot.com/_bXDgUoT7V7o/Sk4AeAT0K7I/AAAAAAAAANA/5lDV0iMS_V8/s400/newkids3.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5354217522469284786&quot; style=&quot;display:block;margin-top:0px;margin-right:auto;margin-bottom:10px;margin-left:auto;text-align:center;cursor:pointer;width:320px;height:320px;&quot;/&gt;&lt;/div&gt;&lt;div style=&quot;text-align:left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:left;&quot;&gt;Nice hair! No, not them. Here are some of the New Kids on the Erlang Block:&lt;/div&gt;&lt;div style=&quot;text-align:left;&quot;&gt;&lt;div style=&quot;text-align:left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:left;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(0, 0, 238);&quot;&gt;&lt;img src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/Sk4EEAp6KfI/AAAAAAAAANo/dSLaROLb6oA/s400/collage.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5354221473931864562&quot; style=&quot;display:block;margin-top:0px;margin-right:auto;margin-bottom:10px;margin-left:auto;text-align:center;cursor:pointer;width:400px;height:332px;&quot;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(0, 0, 238);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align:left;&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://heroku.com/&quot;&gt;Heroku&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Heroku is a platform for deploying Ruby or Rails web apps. They've built their routing mesh in Erlang. This &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://heroku.com/how/architecture&quot;&gt;routing mesh&lt;/a&gt; is used to load-balance and route requests to their application work units (dynos). This is a really cool piece of cloud infrastructure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.hypernumbers.com/&quot;&gt;HyperNumbers&lt;/a&gt;&lt;/div&gt;&lt;div&gt;HyperNumbers is a startup that is &quot;doing for numbers what hypertext did for text&quot;. Think GoogleDocs, but each cell can be a resource that's located on another spreadsheet. Coming soon.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://couchdb.apache.org/&quot;&gt;CouchDB&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://couchdb.apache.org/&quot;&gt;&lt;/a&gt;CouchDB is a non-relational document database written in Erlang, and it is going from strength to strength. Look at this &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/trends?q=couchdb&quot;&gt;graph&lt;/a&gt; from Google Trends:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/Sk4BZxgLNvI/AAAAAAAAANQ/y_IRGWiCzsA/s400/couchdd_trend.png&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:400px;height:203px;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5354218549286745842&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you don't know what CouchDB is, you should definitely have a look it. Even is it's just to make you challenge you preconceptions around databases, and relational ones in particular. There is also a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://books.couchdb.org/relax/&quot;&gt;book &lt;/a&gt;coming out soon. It's open source.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt;&lt;/div&gt;&lt;div&gt;RabbitMQ is an open source, high-performance enterprise messaging system, and an implementation of the messaging standard AQMP. It is written in Erlang. I've heard rumors that ActiveMQ (Java) has 20 times more lines of code. (NB: If anyone can give me a reference or link to proof I would be grateful). &lt;span class=&quot;Apple-style-span&quot; style=&quot;color:#FF0000;&quot;&gt;Update: See comments for line counts.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nitrogenproject.com/&quot;&gt;Nitrogen Web Framework&lt;/a&gt;&lt;/div&gt;&lt;div&gt;This is my favourite web framework. It's a real Web 2.0 framework, and it's highly productive. Some of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nitrogenproject.com/web/learn&quot;&gt;main features&lt;/a&gt; are:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Event-Driven Development&lt;/li&gt;&lt;li&gt;Brainlessly Easy Ajax&lt;/li&gt;&lt;li&gt;Ridiculously Simple Comet&lt;/li&gt;&lt;li&gt;Complex Interfaces: Dragging, Dropping, and Sorting&lt;/li&gt;&lt;li&gt;Flexible Templating&lt;/li&gt;&lt;li&gt;Data Binding&lt;/li&gt;&lt;li&gt;Erlang Power&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;I've used this to create my own pet Erlang project, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.opinion8r.com/&quot;&gt;opinion8r.com&lt;/a&gt;. Check it out. It's also open source.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.smarkets.com/&quot;&gt;Smarkets&lt;/a&gt;&lt;/div&gt;&lt;div&gt;I didn't go to this talk, but I've been to one given last year at the Erlang London User group. Smarkets is an online betting exchange which allows users to bet on anything they wish. It is implemented in Erlang and close to launch.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://campfirenow.com/&quot;&gt;Campfire&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Campfire is one of the applications from the guys at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.37signals.com/&quot;&gt;37Signals&lt;/a&gt;. If you don't know who 37 Signals are, they created Ruby on Rails. The functional C polling for Campfire service that was being used was replaced by an Erlang implementation:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(0, 0, 238);&quot;&gt;&lt;img src=&quot;http://1.bp.blogspot.com/_bXDgUoT7V7o/Sk4CNBqc-_I/AAAAAAAAANY/Phjz8_7XTfI/s400/campfire.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5354219429798149106&quot; style=&quot;display:block;margin-top:0px;margin-right:auto;margin-bottom:10px;margin-left:auto;text-align:center;cursor:pointer;width:400px;height:155px;&quot;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Erlang implementation is as fast as the C implementation, modular and extensible, and much easier to administer with 1 OS process instead of 80.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.process-one.net/en/&quot;&gt;ProcessOne&lt;/a&gt; - OneTeam Media Server&lt;/div&gt;&lt;div&gt;&quot;OneTeam Media Server is a new project launched by ProcessOne which is a Media server for Flash clients implementing the FLV and RTMP protocol. The project is designed so that it can work hand in hand with ejabberd, ProcessOne Instant Messaging platform.&quot;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This one is very exciting. The media server has Flash in the front end, and Erlang in the back. It makes thing like writing video chat in the browser ridiculously easy. And it's open source! Look out for it in July.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/webmachine/&quot;&gt;Webmachine&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Webmachine is the best way to implement a REST interface to your Erlang application that I've seen to date. I've &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2008/06/migrating-native-erlang-interface-to.html&quot;&gt;blogged&lt;/a&gt; about REST and Erlang in the past, but instead of rolling your own, you should look at this. Especially considering how it handles all the response codes correctly, does all the correct caching responses etc. Another open source project.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size:large;&quot;&gt;And the point is...?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think it's a very positive indicator for the future of Erlang that it is being used in these new and exciting areas and companies. It is performing very well in the field of high-scalability infrastructure. It is well suited to Cloud computing. But most importantly, &lt;i&gt;&lt;b&gt;very clever and innovative people are using it and loving i&lt;/b&gt;&lt;b&gt;t&lt;/b&gt;&lt;/i&gt;. That, above all else, means the future looks good for Erlang.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;P.S. I'm sure I missed some great talks again this year, but lucky for me and you, you can find the talks and videos &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-factory.com/conference/London2009/talks&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-5669561164847906526?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-5669561164847906526</guid>
         <pubDate>Thu, 02 Jul 2009 06:32:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://1.bp.blogspot.com/_bXDgUoT7V7o/Sk4AeAT0K7I/AAAAAAAAANA/5lDV0iMS_V8/s72-c/newkids3.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Plaudit</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/plaudit.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.noop.nl/2009/06/top-200-blogs-for-developers-q2-2009.html&quot;&gt;Apparently&lt;/a&gt;, this is the 141st most &quot;top&quot; blog for developers (as of Q2 2009). That's probably pretty far out along some long tail of topness. Ah well. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The metric used captures something like degree of interest of the rest of the blogosphere. So, thanks for your interest. &lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-7776751819730099371?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-7776751819730099371</guid>
         <pubDate>Mon, 29 Jun 2009 15:15:00 -0700</pubDate>
      </item>
      <item>
         <title>Let's talk about feelings</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/lets-talk-about-feelings.html</link>
         <description>I seem to recall that back in the days when he was prone to wild outbursts of public self-examination (this even before blogging and twitter) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cleeseblog.com/&quot;&gt;John Cleese&lt;/a&gt; gave an interview in part about his early experiences with therapy, with a &quot;talking&quot; cure. His therapist would begin, &quot;How do you feel?&quot; and John would say &quot;Well, I think...&quot; and his therapist would interrupt &quot;No. How do you feel?&quot; and John would say &quot;Well, I think...&quot; and his therapist would interrupt &quot;No. How do you feel?&quot; And so on. You can see the problem. And he couldn't, I suppose. Which was the problem.&lt;br /&gt;&lt;br /&gt;More and more these days I want to ask people how they &lt;span style=&quot;font-style:italic;&quot;&gt;feel&lt;/span&gt; about their code. Here's part of why.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://puttingtheteaintoteam.blogspot.com/&quot;&gt;Ivan Moore&lt;/a&gt; and &quot;the other&quot; Mike Hill have this conference session that they do called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaoo.dk/london-2009/file?path=/qcon-london-2009/slides/IvanMoore_ProgrammingInTheSmall.pdf&quot;&gt;Programming in the Small&lt;/a&gt; [pdf]. I love it. They put little examples of code in front of folks and invite them to refactor, just a little bit. And then reflect on the refactoring. One of the things they've noticed that programers tend to do under these conditions is futz around with the code before getting down to actually improving the design.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Mike and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.m3p.co.uk/blog&quot;&gt;Steve Freeman&lt;/a&gt; do a similar session called &quot;Programming without Getters&quot; This is in the so-called &quot;dojo&quot; format, where a revolving pair of programmers is invited to take some fairly typical &quot;enterprise&quot; class code and refactor it to remove the getters. There are those of us that believe that there can be &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/2008/06/tdd-mocks-and-design.html&quot;&gt;something quite special&lt;/a&gt; about OO code with that property, but the session didn't really get there. That's because the pairs couldn't bring themselves to do the refactoring as asked, they couldn't even start to remove any getters, until they'd futzed around with the code first. And since a new person rolls into the pair every five minutes or so, it's pretty much a non-stop futz-fest. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.lindarising.org/&quot;&gt;Linda Rising&lt;/a&gt; saw &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.keithbraithwaite.demon.co.uk/professional/presentations/2008/qcon/MeasureForMeasure.pdf&quot;&gt;a talk&lt;/a&gt; I give about this &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.objectmentor.com/articles/2009/06/08/metrics-of-moment&quot;&gt;design metric&lt;/a&gt; that I've been &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/search/label/test-first%20complexity&quot;&gt;playing with&lt;/a&gt; over the last couple of years (I have a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.zuehlke.com/en/the-company/locations/united-kingdom/&quot;&gt;day job&lt;/a&gt;, so progress has been slow). She was struck by my observation that folks who've tried this metric on their own code have reported that refactoring which made them happier with the code also increases the value of the metric. Linda wanted to know if they really said &quot;happier&quot;. They really do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It turns out that Linda did some research back in the day on a design metric of her own. During this work she had noticed that in general, programers like to futz around with code before they get down to work on it. If I recall correctly, she asked &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.dreamsongs.com/&quot;&gt;Dick Gabriel&lt;/a&gt; about this and he said that &quot;programmers do that&quot;, along with some allusion to that metaphorical aphorism about the flavour of soup and pissing in it. I'm sure a lot of that goes on. But what Linda (again, this is as well as I recall) further noticed was that they tended to do this&lt;i&gt; much less &lt;/i&gt;with code that scored well on her metric. And they described themselves as being more &lt;i&gt;comfortable&lt;/i&gt; working on this code than on code that had a low score.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, I've nothing against metrics in principle (after all, I seem to be in the middle of inventing one) but I'm rather dubious about all this dashbordery and piechartism that's going on these days, all this getting of the CI server to dish up trends of metrics and blah, blah, blah. It's nice to have the numbers, it's nice to see a healthy trend, but.......&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;How do you &lt;i&gt;feel&lt;/i&gt; about your code? Does it make you &lt;i&gt;happy&lt;/i&gt;? Is it &lt;i&gt;comfortable&lt;/i&gt;?&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-3877152177530466653?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-3877152177530466653</guid>
         <pubDate>Mon, 29 Jun 2009 14:21:00 -0700</pubDate>
      </item>
      <item>
         <title>XP Day London 09: Call for Sessions</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/xp-day-london-08-call-for-sessions.html</link>
         <description>Submissions are now open for programmed sessions at XpDay London 2009, to be held 7th and 8th December 2009. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xpday.org/&quot; style=&quot;text-decoration:none;color:rgb(145, 54, 173);&quot;&gt;http://www.xpday.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You are invited to propose a session for the first day of the conference. We are particularly interested in the following&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Experience reports—share your stories of challenge and success with Agile and Lean techniques. Experience reports will be intensively shepherded by experienced practitioners.&lt;/li&gt;&lt;li&gt;Hands-on technical sessions—share techniques and practices in practical sessions: workshops, tutorials, simulations&lt;/li&gt;&lt;li&gt;Practitioners' advances in the art—share the techniques of expert Agile and Lean practitioners, work with them to move the craft forward.&lt;/li&gt;&lt;/ul&gt;The second day of the conference will be an OpenSpace session with topics selected at the end of the first day. Programmed sessions are most suitable for topics requiring some set up or extensive preparation.&lt;br /&gt;&lt;br /&gt;To submit a session, please go to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday-london.editme.com/XpDay2009Submissions&quot;&gt;http://xpday-london.editme.com/XpDay2009Submissions&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Submissions will be accepted until Friday 14th August.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-4115294738716434813?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-4115294738716434813</guid>
         <pubDate>Sun, 28 Jun 2009 13:07:00 -0700</pubDate>
      </item>
      <item>
         <title>Google AppEngine Disappointment</title>
         <link>http://jaksa.wordpress.com/2009/06/22/google-appengine-disappointment/</link>
         <description>I was eager to try out Google&amp;#8217;s AppEngine for Java, but I was soon disappointed to find out that the AppEngine is just a partial implementation of the Java APIs. The biggest problem with the missing APIs is that a lot of 3rd party software and libraries simply won&amp;#8217;t work, which means that you loose [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=127&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=127</guid>
         <pubDate>Mon, 22 Jun 2009 05:58:29 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p><img class="alignleft" src="http://weblogs.java.net/blog/felipegaucho/archive/ae_gwt_java.png" alt="" width="300" height="200"/>I was eager to try out Google&#8217;s <a rel="nofollow" target="_blank" href="http://code.google.com/appengine/docs/java/overview.html">AppEngine for Java</a>, but I was soon disappointed to find out that the AppEngine is just a <a rel="nofollow" target="_blank" href="http://code.google.com/appengine/docs/java/jrewhitelist.html">partial implementation</a> of the Java APIs. The biggest problem with the missing APIs is that a lot of 3rd party software and libraries simply won&#8217;t work, which means that you loose all the benefits of the mature Java ecosystem. Porting an existing Java application to AppEngine is simply out of question.</p>
<p>Another major problem is persistence. You cannot deploy your favourite DBMS on AppEngine, you have to use Google&#8217;s Datastore, which is not a common relational DB. Google makes available JDO and JPA interfaces to access the Datastore. However, these are also partial implementations which provide just a familiar syntax for a substantially different persistence mechanism and create a false sense of familiarity. This is particularly true when you try to refer to the JDO documentation for troubleshooting, but you discover that the semantics of Google&#8217;s JDO implementation are quite different. It would have been much better to stick with a proprietary persisntece API and not pretend to fill the gap to reach JDO or JPA semantics.</p>
<p>Another important missing feature are Threads, which makes AppEngine a poor choice for massive computations since paralellization of subtasks is not possible, at least until Google implement the AppEngine <a rel="nofollow" target="_blank" href="http://labs.google.com/papers/mapreduce-osdi04.pdf">Map/Reduce</a> service.</p>
<p>Lastly the overall sense of a finished product is not there. Things that one would expect to work, fail for some obscure reason. Error messages are often cryptic. Apart from an introductionary tutorial, documentation is quite scarce. I guess this is justifiable since AppEngine is still a beta release, but I would rather consider it a pre-alpha. I was expecting much more considerate choices from the smart Google engineers, who have amazed us many times so far.</p>
<p>There were a few things I did like about the app engine. For example, the Eclipse plugin simplifies configuration, testing and deployment. Integration with other Google services are a promissing factor. All in all, Google AppEngine is an interesting toy, but compared to other solutions it&#8217;s remains just a toy. If you want to play with it, I suggest you should read <a rel="nofollow" target="_blank" href="http://www.pardontheinformation.com/2009/06/google-app-engine-for-java-3-tips-for.html">this</a>.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/127/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/127/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/127/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/127/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/127/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=127&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
         <media:content url="http://weblogs.java.net/blog/felipegaucho/archive/ae_gwt_java.png" medium="image"/>
      </item>
      <item>
         <title>Test-Driven Design is not testing</title>
         <link>http://aspsp.blogspot.com/2009/06/test-driven-design-is-not-testing.html</link>
         <description>&lt;div&gt;I've recently worked with a team doing its first agile project (though one or two team members had been involved in an agile project before). The most difficult concept to get across was TDD - test driven design. I found that people really didn't grok the idea until I pair-programmed with them for a couple of hours. I wonder why that might be.&lt;br/&gt;&lt;br/&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://behaviour-driven.org/Introduction'&gt;Dan North&lt;/a&gt; has suggested one possibility. He observed that newcomers to TDD often don't get the really big payback because they continue to think that TDD is mainly about testing - even if they will admit that writing the tests before the code leads to better quality code. They never transition to treating TDD as a design process, letting them discover the API to a component they're writing, nor to the realisation that TDD is about defining the behaviour of their component and its interactions with other components of the system.&lt;br/&gt;&lt;br/&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://peripateticaxiom.blogspot.com/2008/03/tests-and-gauges.html'&gt;Keith Braithwaite&lt;/a&gt; has put forward another consideration. In physical engineering disciplines, practitioners speed up their work process by using gauges. There are many kinds, from the simple spark plug gap gauge, which is simply a sliver of metal to slide between the electrodes, to electronic vernier calliper gauges that can be pre-set to a precise dimension with tolerances above and below. Each workpiece is tested at each stage of the process by checking its dimensions with the appropriate gauge(s). Workpieces that are out of tolerance are sent back for rework or scrapped. Our unit tests are a bit like that - they provide a safeguard that the software component we're working on still meets all its requirements following any engineering we've done.&lt;br/&gt;&lt;br/&gt;It occurred to me today that unit and acceptance tests, particularly if automated, perform another valuable function in the context of an agile (especially a lean) development process. Whereas the waterfall processes familiar to most developers are characterised by &quot;quality gates&quot; at key stages, every single artifact in an agile development has its own little quality gate, manifested in the appropriate tests. This theoretically frees the development process from the usual bottlenecks that the quality gates tend to become.&lt;br/&gt;&lt;br/&gt;I say &quot;theoretically&quot;, because in many instances agile development projects have to take place within a quality system that doesn't take advantage of incremental delivery. Instead, continued approval and in many cases funding for the project tends to be contingent on passing the traditional quality gates following requirements analysis, functional specification, high-level design, low-level design, coding, integration, system test and acceptance. Project managers are therefore forced to conjure up some kind of spurious linkage between the milestones laid down in the rigid quality system and some arbitrary points along their product release plan. This can hamper their freedom to adjust the release plan in response to changing circumstances and emerging technical insights.&lt;br/&gt;&lt;br/&gt;This could be avoided if the quality system could recognise that properly written tests represent every work product of a software development project apart from the code itself. It should therefore simply insist on a verification at each iteration (or at each release, perhaps) that the tests comprehensively and comprehensibly represent the requirements of the business on the system under development and that the required set of tests pass repeatably. I say &quot;the required set&quot; because there's always the possibility that some tests will intentionally fail - e.g. where they have been written to test features that are not yet in the current release.&lt;br/&gt;&lt;br/&gt;In other words, TDD can be used to eliminate the quality-gate bottlenecks of quality systems that assume waterfall development processes.&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-7951850868462003290?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-7951850868462003290</guid>
         <pubDate>Mon, 15 Jun 2009 10:40:00 -0700</pubDate>
      </item>
      <item>
         <title>Flow: are two dimensions enough?</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/flow-are-two-dimensions-enough.html</link>
         <description>Inspired by a comment by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.metaprog.com/blogs/&quot;&gt;Joseph&lt;/a&gt; at the recent &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agilecoachesgathering.org/wiki/index.php/Home&quot;&gt;Agile Coach's Gathering&lt;/a&gt; I've been experimenting with the use of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/File:Challenge_vs_skill.jpg&quot;&gt;this model&lt;/a&gt; in mid-year reviews for my team.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the guys observed that it seems to have a missing dimension. It seems that it's possible to have a case whereby an individual is working on a solidly challenging problem, well up the y-axis, and they have the high level of skill to meet that challenge, well along the x-axis...and when all's said and done they'd really rather be doing something a bit more enjoyable. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Missing axis: &lt;i&gt;fun&lt;/i&gt;.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-430079782998857316?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-430079782998857316</guid>
         <pubDate>Mon, 08 Jun 2009 13:48:00 -0700</pubDate>
      </item>
      <item>
         <title>Bridging the Communication Gap</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/bridging-communication-gap.html</link>
         <description>&lt;div&gt;Call it automated acceptance testing, functional test driven development, checked examples or what you will—the use of automatic validation is one of the most effective tools in the Agile developer's kit. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;It's a large and involved field, touching on almost every aspect of development. Handy, then, that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gojko.net/&quot;&gt;Gojko Adzic&lt;/a&gt; has published a very comprehensive guide to the use of automated acceptance tests in contemporary Agile development practice, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.acceptancetesting.info/the-book/&quot;&gt;&lt;i&gt;Bridging the Communication Gap&lt;/i&gt;&lt;/a&gt;&lt;i&gt;: Specification by example and agile acceptance testing. &lt;/i&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;This book is a much-needed checkpoint in the on-going adventure to discover (and re-discover) how to write software effectively. Gojko is a very energetic enthusiast for these ideas, and a very experienced practitioner of them. His knowledge and expertise is present on every page.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A strong theme runs through the book—that the reason we capture examples of required behaviour and automate validation of them is to improve communication. Examples turn out to be a very powerful way to understand a problem domain and to explore a solution suitable for that domain. There turn out to be fascinating reasons for why this is true, but Gojko quite reasonably focusses on practical advice. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The main body of the book tells a story, a story of understanding, finding, and using examples to create shared understanding across a team. Gojko gives very concrete advice in a series of short chapters and explains how to do this. How to organise a workshop to find examples, how to find good examples, how to use tools to automate validation, how to use the resulting tests to guide development. Each chapter ends with a handy bullet list of key points. Together with other material on the best use for developers to make of such checked examples, and how to fit example discovery and capture into a typical Agile development process &lt;i&gt;Bridging the Communication Gap&lt;/i&gt; provides as close to a &lt;i&gt;vade mecum&lt;/i&gt; for newcomers to the discipline of functional test driven development as we are likely to see.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Gojko draws informative parallels with other techniques more or less strongly aligned with the Agile development world. This places the practice of Agile acceptance testing in context, and as a team-wide activity, reinforcing the cross-functional nature of the tool. Always the emphasis is on helping the various stakeholders in a development project communicate better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a survey of tools available for this kind of work, which I might wish were slightly broader in scope and a little more detailed, but it does give a good overview of the market leaders. &quot;Market leaders&quot; in the weakest sense, since it turns out that the best tools for this kind of work are all FOSS: big-ticket corporate testing tools really aren't in this game.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Various points regarding writing and using tests are illustrated with (of course) illuminating examples. Also described are limitations of these techniques and some pitfalls to watch out for, something that more promoters of development techniques should provide.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The book is self-published and my copy was printed by Lightening Source. Books produced this way are getting better all the time, but are still not presented at the level of quality one would expect from a commercial publishing house. The pages seem very full and with the choice of font made the text a very dark colour which I don't find easy to read. The section and sub-section headings are sometimes over long and are not laid out well, a combination that I found made the book less easy to navigate than it might have been.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will be using with book with clients and recommending it to them for future reference. A boon to the community.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-5007714223060812717?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-5007714223060812717</guid>
         <pubDate>Sun, 07 Jun 2009 08:27:00 -0700</pubDate>
      </item>
      <item>
         <title>The Quality of non-declining Velocity</title>
         <link>http://peripateticaxiom.blogspot.com/2009/06/quality-of-non-declining-velocity.html</link>
         <description>I'm supposing that anyone reading this blog will be familiar with the stuff-left-to-do &lt;i&gt;vs&lt;/i&gt; time chart used by many Agile teams to track the progress and (with due care an attention) predict the outcome of a development episode:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_itmSz8f6ak4/Siqj49FfmmI/AAAAAAAAAAM/nYqRwm7VzCg/s1600-h/burndown.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:201px;height:151px;&quot; src=&quot;http://3.bp.blogspot.com/_itmSz8f6ak4/Siqj49FfmmI/AAAAAAAAAAM/nYqRwm7VzCg/s320/burndown.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5344264106694122082&quot;/&gt;&lt;/a&gt;In his &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.scrum-breakfast.com/2009/04/lean-agile-scrum-conference-in-zurich.html&quot;&gt;Zurich Lean/Scrum/Agile show&lt;/a&gt; keynote &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.scrumalliance.org/profiles/7&quot;&gt;Ken Schwaber&lt;/a&gt; presented an interesting slant on this chart (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://twitter.com/RonJeffries/statuses/2058380901&quot;&gt;apparently&lt;/a&gt; he got this from &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xprogramming.com/blog&quot;&gt;Ron Jeffries&lt;/a&gt;). The argument is that if you have poor internal quality—in particular if your &quot;definition of done&quot; is not strong enough and does not require you to keep your code in tip-top condition—then there will be a hidden accumulation of stuff-left-to-do. So your chart is in effect more like this:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_itmSz8f6ak4/SiqlqxkPJ9I/AAAAAAAAAAU/u469U5AgHxM/s1600-h/hidden-dip.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:254px;height:179px;&quot; src=&quot;http://3.bp.blogspot.com/_itmSz8f6ak4/SiqlqxkPJ9I/AAAAAAAAAAU/u469U5AgHxM/s320/hidden-dip.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5344266062106929106&quot;/&gt;&lt;/a&gt;&lt;div&gt;This is interestingly different from the technique that some use to show scope added during an episode, with a stepped baseline. Here, additional work is accumulating, invisibly, inside your code. Work that you will have to do at some point to get a releasable increment. This has the effect of making a burn-down line more shallow than it appears, suggesting that there will be either unanticipated under-delivery of scope or (worse yet) a need to slip delivery.&lt;/div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://4.bp.blogspot.com/_itmSz8f6ak4/SiqmahWRd3I/AAAAAAAAAAc/Qc-C7iDostg/s1600-h/slip.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:262px;height:212px;&quot; src=&quot;http://4.bp.blogspot.com/_itmSz8f6ak4/SiqmahWRd3I/AAAAAAAAAAc/Qc-C7iDostg/s320/slip.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5344266882387113842&quot;/&gt;&lt;/a&gt;If the causes of poor internal quality are not rectified, then this effect will repeat, and over successive episodes the team in question will get slower and slower (or deliver less and less)&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://2.bp.blogspot.com/_itmSz8f6ak4/SirBXAVliLI/AAAAAAAAAA0/uCnsKjjc2CQ/s1600-h/slope.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:264px;height:185px;&quot; src=&quot;http://2.bp.blogspot.com/_itmSz8f6ak4/SirBXAVliLI/AAAAAAAAAA0/uCnsKjjc2CQ/s320/slope.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5344296508800207026&quot;/&gt;&lt;/a&gt;Talking about this with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://availagility.wordpress.com/&quot;&gt;Karl Scotland&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.metaprog.com/blogs/&quot;&gt;Joseph Pelrine&lt;/a&gt; in the bar afterwards we tossed around the idea that this shows internal quality (traditionally a hard thing to measure) to be something like the first derivative of project velocity with respect to time. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And now to stretch the metaphor to breaking point. For that to make sense quantitatively it seems as if what we're really saying is that if the internal quality &lt;i&gt;Q&lt;/i&gt; is less than some threshold &lt;i&gt;Q&lt;sub&gt;cv&lt;/sub&gt;&lt;/i&gt; (the quality of non-decreasing velocity) then the velocity &lt;i&gt;V&lt;/i&gt; will decrease over time: &lt;/div&gt;&lt;div style=&quot;text-align:center;&quot;&gt;∂&lt;i&gt;V&lt;/i&gt;/∂&lt;i&gt;t&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size:x-large;&quot;&gt;∝&lt;/span&gt;&lt;/i&gt; &lt;i&gt;Q-Q&lt;sub&gt;cv&lt;/sub&gt;&lt;/i&gt;&lt;/div&gt;Well, it seems reasonable that this will hold for low quality, when &lt;i&gt;Q - Q&lt;sub&gt;cv&lt;/sub&gt;&lt;/i&gt; is negative. But what about when &lt;i&gt;Q - Q&lt;sub&gt;cv&lt;/sub&gt;&lt;/i&gt; is positive? Is it possible to take a team that is writing code at the level of quality required for non-decreasing velocity—that is, not accumulating hidden extra work—and then &lt;i&gt;increase&lt;/i&gt; velocity by increasing quality?&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think it is.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think that a team can push really hard on internal quality and have it turn out that there is less work to do than they thought to get finished.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(0, 0, 238);&quot;&gt;&lt;img src=&quot;http://2.bp.blogspot.com/_itmSz8f6ak4/SirDqJNx7DI/AAAAAAAAAA8/J_SaeGSGMBc/s320/sope-up.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5344299036624153650&quot; style=&quot;display:block;margin-top:0px;margin-right:auto;margin-bottom:10px;margin-left:auto;text-align:center;cursor:pointer;width:253px;height:162px;&quot;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;And maybe that's obvious—and maybe it isn't—but certainly I now feel as if I have a much better handle on how to explain to someone why (as the Software Craftsmanship folks say) the only way to go fast is to go well.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-5758211233957798093?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-5758211233957798093</guid>
         <pubDate>Sat, 06 Jun 2009 10:53:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_itmSz8f6ak4/Siqj49FfmmI/AAAAAAAAAAM/nYqRwm7VzCg/s72-c/burndown.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Look out RIAs, HTML5 is coming</title>
         <link>http://21ccw.blogspot.com/2009/06/look-out-rias-html5-is-coming.html</link>
         <description>&lt;span style=&quot;font-family:sans-serif;&quot;&gt;Google showing off &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://googlesystem.blogspot.com/2009/05/google-wave.html&quot;&gt;Wave&lt;/a&gt;, has [re]ignited some discussion around HTML5. I read an article on InfoQ, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/news/2009/06/Wave-Silverlight&quot;&gt;Is Google Wave Going to Have an Impact on RIA/Silverlight?&lt;/a&gt; Which struck me as a bit of an odd question. Tim Heuer&lt;/span&gt;&lt;span style=&quot;font-family:sans-serif;&quot;&gt; (in the Silverlight camp) is correct in asking &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://timheuer.com/blog/archive/2009/05/30/google-wave-forces-out-silverlight-flash-ria-platforms.aspx&quot;&gt;is HTML5 really what people are talking about here?&lt;/a&gt;&quot; and towards the end of the article, the correct question is polled:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&quot;What negative impact will HTML 5/Wave going to have on RIA/Silverlight?&quot; [sic]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;At the time the results of the poll were:&lt;br /&gt;&lt;br /&gt;Major: 66&lt;br /&gt;Significant: 115&lt;br /&gt;Small: 112&lt;br /&gt;None: 43&lt;br /&gt;Total votes: 336&lt;br /&gt;&lt;br /&gt;I was a bit surprised by the poll results. I voted &quot;Major&quot;, and I find it hard to understand how someone could vote &quot;None&quot;. None?! Really? I do realise that this is partly due to the fact that most people, including me, think they are above average (I just discovered that it is also called the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Lake_Wobegon_effect&quot;&gt;Lake Wobegon&lt;/a&gt; effect. Cute). There is also some confusion about including Wave in the question, which has nothing to do with the issue. I'll try and convince you of the potential impact...&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;br /&gt;Why RIAs exist&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The existence of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Rich_Internet_application&quot;&gt;Rich Internet Applications&lt;/a&gt; can be explained by the word &quot;Rich&quot; in the name. At some point in the past few years, people started to realise that HTML didn't keep up with the explosion in bandwidth and processing power available to users, and that the web experience could be &quot;richer&quot;. This was especially obvious in areas such as not having the ability to to arbitrary on-screen animantions and rendering on a &quot;canvas&quot;, the ability to store data locally on user's hard drives and drag-and-drop, amongst others. The lack of these features in HTML created a gap in the market, but only whilst browser technology continues to lag. This gap has been exploited by Flex, Silverlight and JavaFX.&lt;br /&gt;&lt;br /&gt;&lt;b style=&quot;font-style:italic;&quot;&gt;This situation is changing.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Enter HTML5&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some of the features in HTML5 will add some really exciting possibilities to applications running on the browser platform:&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;b&gt;Video&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Although I wouldn't categorise video as a major driver for RIA technologies, it is important to mention in relation to Adobe flash, which is the dominant technology for delivering internet video. YouTube is already delivering non-flash internet video in mobile devices. The introduction of the  tag will reduce the pressure of deploying flash on every platform, which could have an effect on the usage of Flex. Consider that Flash is not available on the iPhone: if you have a choice of developing your application on just one technology (HTML5) for both desktop and mobile, or choosing 2, which would cost less?&lt;br /&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;b&gt;Canvas drawing (immediate mode drawing)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Canvas drawing will enable application developers to fill a gaping hole in native browser capabilities - gaming. The gaming industry is bigger than the movie industry, and the availability of a virtually universally available standard platform will not got unnoticed by game developers. Of course this capability doesn't only apply to gaming.&lt;br /&gt;&lt;div style=&quot;font-weight:bold;&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;Local storage&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-weight:normal;&quot;&gt;As long as there's no capability for storing data offline, web applications continue to be considered the poor cousin of desktop applications. Google documents are not availble offline without &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gears.google.com/&quot;&gt;Google Gears&lt;/a&gt;. Having local storage available in a &lt;/span&gt;&lt;i&gt;&lt;span style=&quot;font-weight:normal;&quot;&gt;standardised&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-weight:normal;&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt; way is a big attraction for application developers. Gears might work for Gooogle, but not everyone is so keen on having a dependency on a non-standard technology.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Some other disavantages to RIAs which could favour HTML5 applications&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- RIAs are usually everything or nothing. They don't play well with embedding RIA functionality into existing web pages. HTML5 allows you to grow your application, creating a richer and richer experience as you go along.&lt;br /&gt;- Some RIAs have proprietary technologies.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- RIAs require an extra &lt;b&gt;deployment&lt;/b&gt; step on top of deploying the browser. Browsers implementing HTML5 will provide a more standardised way of deploying applications to users, also in the corporate environment where locked-down systems are common. Choosing a technology that doesn't require another installation step is a big attraction for corporate IT departments.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;In the long term&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There another significant point to make.&lt;br /&gt;&lt;br /&gt;I believe it is part of Google's long term strategy to make the browser the de-facto application platform. &lt;b&gt;To displace Windows as the dominant aplication platform&lt;/b&gt;. You can see it already with Chrome, how the tabs on the browser have become the new taskbar, and the integration of browser tabs as &quot;applications&quot; into the host OS. For example, features like local file storage and the canvas provide a path for Google Docs to become more like MS Office. You can be sure that some of the drive behind the HTML5 standard is coming from the Google docs team. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm not the only one thinking along these lines: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://industry.bnet.com/technology/10002039/googles-long-shot-at-kicking-microsoft-off-the-desktop/&quot;&gt;http://industry.bnet.com/technology/10002039/googles-long-shot-at-kicking-microsoft-off-the-desktop/&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;In closing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm not trying to say that HTML5 will eliminate RIA technologies, but I do believe that thinking that its impact on RIA will be &quot;small&quot; or &quot;none&quot; is absolutely ridiculous.&lt;br /&gt;&lt;br /&gt;There are some big players pushing the browser to become the dominant application platform. HTML5 is a big step in that direction.&lt;br /&gt;&lt;br /&gt;If you disagree, I look forward to your comments!&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-8818275353199237827?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-8818275353199237827</guid>
         <pubDate>Fri, 05 Jun 2009 08:50:00 -0700</pubDate>
      </item>
      <item>
         <title>The Vendor/Client Relationship in Real Life</title>
         <link>http://peripateticaxiom.blogspot.com/2009/05/vendorclient-relationship-in-real-life.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=R2a8TRSgzZY&quot;&gt;What would happen&lt;/a&gt;[youtube] if clients tried to deploy the kinds of arguments they use with &quot;professional services&quot; suppliers in other situations...&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-2264469811357527602?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-2264469811357527602</guid>
         <pubDate>Wed, 27 May 2009 23:10:00 -0700</pubDate>
      </item>
      <item>
         <title>The Law of Conservation of Misery</title>
         <link>http://21ccw.blogspot.com/2009/05/law-of-conservation-of-misery.html</link>
         <description>At university I had a professor who would jokingly refer to his Law of Conservation of Misery:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style:italic;&quot;&gt;The total amount of misery in a system is constant&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which implies that when you try and decrease the misery in one aspect of a system, you will increase the misery in some of the other aspects.&lt;br /&gt;&lt;br /&gt;There are many types of misery. In software engineering projects these could include non-maintainability, non-performance and budget constraints.&lt;br /&gt;&lt;br /&gt;Personally, I think people are too prone to think that there are &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Zero-sum&quot;&gt;zero-sum&lt;/a&gt; monsters lurking under each bed, so my own take on the &quot;law&quot; would be:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style:italic;&quot;&gt;The total amount of misery in a system is &amp;gt; 0&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style:italic;&quot;&gt;&lt;/span&gt;&lt;/span&gt;Which implies that you &lt;span style=&quot;font-weight:bold;&quot;&gt;can&lt;/span&gt; make tradeoffs that decrease the total amount of misery&lt;span style=&quot;font-style:italic;&quot;&gt;, &lt;/span&gt;but you can never eliminate it completely. A bad implementation of a system will have a higher total amount of misery, and a good one will have less, but you will always have at least a little bit!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-1553935460548581277?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-1553935460548581277</guid>
         <pubDate>Wed, 20 May 2009 04:29:00 -0700</pubDate>
      </item>
      <item>
         <title>How to send email via Gmail using Erlang</title>
         <link>http://21ccw.blogspot.com/2009/05/how-to-send-email-via-gmail-using.html</link>
         <description>One of my pet projects, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.dayfindr.com&quot;&gt;www.dayfindr.com&lt;/a&gt;, integrates with email to send notifications to users.&lt;br /&gt;&lt;br /&gt;I use &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.blogger.com/www.google.com/apps%20%20&quot;&gt;Google Apps&lt;/a&gt; for email infrastructure, so you need an SMTP client that supports &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Secure_Sockets_Layer&quot;&gt;TLS&lt;/a&gt;. At the time, I couldn't find a simple Erlang SMTP client that could handle TLS, so I used a command-line SMTP client.&lt;br /&gt;&lt;br /&gt;For my new pet project, for want of a better name temporarily called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.theisabelleproject.com/&quot;&gt;The Isabelle Project&lt;/a&gt;, I need to add some email functionality. This time I would prefer to use an Erlang solution with proper error handling and logging.&lt;br /&gt;&lt;br /&gt;I looked at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&quot;&gt;SMTP&lt;/a&gt; protocol on Wikipedia, and it didn't seem to difficult. Erlang's built-in ssl module also seemed to support TLS. So, with a bit of trial and error, here's the result:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;-module(smtp).&lt;br /&gt;-export([connect/0]).&lt;br /&gt;&lt;br /&gt;connect() -&amp;gt;&lt;br /&gt; {ok, Socket} = ssl:connect(&quot;smtp.gmail.com&quot;, 465, [{active, false}], 1000),&lt;br /&gt; recv(Socket),&lt;br /&gt; send(Socket, &quot;HELO localhost&quot;),&lt;br /&gt; send(Socket, &quot;AUTH LOGIN&quot;),&lt;br /&gt; send(Socket, binary_to_list(base64:encode(&quot;___@gmail.com&quot;))),&lt;br /&gt; send(Socket, binary_to_list(base64:encode(&quot;johngalt&quot;))),&lt;br /&gt; send(Socket, &quot;MAIL FROM: &amp;lt;___@gmail.com&amp;gt;&quot;),&lt;br /&gt; send(Socket, &quot;RCPT TO:&amp;lt;___@gmail.com&amp;gt;&quot;),&lt;br /&gt; send(Socket, &quot;DATA&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;From: &amp;lt;___@gmail.com&amp;gt;&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;To: &amp;lt;___@gmail.com&amp;gt;&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;Date: Tue, 15 Jan 2008 16:02:43 +0000&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;Subject: Test message&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;This is a test&quot;),&lt;br /&gt; send_no_receive(Socket, &quot;&quot;),&lt;br /&gt; send(Socket, &quot;.&quot;),&lt;br /&gt; send(Socket, &quot;QUIT&quot;),&lt;br /&gt; ssl:close(Socket).&lt;br /&gt;&lt;br /&gt;send_no_receive(Socket, Data) -&amp;gt;&lt;br /&gt; ssl:send(Socket, Data ++ &quot;&amp;#92;r&amp;#92;n&quot;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;send(Socket, Data) -&amp;gt;&lt;br /&gt; ssl:send(Socket, Data ++ &quot;&amp;#92;r&amp;#92;n&quot;),&lt;br /&gt; recv(Socket).&lt;br /&gt;&lt;br /&gt;recv(Socket) -&amp;gt;&lt;br /&gt; case ssl:recv(Socket, 0, 1000) of&lt;br /&gt; {ok, Return} -&amp;gt; io:format(&quot;~p~n&quot;, [Return]);&lt;br /&gt; {error, Reason} -&amp;gt; io:format(&quot;ERROR: ~p~n&quot;, [Reason])&lt;br /&gt; end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the output from the Erlang shell:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;3&amp;gt; application:start(ssl).&lt;br /&gt;ok&lt;br /&gt;4&amp;gt; smtp:connect().&lt;br /&gt;&quot;220 mx.google.com ESMTP y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;250 mx.google.com at your service&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;334 VXNlcm5hbWU6&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;334 UGFzc3dvcmQ6&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;235 2.7.0 Accepted&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;250 2.1.0 OK y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;250 2.1.5 OK y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;354 Go ahead y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;250 2.0.0 OK 1242683885 y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;&quot;221 2.0.0 closing connection y37sm613282mug.19&amp;#92;r&amp;#92;n&quot;&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The only tricky bit is that for the AUTO LOGIN, the received text and the username and password you send is base-64 encoded. By default the connect is active=false, which means the responses are send to the creating process directly. Using passive mode requires explicit receiving of the response using ssl:recv/2&lt;br /&gt;&lt;br /&gt;You'll have to handle errors better if you use this in production, but the basic protocol is pretty straightforward...&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-856792514420372731?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-856792514420372731</guid>
         <pubDate>Tue, 19 May 2009 04:19:00 -0700</pubDate>
      </item>
      <item>
         <title>Epic user interface fail of Homeric proportions</title>
         <link>http://peripateticaxiom.blogspot.com/2009/05/epic-uer-interface-fail-of-homeric.html</link>
         <description>A little while ago I was riding the now sadly degenerate &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/East_Coast_Main_Line&quot;&gt;East Coast Main Line &lt;/a&gt;service in a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/British_Rail_Mark_4&quot;&gt;Mk IV&lt;/a&gt; coach and noticed a bit of a curfuffle in the vestibule (I love it that British railway carriages are still referred to as having &quot;vestibules&quot;). Paying attention I discovered that an elderly lady had required assistance from the train staff with the door of the toilet. This seemed a little odd, so after a suitably discreet interval I went to investigate. One has to make one's own enertainment on the train.&lt;br /&gt;&lt;br /&gt;What I found was a flabbergasting cascade of fail.&lt;br /&gt;&lt;br /&gt;This advice is welcome:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; title=&quot;DSC00106 by Keith Braithwaite, on Flickr&quot; target=&quot;_blank&quot; href=&quot;http://www.flickr.com/photos/keithbraithwaite/3544526551/&quot;&gt;&lt;img height=&quot;114&quot; alt=&quot;DSC00106&quot; src=&quot;http://farm4.static.flickr.com/3330/3544526551_376f1814d2_m.jpg&quot; width=&quot;240&quot;/&gt;&lt;/a&gt;&lt;br /&gt;Judging by the design and finish, this is the original signage.&lt;br /&gt;&lt;br /&gt;But how to close and lock the door?&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; title=&quot;DSC00104 by Keith Braithwaite, on Flickr&quot; target=&quot;_blank&quot; href=&quot;http://www.flickr.com/photos/keithbraithwaite/3545334842/&quot;&gt;&lt;img height=&quot;238&quot; alt=&quot;DSC00104&quot; src=&quot;http://farm3.static.flickr.com/2333/3545334842_8463ff4d75.jpg&quot; width=&quot;500&quot;/&gt;&lt;/a&gt;&lt;br /&gt;Ok, slightly non-obvious. Also, lacking some rather crucial information, it will turn out.&lt;br /&gt;&lt;br /&gt;Seems as if more people than the lady I saw have had problems with the door, since there was this later, auxiliary sign:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; title=&quot;DSC00107 by Keith Braithwaite, on Flickr&quot; target=&quot;_blank&quot; href=&quot;http://www.flickr.com/photos/keithbraithwaite/3544526749/&quot;&gt;&lt;img height=&quot;180&quot; alt=&quot;DSC00107&quot; src=&quot;http://farm3.static.flickr.com/2137/3544526749_75f444a9a4_m.jpg&quot; width=&quot;240&quot;/&gt;&lt;/a&gt;&lt;br /&gt;Apologies for the poor quality. The text at the bottom reads &quot;If the 'lock' button is not illuminated, the toilet doot is &lt;strong&gt;NOT&lt;/strong&gt; locked&quot; It might very well be &lt;em&gt;closed&lt;/em&gt;, you see, but not &lt;em&gt;locked&lt;/em&gt;. The original signage has braille attached, not so this vital little nugget of information (as I recall).&lt;br /&gt;&lt;br /&gt;It seems that not even this prompt has quite been doing the job, as this third sign had also been added:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; title=&quot;DSC00105 by Keith Braithwaite, on Flickr&quot; target=&quot;_blank&quot; href=&quot;http://www.flickr.com/photos/keithbraithwaite/3545334968/&quot;&gt;&lt;img height=&quot;290&quot; alt=&quot;DSC00105&quot; src=&quot;http://farm3.static.flickr.com/2454/3545334968_304bec6362.jpg&quot; width=&quot;500&quot;/&gt;&lt;/a&gt;&lt;br /&gt;The visually impared (and those on urgent business) are now in serious trouble.&lt;br /&gt;&lt;br /&gt;Being of an equiring mind, and finding the complexity of this control system too hard to believe, I did a few experiments and made an important discovery not covered by any of the above instructions but of no little importance I think.&lt;br /&gt;&lt;br /&gt;If you press, or, let us say, accidentally nudge, the 'lock' button while the door is closed and locked the door (which is powered in the interest of the mobility impared, a good thing in itself) both &lt;em&gt;unlocks and opens&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Now, how hard could this be? What am I missing from this design?&lt;br /&gt;&lt;br /&gt;Still two buttons, their respective behaviour being:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;If the door is open, close and lock it. If the door is closed and locked, no action.&lt;/li&gt;&lt;li&gt;If the door is closed and locked, open it. If the door is open, no action.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I'll be popping over to Switzerland in a couple of weeks, a place where they still take trains (and much else) seriously. And shall on the trip from Flughafen Zurich to the Haputbahnhof be paying close attention to the toilet doors.&lt;br /&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-9184606265171363867?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-9184606265171363867</guid>
         <pubDate>Tue, 19 May 2009 05:58:00 -0700</pubDate>
      </item>
      <item>
         <title>I Broke Google!</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/ZLTZKHyjDCc/i-broke-google.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/ZLTZKHyjDCc&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-451634586200145026</guid>
         <pubDate>Mon, 18 May 2009 10:00:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_Q_F_ea5EKi0/ShGU7FXX_RI/AAAAAAAAAE0/zOI4OXjsevc/s72-c/2009-05-18+18.00_ScreenShot_001.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>24th March 2009: Theory of Constraints Challenged</title>
         <link>http://aspsp.blogspot.com/2009/05/24th-march-2009-theory-of-constraints.html</link>
         <description>&lt;div&gt;My sincere thanks to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.kevinrutherford.co.uk/'&gt;Kevin Rutherford&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.allankelly.net/'&gt;Allan Kelly&lt;/a&gt; for co-presenting a fascinating session about lean software development to the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.bcs.org/server.php?show=nav.9418'&gt;BCS Kingston &amp;amp; Croydon branch&lt;/a&gt; on 24th March this year, entitled &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.bcs.org/server.php?show=ConWebDoc.20825'&gt;&quot;Lean, Constraints, Action!&quot;&lt;/a&gt;. The audience was excellent too and helped us re-create a famous experiment related by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.toc-goldratt.com/index.php?cont=21'&gt;Eliyahu Goldratt&lt;/a&gt; in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.amazon.co.uk/Goal-Process-Ongoing-Improvement/dp/0566086654/'&gt;&quot;The Goal&quot;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lh3.ggpht.com/_eJ-aAjApSE0/Sg0_y8h-PxI/AAAAAAAABAw/s1NXA4h0kR4/%5BUNSET%5D.jpg&quot;&gt;&lt;img src='http://lh3.ggpht.com/_eJ-aAjApSE0/Sg0_y8h-PxI/AAAAAAAABAw/s1NXA4h0kR4/%5BUNSET%5D.jpg?imgmax=800' style='max-width:400px;'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(Click images to see a larger version)&lt;br /&gt;&lt;br /&gt;I had participated in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.vancouver.wsu.edu/fac/holt/em530/Docs/DiceGames.htm'&gt;this game&lt;/a&gt; previously at the London &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.xpday.org/2008/keynotes'&gt;XP Day 2008&lt;/a&gt; (facilitated by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://availagility.wordpress.com/'&gt;Karl Scotland&lt;/a&gt; in an Open Space session). It is designed to demonstrate an intuitively paradoxical finding: that a lean, pull-oriented flow substantially reduces the amount of inventory or work in progress (WIP), &lt;b&gt;while improving throughput&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;However, I had a sneaky feeling that the experiment was biased, because in the first &quot;push&quot; simulation, the assembly line was not pre-loaded with WIP, while in the second &quot;pull&quot; simulation, the line was pre-loaded with workpieces at each &quot;workstation's&quot; input buffer up to either the maximum limit or to 50% of that limit. Therefore in a simulation of 10 rounds (equivalent to ten working days - approximately equal to the average cycle time in a six-workstation setup) the push simulation will only start to produce output towards the very end of the simulation, while the pull simulation will produce something from the very first day.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lh5.ggpht.com/_eJ-aAjApSE0/Sg1En5KocGI/AAAAAAAABA0/JQiC0iXe01o/%5BUNSET%5D.jpg&quot;&gt;&lt;img src='http://lh5.ggpht.com/_eJ-aAjApSE0/Sg1En5KocGI/AAAAAAAABA0/JQiC0iXe01o/%5BUNSET%5D.jpg?imgmax=800' style='max-width:400px;'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So I got Allan and Kevin to agree to vary the rules a little bit, to try to get closer to a &quot;steady state&quot; from the first &quot;day&quot;. Before each of the two simulations, our teams placed three Lego blocks on each of the coasters representing the input buffers of the second through sixth workstations (the first workstation of course has the whole of the product backlog as its input hopper). In fact, as it turned out, four workpieces would have been closer to the true steady state in the pull simulation, even more in the push simulation.&lt;br /&gt;&lt;br /&gt;Off our teams went and played the production line for ten rounds each. In the push simulation, the die was passed in order from workstation 1 to workstation 6 during each round and the number of workpieces transferred to the next input buffer was the number thrown, up to the number of pieces available in the workstation's input buffer. Instances of starvation were rare under this system, but did occur sometimes. At the end we counted up the number of pieces that had come off the end of the line and the number currently in progress (i.e. on any of the five input buffers for workstations 2 to 6).&lt;br /&gt;&lt;br /&gt;In the pull simulation, the die was passed in the opposite direction and the input buffers were constrained to a maximum of six workpieces. So if the next input buffer had three pieces already in it and the player threw anything over a 3, they could only pass along 3 more workpieces (subject to their own input buffer holding at least 3, of course). Once again, the results after 10 rounds were compared.&lt;br /&gt;&lt;br /&gt;The results didn't surprise me particularly, but I think some of the others were a little taken aback:&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lh3.ggpht.com/_eJ-aAjApSE0/Sg1IHLqFAcI/AAAAAAAABA4/EcfUcmYO2Sg/%5BUNSET%5D.jpg&quot;&gt;&lt;img src='http://lh3.ggpht.com/_eJ-aAjApSE0/Sg1IHLqFAcI/AAAAAAAABA4/EcfUcmYO2Sg/%5BUNSET%5D.jpg?imgmax=800' style='max-width:400px;'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the constraint resulted in both lower WIP and lower throughput. This makes sense when you consider that there were far more occasions during the pull game than during the push game when players were unable to process the full number of workpieces indicated by the die.&lt;br /&gt;&lt;br /&gt;Looking back at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.vancouver.wsu.edu/fac/holt/em530/Docs/DiceGames.htm'&gt;game notes&lt;/a&gt;, it is noted that if the simulation is run for much longer than 10 days, the pull (or Kanban) system &quot;will rarely produce as much as the traditional push&quot;. This may have escaped the attention of some readers (or perhaps it's a more recent edit - I don't know).&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lh4.ggpht.com/_eJ-aAjApSE0/Sg1J_0PTIvI/AAAAAAAABA8/mMHU63cb0ek/%5BUNSET%5D.jpg&quot;&gt;&lt;img src='http://lh4.ggpht.com/_eJ-aAjApSE0/Sg1J_0PTIvI/AAAAAAAABA8/mMHU63cb0ek/%5BUNSET%5D.jpg?imgmax=800' style='max-width:400px;'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My conclusion is that you get nothing for free. The cost of reducing WIP is reduced throughput, which is perfectly acceptable as long as you're aware of it. Software development projects are not production lines in any case, so it is very unlikely that any developer will sit around kicking her or his heels if the work runs out on a given day. There are always low priority tasks such as fettling the build system, cleaning up the documentation on the project Wiki, answering user support requests etc. - or just take the next item off the product backlog and raise the kanban limit temporarily.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-2076625803593208626?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-2076625803593208626</guid>
         <pubDate>Fri, 15 May 2009 04:59:00 -0700</pubDate>
      </item>
      <item>
         <title>Scaling Software Agility Presentation by Dean Leffingwell</title>
         <link>http://change-challenge.blogspot.com/2009/05/scaling-software-agility-presentation.html</link>
         <description>This is a followup to one of my previous book recommendations - &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/07/scaling-software-agility-by-dean.html&quot;&gt;Scaling Software Agility by Dean Leffingwell&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can access a summary basically of the major themes Dean focusses on for Scaling of Agile: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.squadco.com/presentations/SSA_Overview_SQUAD-Oct-2007.pdf&quot;&gt;Scaling Software Agility (pdf)&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-8625711549713685280?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-8625711549713685280</guid>
         <pubDate>Fri, 15 May 2009 03:41:00 -0700</pubDate>
      </item>
      <item>
         <title>Parallel For Loop in C#: Part 2</title>
         <link>http://jaksa.wordpress.com/2009/05/08/parallel-for-loop-2/</link>
         <description>In the previous part we have implemented a ThreadPoolExecutor that accepts tasks and executes them in parallel. In this part we will implement a parallel for loop.
The parallel for needs to iterate over a collection of items and invoke the specified closure on every item. It has to perform these invocations in parallel and [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=119&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=119</guid>
         <pubDate>Fri, 08 May 2009 07:05:55 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>In the <a rel="nofollow" target="_blank" href="http://jaksa.wordpress.com/2009/05/08/parallel-for-loop-1/">previous part </a> we have implemented a ThreadPoolExecutor that accepts tasks and executes them in parallel. In this part we will implement a parallel for loop.<br />
The parallel for needs to iterate over a collection of items and invoke the specified closure on every item. It has to perform these invocations in parallel and the next instruction should be executed only after all the elements have been processed. When used, it should look something like this:</p>
<pre>ForEach(distributionList, (destination) =&gt; { Message msg = new Message(destination.Address); msg.Content = Encrypt(Content, destination.PublicKey); msg.Send(); Console.WriteLine("sent message to" + destination.Name);
}</pre>
<p>So the signature of the method should be:</p>
<pre>public static void ForEach(ICollection&lt;T&gt; collection, Action&lt;T&gt; action)</pre>
<p>We know that we need to use the ThreadPoolExecutor, enqueue all the actions and execute them and then wait for the executor to finish. But we have a mismatch. The ForEach() method takes a parameterized action, while the thread executor takes an action without any arguments. What we need to do is construct a set of parameterless actions by adding each element of the collection as the parameter of the parameterized action.</p>
<p>action(x) -&gt; action1, action2, action3&#8230; actionN</p>
<p>We can do it with one simple line of code:</p>
<p><code>Action parameterlessAction = (() =&gt; parameterizedAction.Invoke(element));</code></p>
<p>This was first invented in lambda calculus, and it was called a <strong>closure</strong>, because the function gets closed over the free parameter. Hence the (slightly misnamed) term closure that the rest of us programmers use. Most of the programmers would be more familiar with the term <strong>currying</strong> to define this operation.</p>
<p>Our code would take the following form:</p>
<pre>public static void ForEach(ICollection&lt;T&gt; collection, Action&lt;T&gt; action) { ThreadPoolExecutor executor = new ThreadPoolExecutor(); foreach (T element in collection) { Action parameterlessAction = (() =&gt; parameterizedAction.Invoke(element)); executor.AddTask(parameterlessAction); } executor.Finish(); } executor.Finish();
}</pre>
<p>However, this code has a well hidden and nasty bug. The bug is caused by a certain property of closures, which makes them dangerous in the wrong hands. This is also one of the major reasons why many Java developers don&#8217;t want closures. Don&#8217;t you see it? Hmmm&#8230; Are you ready for using closures? <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley'/><br />
Closures require that their free variables have an extent at least as long as the lifetime of the closure itself.<br />
In our scenario we are referring to <code>element</code> inside the <code>parameterlessAction</code>, but the value of <code>element</code> changes with each iteration. So by the time we invoke the closure unexpected results can happen. Fortunately enough, in our case, Visual Studio was able to detect this situation through static analysis and shyly display a warning in the form of a blue squiggly underline. The solution is to assign element to a temporary variable, and the compiler will be smart enough to allocate that variable on the heap instead of the stack, so that the variable has a longer lifetime than the method invocation.<br />
So here&#8217;s the final version of the code:</p>
<pre>public static void ForEach(ICollection&lt;T&gt; collection, Action&lt;T&gt; action) { ThreadPoolExecutor executor = new ThreadPoolExecutor(); foreach (T element in collection) { T parameter = element; Action parameterlessAction = (() =&gt; parameterizedAction.Invoke(parameter)); executor.AddTask(parameterlessAction); } executor.Finish(); } executor.Finish();
}</pre> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/119/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/119/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/119/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/119/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/119/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=119&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
      </item>
      <item>
         <title>Parallel For Loop in C#: Part 1</title>
         <link>http://jaksa.wordpress.com/2009/05/08/parallel-for-loop-1/</link>
         <description>This is the first of the two posts that shows you how to build a parallel for loop in C#.
In this part we will start building a rudimentary ThreadPoolExecutor that will be the core of the parallel execution. It will have has 2 methods: AddTask(Action a) &amp;#8211; it queues up a task to be executed one [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=111&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=111</guid>
         <pubDate>Fri, 08 May 2009 03:32:05 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>This is the first of the two posts that shows you how to build a parallel for loop in C#.</p>
<p>In this part we will start building a rudimentary ThreadPoolExecutor that will be the core of the parallel execution. It will have has 2 methods:</p>
<ul>
<li><code>AddTask(Action a)</code> &#8211; it queues up a task to be executed one of the threads in the pool.</li>
<li><code>Finish()</code> &#8211; signals the executor to stop accepting any other tasks and wait till all tasks are completed.</li>
</ul>
<p>The implementation is based on the BlockingQueue implemented in the <a rel="nofollow" target="_blank" href="http://jaksa.wordpress.com/2009/05/07/blocking-queue-in-c/">previous post</a>. It uses 10 worker threads that constanty get tasks from the queue and execute them. Since it is a blocking queue, the workers will block untill someone puts a task in the queue. The queue is thread safe, so every task will be processed only by one worker.</p>
<p>We will start by implementing the logic that queues up the tasks and the worker threads that execute the tasks, later we will thing about termination.</p>
<pre> public class ThreadPoolExecutor { private readonly BlockingQueue tasks = new BlockingQueue(); private readonly Thread[] workers; public ThreadPoolExecutor() { workers = new Thread[10]; for (int i = 0; i &lt; workers.Length; i++) { workers[i] = new Thread(run); workers[i].Start(); } } public void AddTask(Action task) { tasks.Enqueue(task); } private void run() { while (true) { tasks.Get().Invoke(); } } }
</pre>
<p>Now we need to add the termination condition. Let&#8217;s start by just not accepting new threads, and later we will think about waiting for the tasks to be processed. We will use a boolean that indicates whether the ThreadPoolExecutor is open or closed. If it is open, it can accept new tasks. Once the Finish() method gets called, the ThreadPoolExecutor becomes closed and doesn&#8217;t accept any new task.</p>
<pre>
public class ThreadPoolExecutor { private bool open = true; // open to accept new tasks private readonly BlockingQueue tasks = new BlockingQueue(); private readonly Thread[] workers; ... public void AddTask(Action task) { if (open) { tasks.Enqueue(task); } else { throw new Exception("Queue is closed"); } } public void Finish() { open = false; } private void run() { while (true) { tasks.Get().Invoke(); } } }
</pre>
<p>The problem with this implementation is that the Finish() method doesn&#8217;t wait for all tasks to be processed, but returns immediately. The tasks to be processed include the ones in the queue along with the ones being currently processed by the workers. We will introduce a counter to keep track of this number. The Finish() method will block until that counter reaches 0. For blocking we will use <a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx">System.Threading.Monitor</a> and we will synchronize on &#8220;this&#8221;. Moreover, once all the tasks have been processed, we&#8217;ll interrupt all the worker threads that are blocked on the queue.</p>
<pre>using System;
using System.Collections.Generic;
using System.Threading; namespace Concurrent { public class ThreadPoolExecutor { private bool open = true; // open to accept new tasks private readonly BlockingQueue tasks = new BlockingQueue(); private readonly Thread[] workers; private int pendingTasks; // the number of tasks in the queue public ThreadPoolExecutor() { workers = new Thread[10]; for (int i = 0; i &lt; workers.Length; i++) { workers[i] = new Thread(run); workers[i].Start(); } } public void AddTask(Action task) { lock (this) { if (open) { tasks.Enqueue(task); pendingTasks++; } else { throw new Exception("Queue is closed"); } } } public void Finish() { lock(this) { open = false; // wait till all tasks are finished while (pendingTasks &gt; 0) { Monitor.Wait(this); } // kill the workers waiting for more tasks foreach (Thread worker in workers) { worker.Interrupt(); } } } private void run() { try { while (true) { lock (this) { if (!open &amp;&amp; pendingTasks == 0) break; // if we're not open anymore and there are no tasks in queue, break the loop } // don't block other threads while processing the task tasks.Get().Invoke(); lock (this) { pendingTasks--; Monitor.PulseAll(this); // notify waiting threads that the tasks are all processed } } } catch(ThreadInterruptedException) {} } }
}</pre>
<p>In order to parallelize your program, divide it in concurrently executable tasks and wrap every task in an Action object. For convenience you can also use closures. Add all the tasks to the ThreadPoolExecutor and wait for them to finish by calling the Finish() method.</p>
<p>In the next post we will be adding some syntactic sugar to implement a parallel for construct.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/111/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/111/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/111/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/111/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/111/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=111&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
      </item>
      <item>
         <title>Second Opinions</title>
         <link>http://peripateticaxiom.blogspot.com/2009/05/second-opinions.html</link>
         <description>Got an opinion piece up in E&amp;amp;T magazine regarding second opinions.&lt;br /&gt;&lt;br /&gt;Many thanks to all who &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.reddit.com/r/programming/comments/7yqzr/why_dont_we_see_it_consultancies_getting_second/&quot;&gt;responded &lt;/a&gt;to my earlier &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/2009/02/consulting-engineers.html&quot;&gt;posts &lt;/a&gt;and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.linkedin.com/answers/technology/software-development/TCH_SFT/441523-2064343?browseIdx=0&amp;amp;sik=1241774570392&quot;&gt;enquiries &lt;/a&gt;about that. I'll be posting digests of some stories soon.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-4312067199028188360?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-4312067199028188360</guid>
         <pubDate>Fri, 08 May 2009 03:16:00 -0700</pubDate>
      </item>
      <item>
         <title>Blocking Queue in C#</title>
         <link>http://jaksa.wordpress.com/2009/05/07/blocking-queue-in-c/</link>
         <description>Here&amp;#8217;s a simple implementation of a blocking queue in C#. This can be used for consumer producer scenarios, buffered messaging, worker pools etc.
using System.Collections.Generic;
using System.Threading; namespace BlockingQueue{
public class BlockingQueue&amp;#60;T&amp;#62; { private Queue&amp;#60;T&amp;#62; q = new Queue&amp;#60;T&amp;#62;(); public void Enqueue(T element) { q.Enqueue(element); [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=99&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=99</guid>
         <pubDate>Thu, 07 May 2009 02:39:39 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>Here&#8217;s a simple implementation of a blocking queue in C#. This can be used for consumer producer scenarios, buffered messaging, worker pools etc.</p>
<pre><span style="color:#3333ff;">using </span>System.Collections.Generic;
<span style="color:#3333ff;">using </span>System.Threading; <span style="color:#3333ff;">namespace </span>BlockingQueue{
<span style="color:#3333ff;">public </span><span style="color:#3333ff;">class </span>BlockingQueue&lt;T&gt; { <span style="color:#3333ff;">private </span>Queue&lt;T&gt; q = <span style="color:#3333ff;">new </span>Queue&lt;T&gt;(); <span style="color:#3333ff;">public void </span>Enqueue(T element) { q.Enqueue(element); <span style="color:#3333ff;">lock </span>(q) { Monitor.Pulse(q); } } <span style="color:#3333ff;">public </span>T Get() { <span style="color:#3333ff;">lock</span>(q) { <span style="color:#3333ff;">while </span>(q.Count == 0) { Monitor.Wait(q); } <span style="color:#3333ff;">return </span>q.Dequeue(); } }
}
}</pre> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/99/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=99&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
      </item>
      <item>
         <title>Distributed bug-tracking in Haskell</title>
         <link>http://aspsp.blogspot.com/2009/05/distributed-bug-tracking-in-haskell.html</link>
         <description>At the recent &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spaconference.org/spa2009/&quot;&gt;SPA 2009&lt;/a&gt; conference, there was a lot of talk about functional programming, Haskell in particular (a couple of years ago, the flavour of the month had been Erlang). Just to prove that Haskell is no longer &quot;just a research language&quot;, along comes &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.distract.wellquite.org/&quot;&gt;DisTract&lt;/a&gt;, a distributed issue-tracking system that runs in Firefox browsers. If you're already using Git, Darcs, Mercurial or Monotone as your distributed software configuration management solution, the author reasoned, why shouldn't you be able to close bugs while you're off-line at the same time as you check in your fix? Caveat: I have not tried this yet, but it sounds like a really neat idea. Does anyone know of a user forum?&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-3223512199395535088?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-3223512199395535088</guid>
         <pubDate>Tue, 05 May 2009 09:56:00 -0700</pubDate>
      </item>
      <item>
         <title>Thanking Your Teacher</title>
         <link>http://change-challenge.blogspot.com/2009/05/thanking-your-teacher.html</link>
         <description>&quot;The best way of making an offering to your teacher is to practise what you have been taught&quot;&lt;br /&gt;&lt;br /&gt;- HH The Dalai Lama from &quot;The Essential Dalai Lama&quot;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-1343484092441977936?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-1343484092441977936</guid>
         <pubDate>Sat, 02 May 2009 04:34:00 -0700</pubDate>
      </item>
      <item>
         <title>Time Tracking Tools</title>
         <link>http://jaksa.wordpress.com/2009/05/01/time-tracking-tools/</link>
         <description>Have you ever asked yourself how much time during the day in the office do you spend looking at funny youtube videos, reading emails, taking coffee or doing some boring administrative task that keeps you from getting your work finished? I&amp;#8217;ve actually been asking myself that for what it feels my entire life. I always [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=91&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=91</guid>
         <pubDate>Fri, 01 May 2009 03:45:07 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>Have you ever asked yourself how much time during the day in the office do you spend looking at funny youtube videos, reading emails, taking coffee or doing some boring administrative task that keeps you from getting your work finished? I&#8217;ve actually been asking myself that for what it feels my entire life. I always tought that a well organized and productive 3 hours could be more valuable than a whole day of distractions. I always wanted to measure that productivity in detail and see what things I&#8217;m spending my time on and how much. Now I finally can.</p>
<p>A few months ago I found out on <a rel="nofollow" target="_blank" href="http://lifehacker.com/">Lifehacker</a> about this software called <a rel="nofollow" target="_blank" href="http://www.rescuetime.com/">RescueTime</a> that tracks how you spend your time on a computer. It&#8217;s free and you run it in the background. It categrorizes your activities in Communication, Development Tools, Reference/Search etc. If you are using a browser it is smart enough to distinguish which sites are you accessing, so reading The Server Side and Failblog.org are considered two different activities.</p>
<p> </p>
<p><img class="aligncenter size-medium wp-image-93" title="rescuetime-screenshot" src="http://jaksa.files.wordpress.com/2009/05/rescuetime-screenshot.png?w=300&#038;h=261" alt="rescuetime-screenshot" width="300" height="261"/></p>
<p>One downside of RescueTime is that it posts your usage statistics to their servers, so if you don&#8217;t want anyone to see how much time you spent&#8230; watching porn in the office, you might choose to disable RescueTime for a couple of hours. On the other side, your usage statistics are accessible only by you, so your boss can&#8217;t detract from your salary every 5 mins you spent checking your private mail.</p>
<p>Another downside is that it doesn&#8217;t show you when exactly did you start working with a particular program and when were you AFK. So you can&#8217;t distinguish between a meeting and a lunch break.</p>
<div>
<div>Both of these problems are solved by <a rel="nofollow" target="_blank" href="http://www.manictime.com/">ManicTime</a>. Manic time works only locally and gives you information on what did you do at an exact moment of the day: </div>
<div><img class="aligncenter size-medium wp-image-94" title="manictime-screenshot" src="http://jaksa.files.wordpress.com/2009/05/manictime-screenshot.png?w=300&#038;h=219" alt="manictime-screenshot" width="300" height="219"/></div>
<div>
<p> </p>
<p> </p>
<p>The only downside of ManicTime is that it is too fine grained so you don&#8217;t get the quick overview that you can get in RescueTime. Currently I&#8217;m using both of them until I decide which one is better or one of them implements the functionalities of the other.</p></div>
</div> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/91/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/91/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/91/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/91/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/91/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=91&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2009/05/rescuetime-screenshot.png?w=300" medium="image">
            <media:title>rescuetime-screenshot</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2009/05/manictime-screenshot.png?w=300" medium="image">
            <media:title>manictime-screenshot</media:title>
         </media:content>
      </item>
      <item>
         <title>Active and Passive Replication in Distributed Systems</title>
         <link>http://jaksa.wordpress.com/2009/05/01/active-and-passive-replication-in-distributed-systems/</link>
         <description>In the distributed systems research area replication is mainly used to provide fault tolerance. The entity being replicated is a process. Two replication strategies have been used in distributed systems: Active and Passive replication. In active replication each client request is processed by all the servers. Active Replication was first introduced by Leslie Lamport under the [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=84&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=84</guid>
         <pubDate>Fri, 01 May 2009 03:35:47 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>In the distributed systems research area replication is mainly used to provide fault tolerance. The entity being replicated is a process. Two replication strategies have been used in distributed systems: <strong>Active </strong>and <strong>Passive </strong>replication.</p>
<p><img class="aligncenter size-full wp-image-85" title="active-passive-replication" src="http://jaksa.files.wordpress.com/2009/02/active-passive-replication.gif?w=557&#038;h=253" alt="active-passive-replication" width="557" height="253"/></p>
<p>In <strong>active replication</strong> each client request is processed by all the servers. Active Replication was first introduced by <a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/um/people/lamport/">Leslie Lamport</a> under the name <strong>state machine replication</strong>. This requires that the process hosted by the servers is <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Deterministic_algorithm">deterministic</a>. <strong>Deterministic </strong>means that, given the same initial state and a request sequence, all processes will produce the same response sequence and end up in the same final state. In order to make all the servers receive the same sequence of operations, an <a rel="nofollow" target="_blank" href="http://doi.acm.org/10.1145/1041680.1041682">atomic broadcast</a> protocol must be used. An atomic broadcast protocol guarantees that either all the servers receive a message or none, plus that they all receive messages in the same order. The big disadvantage for active replication is that in practice most of the real world servers are non‐deterministic. Still active replication is the preferable choice when dealing with real time systems that require quick response even under the presence of faults or with systems that must handle <a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/um/people/lamport/pubs/byz.pdf">byzantine faults</a>. </p>
<p>In <strong>passive replication </strong>there is only one server (called primary) that processes client requests. After processing a request, the primary server updates the state on the other (backup) servers and sends back the response to the client. If the primary server fails, one of the backup servers takes its place. Passive replication may be used even for non‐deterministic processes. The disadvantage of passive replication compared to active is that in case of failure the response is delayed.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/84/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/84/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/84/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/84/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/84/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=84&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2009/02/active-passive-replication.gif" medium="image">
            <media:title>active-passive-replication</media:title>
         </media:content>
      </item>
      <item>
         <title>The Ideal Student</title>
         <link>http://change-challenge.blogspot.com/2009/04/ideal-student.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Tsongkhapa&quot;&gt;Lama Tsong Khapa&lt;/a&gt; in one of his &quot;Great Exposition&quot; writings stated that the 3 principal qualifications of an ideal student are:&lt;br /&gt;&lt;br /&gt;1. An objective and open mind&lt;br /&gt;2. The intelligence to judge between right and wrong&lt;br /&gt;3. The enthusiasm for and interest in the subject&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-3102130011805894468?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-3102130011805894468</guid>
         <pubDate>Thu, 30 Apr 2009 04:30:00 -0700</pubDate>
      </item>
      <item>
         <title>Online Equation Builder</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/pGecQGaYNro/online-equation-builder.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/pGecQGaYNro&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7689999348921680988</guid>
         <pubDate>Wed, 29 Apr 2009 07:27:00 -0700</pubDate>
      </item>
      <item>
         <title>Reveal to others</title>
         <link>http://change-challenge.blogspot.com/2009/04/reveal-to-others.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Dharmakirti&quot;&gt;Dharmakirti&lt;/a&gt; said that there is no way that you can reveal to others that which is hidden to yourself...&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-6854217235509860234?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-6854217235509860234</guid>
         <pubDate>Tue, 28 Apr 2009 04:26:00 -0700</pubDate>
      </item>
      <item>
         <title>Studying without the desire</title>
         <link>http://change-challenge.blogspot.com/2009/04/studying-without-desire.html</link>
         <description>&quot;If you study without the desire to relate what you are learning to your own life through practice, you run the risk of becoming hardened or apathetic&quot;&lt;br /&gt;&lt;br /&gt;- HH The Dalai Lama - &quot;The Essential Dalai Lama&quot;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-7307266358260879057?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-7307266358260879057</guid>
         <pubDate>Sun, 26 Apr 2009 04:18:00 -0700</pubDate>
      </item>
      <item>
         <title>Identity as a Process</title>
         <link>http://peripateticaxiom.blogspot.com/2009/04/identity-as-process.html</link>
         <description>Returning to a topic I've &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://clublet.com/why?TempleThing&quot;&gt;thought about&lt;/a&gt; before: identity is a problem. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I expect that most of you to be familiar with the &quot;my grandfather's axe/&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Ship_of_Theseus&quot;&gt;boat&lt;/a&gt;/knife...&quot; problem. In short, how does the identity of a composite object vary (or not) as the identities of the components vary? One proposed solution is the so–called &lt;i&gt;perdurantist&lt;/i&gt; approach which hinges on the observation (at once both banal and deeply challenging) that what we think of as objects in the world are really structures with extent in three spacial and one temporal dimension (pace &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Kaluza%E2%80%93Klein_theory&quot;&gt;Kaluza-Klein&lt;/a&gt; type arguments). We don't seem to be very good at that sort of thinking. Note that perdurantism seems still to be talking about fixing the boundaries of a thing in order to identify it. I think that's missing a trick.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://vorlon.case.edu/~beer/Papers/varela.pdf&quot;&gt;This&lt;/a&gt; [pdf] (via &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://michaelfeathers.typepad.com/michael_feathers_blog/&quot;&gt;Michael Feathers&lt;/a&gt;) is a treatment of that trick I've not seen before. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In that paper the biological concept of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://michaelfeathers.typepad.com/michael_feathers_blog/&quot;&gt;autpoiesis&lt;/a&gt; (and the complex of ideas around it) is used to analyse the working of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Glider_(Conway's_Life)&quot;&gt;glider&lt;/a&gt; pattern in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life&quot;&gt;Conway's Game of Life&lt;/a&gt;. I read the paper as telling us that identity of a glider is extent of the continuation of the &lt;i&gt;process&lt;/i&gt; which at any given time looks to us like a glider.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, how to apply this understanding elsewhere...&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-5270717966246691397?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-5270717966246691397</guid>
         <pubDate>Thu, 23 Apr 2009 01:08:00 -0700</pubDate>
      </item>
      <item>
         <title>Not the Best View of London</title>
         <link>http://change-challenge.blogspot.com/2009/04/not-best-view-of-london.html</link>
         <description>Three weeks ago I enthused about my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2009/03/best-view-of-london.html&quot;&gt;Best View of London&lt;/a&gt; as seen from an airplane at sunset. And I mentioned that I hoped to repeat the experience again soon.&lt;br /&gt;&lt;br /&gt;Well, soon - 17 April 2009 - has now come and gone, and unfortunately my view was completely blocked by the some very low hanging cloud, and rainy weather. Lovely.&lt;br /&gt;&lt;br /&gt;(so that was &quot;the good&quot;....)&lt;br /&gt;&lt;br /&gt;Now for &quot;the bad&quot;...&lt;br /&gt;&lt;br /&gt;I climbed into a nice shiny 7-seater mini-cab for my journey home and began (or tried) to unwind from quite a testy week on the client site in Switzerland. We drove along slowly, mindful of the wet weather, and the darkening conditions. There was quite a bit of traffic ... more than I am accustomed to of late. Perhaps the warming weather is bring more visitors to London for the weekend. Or not.&lt;br /&gt;&lt;br /&gt;Turns out my driver has only been doing this job for 1 month. Which is approximately 48 months shorter than any other mini-cab driver I have had the pleasure or displeasure of sharing a small space and a journey with. Previously he worked for 5 years in a contact lens manufacturer but had lost his job - his only source of income - due to recessionary conditions and shrinking sales. So this mini cab business is pretty important to a nice guy, well studied, and well experienced.&lt;br /&gt;&lt;br /&gt;Suddenly the fool 2-4 cars ahead of us in the left lane of the A4 once again fluffed around on the road ... brake lights lighted up for no apparent reason, we all started braking. Some of us harder than others. Some of us in smaller cars. Oops!! We were unfortunately too close this second time. &lt;br /&gt;&lt;br /&gt;1x BANG! &lt;br /&gt;&lt;br /&gt;2x BANG!!&lt;br /&gt;&lt;br /&gt;3x BANG!!!&lt;br /&gt;&lt;br /&gt;:( &lt;br /&gt;&lt;br /&gt;(who says 3rd time lucky?)&lt;br /&gt;&lt;br /&gt;Everyone is out of the vehicles, examining damage, standing in the road, beginning to point fingers, etc etc. Typical inexperienced accident stuff. I started checking that no one was (seriously) injured, asked people to step off the road, calmed them a little and started actioning photo and detail taking so we could all get out of there ASAP before more rain, more darkness, or worse ... causing another accident.&lt;br /&gt;&lt;br /&gt;The driver behind us fled the scene whilst no one was specifically watching. Luckily for her, and her navy blue BMW 1-series, she seemed to have little/no damage. A slightly different story for the mini-cab's rear bumper. But, no real problem at this time - 1 less person and vehicle details to take.&lt;br /&gt;&lt;br /&gt;I am watching the traffic coming towards us - 3 lanes full. And I am getting more and more nervous by the second ... so I walk up the road a couple of metres, whilst on the pavement. And I try to work out how to signal that drivers should be more cautious....? No torch, I am wearing dark clothing ... hmmm? It is getting darker and wetter ... &lt;br /&gt;&lt;br /&gt;Now for &quot;the ugly&quot;&lt;br /&gt;&lt;br /&gt;A ?maniac? comes hurtling past me in the left lane - our blocked up lane - and slams on his brakes to the point of stopping to avoid the 3 cars stopped there with their hazard lights flashing. He puts his indicator on to rejoin the middle lane. And waits. And waits.&lt;br /&gt;&lt;br /&gt;A nice lady slows down in the middle lane and indicates he should rejoin ... she slows down, he sits and waits; she slows down more, he sits still and waits; she slows down even more, he sits and still waits. &lt;br /&gt;&lt;br /&gt;4x BANG!!!!&lt;br /&gt;&lt;br /&gt;5x BANG!!!!!&lt;br /&gt;&lt;br /&gt;Now, the ?maniac? waits no longer and in a flash (of genius) he is gone.&lt;br /&gt;&lt;br /&gt;And the other 3 vehicle drivers are getting out ... into all that darkness, into all that wetness, into all that huge amount of traffic! I am getting very very scared. Luckily 1 of them seems to know what to do, and rapidly after making sure no one is majorly injured they all get into the cars and pull over, behind us.&lt;br /&gt;&lt;br /&gt;And then the London &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.met.police.uk/&quot;&gt;Metropolitan Police Service&lt;/a&gt; show up, take control and ensure safety. I relax. The cars are all moved into a side street, statements are taken, alcohol checks, medication checks and ownerships are verified. Details are copied for all.&lt;br /&gt;&lt;br /&gt;1.5 hours later, we're all on our way again and things have gone as well as they possibly could under such circumstances. Really. I was very impressed with &quot;The Met&quot; and their handling of the situation. For want of a better expression - &quot;good service&quot;! Bravo!!&lt;br /&gt;&lt;br /&gt;I do feel even more sad for my driver though - his single source of income is seriously not going to be earning him anything for the next 2 weeks or so.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-3401588796567818882?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-3401588796567818882</guid>
         <pubDate>Sun, 19 Apr 2009 08:28:00 -0700</pubDate>
      </item>
      <item>
         <title>QCon Panel: A Great Leap Forward or Exposed Artery?</title>
         <link>http://peripateticaxiom.blogspot.com/2009/04/qcon-panel-great-leap-forward-or.html</link>
         <description>A &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/QConLondon2008&quot;&gt;QCon &lt;/a&gt;panel disucssion re &quot;Transparency&quot; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/news/2009/04/transparency-leap-or-exposure&quot;&gt;is now up&lt;/a&gt;. It features &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.threeriversinstitute.org/blog/&quot;&gt;Kent Beck&lt;/a&gt;, Chris Matts, John Nolan and myself, with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.m3p.co.uk/blog/&quot;&gt;Steve Freeman&lt;/a&gt; in the chair.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;Treppenwitz&lt;/em&gt; was pretty strong on this one. What I'm thinking now is that instead of all that ghastly droning on I did, I should have said &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.biblegateway.com/passage/?search=John%208:32;&amp;amp;version=9;&quot;&gt;&quot;the truth shall make you free&quot; &lt;/a&gt;. The only thing to watch out for is that being free, although far superior to the alternative, might not be particularly comfortable.&lt;br /&gt;&lt;br /&gt;But it is still far superior.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-7370967944504450942?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-7370967944504450942</guid>
         <pubDate>Fri, 17 Apr 2009 09:46:00 -0700</pubDate>
      </item>
      <item>
         <title>Darren on Ruby: Migrating Rails to Tomcat / JEE, Part 3: Using Warbler (Rack) to Deploy to Tomcat, Jetty or GlassFish</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/FLuWDLf4FWo/darren-on-ruby-migrating-rails-to-jee_17.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/FLuWDLf4FWo&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-3984320296179051311</guid>
         <pubDate>Thu, 16 Apr 2009 16:28:00 -0700</pubDate>
      </item>
      <item>
         <title>Darren on Ruby: Migrating Rails to Tomcat / JEE, Part 2: Migrating Your Data From SQLite3 to Derby</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/dqZGa9JWhVs/darren-on-ruby-migrating-rails-to-jee.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/dqZGa9JWhVs&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7739743062181556885</guid>
         <pubDate>Tue, 14 Apr 2009 03:29:00 -0700</pubDate>
      </item>
      <item>
         <title>Syntax Highlighting 2.0 on Blogger</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/Pky2bh-cI4c/syntax-highlighting-20-on-blogger.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/Pky2bh-cI4c&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7683602495200717181</guid>
         <pubDate>Sat, 11 Apr 2009 08:28:00 -0700</pubDate>
      </item>
      <item>
         <title>Software Craftsmanship 2010</title>
         <link>http://peripateticaxiom.blogspot.com/2009/04/software-craftsmanship-2010.html</link>
         <description>Apparently &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://parlezuml.com/blog/?postid=797&quot;&gt;there will be one&lt;/a&gt;. Excellent! For all my growing distaste for the This Movement and That Manifesto and what all that's springing up around the parts of the industry that I see most closely, a place that happens to be of the same name as one where people can come together and share an enjoyment of good code and coding is a fine thing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Jason says that he's &quot;banning talks, presentations or any other kind of session that doesn't involve real live coding&quot; I appreciate the gesture, but I'm not sure that's quite right. I found that Ade's session on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kerrybuckley.org/2009/03/02/software-craftsmanship-2009/&quot;&gt;mapping personal practices&lt;/a&gt; particularly valuable—although it could have benefited from another hour or so. None–the–less a programmers' conference with programming as its core topic illustrated through programming is a too–rare thing and Jason is to be commended for making one happen. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Both of the sessions that I ran there involved real coding by attnedees and even though I wasn't coding myself I learned plenty from the reactions of those who were, such as &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gojko.net/2009/02/27/thought-provoking-tdd-exercise-at-the-software-craftsmanship-conference/&quot;&gt;Gojko's&lt;/a&gt; on the TDD session. I've not come across a better forum elsewhere for that kind of discussion on that sort of scale than the SC conference, so having another one seems like a very good thing.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-9003237916455125997?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-9003237916455125997</guid>
         <pubDate>Sat, 11 Apr 2009 09:25:00 -0700</pubDate>
      </item>
      <item>
         <title>Darren on Ruby: Migrating Rails to Tomcat / JEE, Part 1: Switching to JRuby &amp; Apache Derby</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/Qho_MqU0JFo/migrating-rails-to-jee-part-1-switching.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/Qho_MqU0JFo&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7969152418791161062</guid>
         <pubDate>Sat, 11 Apr 2009 05:36:00 -0700</pubDate>
      </item>
      <item>
         <title>Darren on Ruby: JGem, JRake... For Your Convenience</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/0xHcVjMHr14/jgem-jrake-for-your-convenience.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/0xHcVjMHr14&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7719448289216532985</guid>
         <pubDate>Sat, 11 Apr 2009 03:42:00 -0700</pubDate>
      </item>
      <item>
         <title>SPA2009 - first impressions</title>
         <link>http://aspsp.blogspot.com/2009/04/spa2009-first-impressions.html</link>
         <description>&lt;div&gt;Maybe I'm biased, of course, but for me the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.spaconference.org/spa2009/'&gt;SPA2009&lt;/a&gt; conference felt even better than last year's. I think it had the right mix of technical and non-technical sessions, mostly of very high quality, and a few really interesting BOF (birds of a feather) sessions - which for once, didn't feel as if they were just squeezed in at the last minute.&lt;br/&gt;&lt;br/&gt;Functional programming (in particular, Haskell) was a major theme this year, as was testing. My eyes were opened to the possibility of doing test-driven development (TDD) in Haskell - in fact, functional languages are better at this than imperative (stateful) languages. It was also good to meet up with a lot of familiar faces at the joint &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://www.xpdeveloper.net/'&gt;XtC&lt;/a&gt; meeting on the Tuesday night.&lt;br/&gt;&lt;br/&gt;My session notes are on my other laptop. I will try to post them on the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://bcs-spa.org/'&gt;SPA SG site&lt;/a&gt; over the Easter weekend, other duties permitting.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=525cec7a-cb38-8a33-a5b5-abc1adac3a70' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-8492371426030123673?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-8492371426030123673</guid>
         <pubDate>Thu, 09 Apr 2009 07:02:00 -0700</pubDate>
      </item>
      <item>
         <title>What's Up With All The Cynicism in IT?</title>
         <link>http://change-challenge.blogspot.com/2009/04/whats-up-with-all-cynicism-in-it.html</link>
         <description>At &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spaconference.org/spa2009/index.php&quot;&gt;SPA2009&lt;/a&gt;, I had a little session titled &quot;What's Up With All The Cynicism in IT?&quot;. It was unfortunately quite time reduced from my original plan, but I did manage to impart a little knowledge of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/03/6-hats-of-thinking-lateral-thinking.html&quot;&gt;Edward De Bono's Six Thinking Hats&lt;/a&gt; method to a group of 8 varied participants, who did supply quite a bit of &quot;food for thought&quot;.&lt;br /&gt;&lt;br /&gt;I've published my presentation, and the outputs of the group work sessions on the SPA2009 wiki: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spaconference.org/cgi-bin/wiki.pl/?WhatsUpWithAllTheCynicismInITOutputs&quot;&gt;What's Up With All The Cynicism In IT? Outputs&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4528910933820670113?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4528910933820670113</guid>
         <pubDate>Thu, 09 Apr 2009 05:50:00 -0700</pubDate>
      </item>
      <item>
         <title>Fallacy as tool</title>
         <link>http://peripateticaxiom.blogspot.com/2009/04/fallacy-as-tool.html</link>
         <description>In the comments to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.juliansanchez.com/2009/04/06/climate-change-and-argumentative-fallacies/&quot;&gt;this post&lt;/a&gt; regarding the level of debate regarding climate change in certain circles &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pithandsubstance.blogspot.com/&quot;&gt;Pithlord &lt;/a&gt;has this to say:&lt;br /&gt;&lt;blockquote&gt;Most fallacies aren’t really fallacies when you reinterpret them as Bayesian reasons to give an idea more credence rather than iron-clad syllogisms. Without [...] the “ad hominem fallacy” [...] you’d give all your money to Nigerian spammers.&lt;/blockquote&gt;That's a very nice formulation of the idea that the &quot;fallacies&quot; of logic are amongst the tools of rehtoric. This is an notion that has fasinated me ever since I first read &lt;em&gt;Zen and the Art of Motorcyle Maintainance&lt;/em&gt;. The rhetorical apporach may not demand agreement (in the way that a sound and valid argument would) but it does tend to persuade. And the answers given by fallacious arguments are not neccessarily wrong, just uncertain.&lt;br /&gt;&lt;br /&gt;Many folks in the IT industry seem to want to bludgeon their interlocutors into agreement with something that looks a lot like a proof (mea culpa). As I get older the gentle art of persuasion seems more and more attractive.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23912478-3514425722115090899?l=peripateticaxiom.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>keithb</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-23912478.post-3514425722115090899</guid>
         <pubDate>Wed, 08 Apr 2009 06:19:00 -0700</pubDate>
      </item>
      <item>
         <title>SPA2009</title>
         <link>http://change-challenge.blogspot.com/2009/04/spa2009.html</link>
         <description>Also known as the British Computing Society Software Practice Advancement Conference, 2009. I attended &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spaconference.org/spa2009/index.php&quot;&gt;SPA2009&lt;/a&gt; from Sunday-Wednesday (5-8 April 2009) and was really pleased that I did! There were a lot of new faces, a lot of old faces, great new topics and content on programming, process and people stuff. There were some strong opinions that people were passionate about and argued the merits of - a great learning and networking event!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-2278510184910352977?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-2278510184910352977</guid>
         <pubDate>Wed, 08 Apr 2009 05:45:00 -0700</pubDate>
      </item>
      <item>
         <title>Automating testing of web sites with multiple browsers</title>
         <link>http://aspsp.blogspot.com/2009/04/automating-testing-of-web-sites-with.html</link>
         <description>After several days of trying, I've just abandoned an attempt to automate web site tests with multiple browsers (Firefox, Internet Explorer, Safari and Opera under various operating systems). My findings are written up &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://clearspace.openqa.org/message/60051&quot;&gt;here&lt;/a&gt;. Briefly, I think that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://seleniumhq.org/projects/remote-control/&quot;&gt;Selenium RC&lt;/a&gt; has the right architecture, but currently the linkage between the RC server and the browser only works 100% for Firefox. This isn't enough.&lt;br /&gt;&lt;br /&gt;It seems from the documentation that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wtr.rubyforge.org/&quot;&gt;Watir&lt;/a&gt; should support the functionality needed. Can anyone confirm that it's possible to test pages such as &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sisustusliikeid.fi/layout/js/scriptaculous-js-1.7.0/test/functional/ajax_autocompleter2_test.html&quot;&gt;this one&lt;/a&gt; in at least three different browser types with it?&lt;br /&gt;&lt;br /&gt;Update (9 April): I discovered that Selenium RC has a start-up parameter &quot;-proxyInjectionMode&quot;, which is equivalent to choosing the &quot;*pi...&quot; launchers where available. Unfortunately this only works with &quot;*firefox&quot;, so you might just as well use &quot;*pifirefox&quot;. It isn't clear to me why it causes tests to fail when they launch a browser with &quot;*mock&quot;.&lt;br /&gt;&lt;br /&gt;I was also reminded at the SPA2009 conference that it might be worth trying out Cucumber, rSpec, Concordion or other tools, so long as they will drive more than one browser.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-1701960335680678092?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-1701960335680678092</guid>
         <pubDate>Sat, 04 Apr 2009 02:29:00 -0700</pubDate>
      </item>
      <item>
         <title>Best View of London</title>
         <link>http://change-challenge.blogspot.com/2009/03/best-view-of-london.html</link>
         <description>On 27 March 2009, after living in London for 2 years, I got the best view of London I have had yet! &lt;br /&gt;&lt;br /&gt;I was fortunate enough on this day to be flying back to London Heathrow, and arrived over the UK as the sun was beginning to set. I had been napping on the flight until then, and awoke to the plane circling south of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.theo2.co.uk/&quot;&gt;O2 Arena&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Round and round we went ... the green scenery below getting darker and darker. The sun dipped lower, and the City's lights started coming on. Spectacular! The City itself...the tall buildings etc - all I could think was &quot;google maps, with perspectives, eat your heart out!&quot;&lt;br /&gt;&lt;br /&gt;And then finally, we were allowed to proceed to Heathrow ... over Picadily Circus, over Hyde Park, South Kensington ... following the Thames River back ... over Kew Gardens ... and then we were landing.&lt;br /&gt;&lt;br /&gt;I am now hoping that my next return flight on 17 April will come back at sunset again, which is possible because the clocks went back 1 hour :)&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4715827031863578026?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4715827031863578026</guid>
         <pubDate>Mon, 30 Mar 2009 05:29:00 -0700</pubDate>
      </item>
      <item>
         <title>Why people think it's OK to cheat / steal</title>
         <link>http://aspsp.blogspot.com/2009/03/why-people-think-its-ok-to-cheat-steal.html</link>
         <description>Dan Ariely has given a brilliant talk about this and how it impacts the global economic crisis. Watch this on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ted.com/talks/dan_ariely_on_our_buggy_moral_code.html&quot;&gt;Ted&lt;/a&gt; - it'll be 16 minutes well spent. Good insights into human psychology and behaviour.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-7933115424144328560?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-7933115424144328560</guid>
         <pubDate>Thu, 19 Mar 2009 03:51:00 -0700</pubDate>
      </item>
      <item>
         <title>Tools to support agile methods</title>
         <link>http://aspsp.blogspot.com/2009/03/tools-to-support-agile-methods.html</link>
         <description>The whole point of managing a project using an agile method is to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://uncyclopedia.wikia.com/wiki/Agile_software_development&quot;&gt;use lots of coloured cards and post-it notes&lt;/a&gt;, but sometimes you have to fall back on a boring old software tool. The thorny question keeps arising: which one do I recommend?&lt;br /&gt;&lt;br /&gt;Many different project management tools exist, at different price-points and levels of functionality. A long list is shown below. It is important to be clear about a project's requirements for a tool before selecting. Avoid the temptation to extend any tool you select or to spend much effort integrating it with the rest of your project environment – this is a sure way to lock yourself into a single supplier.&lt;br /&gt;&lt;br /&gt;The following list of tools is not exhaustive, though I have kept adding to it as I came across new tools:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.project-open.org&quot;&gt;]project-open[&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.achievo.org&quot;&gt;Achievo&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.activecollab.com&quot;&gt;ActiveCollab&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agilebuddy.com&quot;&gt;Agilebuddy&lt;/a&gt; - reported by a comment on this post to be a full-featured agile project management software tool, which is easy to use and great for Scrum teams. Offered on a subscription model for US$9.95 per user per month&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agilefant.org/&quot;&gt;Agilefant&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agile42.com/cms/pages/download/&quot;&gt;Agilo&lt;/a&gt; – based on the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://trac.edgewall.org/&quot;&gt;Trac&lt;/a&gt; issue-management tool and said to support only a single project at a time&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://airtodo.sourceforge.net/&quot;&gt;airTODO&lt;/a&gt; – PMBOK rather than agile, but minimalist (an Eclipse plug-in)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.extremeplanner.com/&quot;&gt;Extreme Planner&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://confluence.atlassian.com/display/JIRAEXT/GreenHopper&quot;&gt;Greenhopper&lt;/a&gt; – a JIRA plugin favoured by some Scrum teams&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://icescrum.org/&quot;&gt;IceScrum&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://studios.thoughtworks.com/mingle-agile-project-management&quot;&gt;Mingle&lt;/a&gt; - provides a shared workspace for agile teams, supporting XP, Scrum and custom hybrid approaches. Includes a virtual card wall, wiki, charts, reports and more. Integrated with issue tracking and continuous build. Priced US$995 per user with substantial discounts for multiple licences, academic institutions etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pivotaltracker.com/&quot;&gt;Pivotal Tracker&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.projectcards.com/&quot;&gt;ProjectCards&lt;/a&gt; – mixed approach that uses both physical cards and software&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.projectkoach.com/&quot;&gt;ProjectKoach&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rallydev.com/&quot;&gt;Rally&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www-01.ibm.com/software/awdtools/rtc/&quot;&gt;Rational Team Concert&lt;/a&gt; - integrates work item, continuous integration builds and software configuration management (SCM) on the collaborative infrastructure of the Jazz Team Server&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.redmine.org&quot;&gt;redMine&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.scrumworks.com&quot;&gt;Scrumworks&lt;/a&gt; - quite popular free open source package, heavily forms-based, can integrate with JIRA&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.silverstripesoftware.com/&quot;&gt;Silver Catalyst&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.zuehlke.com/en/know-how/technologies/agile-software-development/&quot;&gt;StuffPlanner&lt;/a&gt; – alpha version available by arrangement&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.targetprocess.com/&quot;&gt;TargetProcess&lt;/a&gt; - designed to support Scrum, XP and custom Agile processes particularly in the .NET environment. Includes a comprehensive set of tools and features, including defect-tracking, test management and customer helpdesk portal. Community edition free for up to 5 users&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.twproject.com&quot;&gt;teamwork&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tinypm.com/&quot;&gt;tinyPM&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.versionone.com&quot;&gt;VersionOne&lt;/a&gt; - very full-featured, supports Scrum, DSDM, XP and AUP across multiple projects. Priced from US$348 per user per year, there is a free &quot;team edition&quot; for one team of up to 10&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xpstorystudio.com/&quot;&gt;XP Story Studio&lt;/a&gt; – no development since 2004&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xplanner.org&quot;&gt;XPlanner&lt;/a&gt;&lt;/li&gt; - a popular free open source planning and tracking tool for XP. Quite simple in keeping with the low-ceremony agile approach&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.openxprocess.com/&quot;&gt;xProcess&lt;/a&gt; - free open source project management and process improvement tool, focused particularly on agile and priority-driven approaches. Preconfigured processes include Scrum, FDD, Prince2, Unified and others; can be tailored. Gantt/Burndowns/target status continuously updated. See also &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xprocess.eu.com/&quot;&gt;xProcess Europe&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpweb.sourceforge.net/&quot;&gt;XPWeb&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A number of web sites compare small subsets of the available software tools, including&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agile-tools.net/&quot;&gt;http://www.agile-tools.net/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://brunomiranda.com/past/2008/8/19/agile_project_management_tools/&quot;&gt;http://brunomiranda.com/past/2008/8/19/agile_project_management_tools/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://agilesoftwaredevelopment.com/blog/mattgrommes&quot;&gt;http://agilesoftwaredevelopment.com/blog/mattgrommes&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.life-cycle.de/journal/&quot;&gt;http://www.life-cycle.de/journal/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-955754937492967680?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-955754937492967680</guid>
         <pubDate>Tue, 17 Mar 2009 08:19:00 -0700</pubDate>
      </item>
      <item>
         <title>Latest unwarranted privacy violation</title>
         <link>http://aspsp.blogspot.com/2009/03/latest-unwarranted-privacy-violation.html</link>
         <description>The &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.telegraph.co.uk/news/uknews/4987415/All-travel-plans-to-be-tracked-by-Government.html&quot;&gt;Daily Telegraph&lt;/a&gt; reports that the travel plans and personal details of everyone leaving Britain are to be tracked by the Government. Under the &quot;e-borders&quot; scheme, they intend to make it a criminal offence not to submit, in advance of every trip, personal information such as passport and credit card details, home and email addresses and exact travel plans. This is already starting to happen.&lt;br /&gt;&lt;br /&gt;The kind of thing that e-borders enables is illustrated by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.telegraph.co.uk/news/uknews/road-and-rail-transport/4996018/Motorists-could-be-banned-from-leaving-Britain-over-unpaid-parking-fines.html&quot;&gt;this story&lt;/a&gt;, which shows that you could be stopped from leaving the country if you have unpaid parking fines or indeed any other mark against your name. What are the chances that before the year is out, we'll be reading stories about innocent people trying to travel abroad who get arrested at the airport or sea port thanks to some mix-up?&lt;br /&gt;&lt;br /&gt;With developments like these, it's hard to believe that we are not living in a police state.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-5923391675207754475?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-5923391675207754475</guid>
         <pubDate>Tue, 17 Mar 2009 03:40:00 -0700</pubDate>
      </item>
      <item>
         <title>CodeCity</title>
         <link>http://aspsp.blogspot.com/2009/03/codecity.html</link>
         <description>This looks really intriguing: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.inf.unisi.ch/phd/wettel/codecity-wof.html&quot;&gt;CodeCity&lt;/a&gt; gives a really nice way to visualise properties of Java code bases. An example is shown below (an analysis of Azureus v2.5.00):&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.inf.unisi.ch/phd/wettel/pics/wof/azureus-2500-coarse.png&quot;&gt;&lt;img style=&quot;cursor:pointer;cursor:hand;width:740px;height:390px;&quot; src=&quot;http://www.inf.unisi.ch/phd/wettel/pics/wof/azureus-2500-coarse.png&quot; border=&quot;0&quot; alt=&quot;&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's a free download, so give it a try on your own code!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-2314465954047391338?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-2314465954047391338</guid>
         <pubDate>Tue, 17 Mar 2009 03:33:00 -0700</pubDate>
      </item>
      <item>
         <title>97 Things for Software Architects</title>
         <link>http://egarson.blogspot.com/2009/03/97-things-for-software-architects.html</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki&quot;&gt;97 Things Every Software Architect Should Know&lt;/a&gt; has finally been published, and it's been worth the wait. I have watched it germinate all the way from a friend's whimsical idea on a mailing list (&lt;i&gt;&quot;Hey, this would make a good book!&quot;&lt;/i&gt;) to its birth as hardcopy.&lt;/p&gt;&lt;p&gt;I contributed two of the 97 'Things', &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki/context-is-king-and-simplicity-its-humble-servant&quot;&gt;Context Is King&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki/Heterogeneity%20Wins&quot;&gt;Heterogeneity Wins&lt;/a&gt;. In &lt;b&gt;Context is King&lt;/b&gt;, I postulate that there are no global axioms in the domain of software architecture, but rather that (any) ideal does not live out of context. In &lt;b&gt;Heterogeneity Wins&lt;/b&gt;, I encourage software architects to think outside of the stack, this because I cannot count the number of times that I have consulted on a project where the problem domain was poorly understood, but the technological solution - or, the correct BigCo Framework Extension piece - had already been chosen.&lt;/p&gt;&lt;p&gt;As far as I am aware, &lt;b&gt;97 Things&lt;/b&gt; is the world's first &lt;i&gt;open-source book&lt;/i&gt;, in that all contributions were pre-published and peer-reviewed, and all are Creative Commons-licensed. Furthermore, all of the book's content is available &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki&quot;&gt;online&lt;/a&gt; so you can &lt;b&gt;try before you buy&lt;/b&gt;. But of course, you can't curl up in bed with the web (the Kindle notwithstanding), so you'll probably still want a dead-tree version :-).&lt;/p&gt; &lt;p&gt;An interesting aspect of the book is how some of the axioms &lt;b&gt;contradict one another&lt;/b&gt;. For example, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki/it-s-all-about-performance&quot;&gt;It's all about performance&lt;/a&gt; contradicts my own &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://97-things.near-time.net/wiki/context-is-king-and-simplicity-its-humble-servant&quot;&gt;Context Is King&lt;/a&gt;, because I propose that it is only within scope and business objectives (i.e. context) that an architect has the necessary framework to make the right decisions, while the other promotes the idea that - requirements notwithstanding - nobody wants a system that runs like a snail. (And, while I acknowledge the basic truth of that premise, I would point out that it is context that &lt;i&gt;always&lt;/i&gt; denotes &lt;b&gt;how fast a system should run&lt;/b&gt;, and furthermore that sometimes &lt;b&gt;snail-fast is perfectly acceptable&lt;/b&gt;, e.g. if some other over-arching business goal is met).&lt;/p&gt;&lt;p&gt;It is worth noting that 97 Things will have &lt;b&gt;very good shelf-life&lt;/b&gt; relative to many other software engineering tomes. The advice it contains is fairly generic and technology-agnostic. I favor books that exhibit these qualities, that I know will still be relevant 10 years from now, or (more realistically) after the 6 month lapse has passed between the time I bought it and when I actually found time to study it :-)&lt;/p&gt;&lt;p&gt;Software architecture is a &lt;b&gt;nascent, black art&lt;/b&gt;, and we are still finding our way; I hope within our book you find stimulus and inspiration.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1595066899599866342-1748355739344756747?l=egarson.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>Edward Garson</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-1595066899599866342.post-1748355739344756747</guid>
         <pubDate>Mon, 09 Mar 2009 20:45:00 -0700</pubDate>
      </item>
      <item>
         <title>Introduction to Agile for Traditional Project Managers by Stacia Broderick</title>
         <link>http://change-challenge.blogspot.com/2009/03/introduction-to-agile-for-traditional.html</link>
         <description>I just found this really good Introduction to Agile for Traditional Project Managers presentation that Stacia Broderick put together for Agile 2007. I am quite comfortable with what she says, and the relaxed pace that she presents it at. A well &quot;knit&quot; session integrating some good points from various influences and showing some solid experience she has clearly encountered in real world situations.&lt;br /&gt;&lt;br /&gt;Hosted on InfoQ: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/presentations/Introduction-Agile-Stacia-Broderick&quot;&gt;Introduction-Agile-Stacia-Broderick&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Stacia's blog site: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.agileevolution.com/blog/&quot;&gt;Agile Evolution Blog&lt;/a&gt; ... is not all &quot;agile&quot; focussed, but some gems are scattered. :)&lt;br /&gt;&lt;br /&gt;I think it's a good complement to my Agile Introduction recommendation from about a year ago: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/02/agile-project-management-place-to-start.html&quot;&gt;Agile Project Management - a place to start&lt;/a&gt; though at 1 hour 26 minutes it is a little longer. But I think the time invested is worth it.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-6987186007628922273?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-6987186007628922273</guid>
         <pubDate>Thu, 05 Mar 2009 11:33:00 -0800</pubDate>
      </item>
      <item>
         <title>Darren on Flex: Flexins, Drag 'n' Drop Mixin now with Filtering</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/klEyCaBn5ww/darren-on-flex-flexins-drag-n-drop.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/klEyCaBn5ww&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8114161903549818083</guid>
         <pubDate>Thu, 05 Mar 2009 01:40:00 -0800</pubDate>
      </item>
      <item>
         <title>Typed Literals: Paving The Way For Truly Embedded DSLs</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/1auEVLJA8Y8/typed-literals-paving-way-for-truly.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/1auEVLJA8Y8&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-620482512349865782</guid>
         <pubDate>Tue, 03 Mar 2009 10:48:00 -0800</pubDate>
      </item>
      <item>
         <title>My Favourite Keyboard Shortcuts</title>
         <link>http://aspsp.blogspot.com/2009/02/my-favourite-keyboard-shortcuts.html</link>
         <description>That was the title of a session I proposed for today's first-ever Software Craftsmanship Conference, at the BBC's attractive Media Centre in London's White City. To my surprise, the session was accepted. It worked quite well despite attracting only about half a dozen participants. I certainly learned a good deal from it!&lt;br /&gt;&lt;br /&gt;The&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://softwarecraftsmanship.wikidot.com/myfavouritekeyboardshortcutsoutputs&quot;&gt; output of the session&lt;/a&gt; has been posted on the conference Wiki. However, you'll have to be logged in to see it, as the wiki is private to conference participants. I don't know if Jason Gorman plans to change this now the conference is over.&lt;br /&gt;&lt;br /&gt;The top tips (as a result of a quick spot vote at the end) were:&lt;br /&gt;&lt;br /&gt;The &lt;span style=&quot;font-weight:bold;&quot;&gt;three-step refactoring tango&lt;/span&gt;: Jason's recipe for method extraction where one or more parameters are themselves method calls. In Eclipse, it goes ALT-SHIFT-L (extract local variable), ALT-SHIFT-M (extract method), then ALT-SHIFT-I (inline local variable as method parameter).&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Expand/shrink current selection&lt;/span&gt;: In Eclipse, ALT-SHIFT-up/down arrow or in IDEA, CTRL-w/W. With the cursor on a given word, the word is selected. Repeated applications of the same keyboard combo selects progressively larger portions of the source file (up to and including the entire file). Using the opposite key combination reduces the size of the selection all the way back to 0.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-2231491435964559213?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-2231491435964559213</guid>
         <pubDate>Thu, 26 Feb 2009 14:22:00 -0800</pubDate>
      </item>
      <item>
         <title>Darren on Flex: Flexins, Drag 'n' Drop Mixin</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/892OjwLjIGM/darren-on-flex-flexins-drag-n-drop.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/892OjwLjIGM&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8808069507999126484</guid>
         <pubDate>Wed, 25 Feb 2009 03:54:00 -0800</pubDate>
      </item>
      <item>
         <title>Test-Driven Web Development on Spring and Hibernate</title>
         <link>http://aspsp.blogspot.com/2009/02/test-driven-web-development-on-spring.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://witi-work.blogspot.com/&quot;&gt;Adam Shimali&lt;/a&gt; and I will be piloting our TDD course at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://spa2009.org/&quot;&gt;SPA2009&lt;/a&gt; on the Sunday afternoon. Three two-hour samples of a full two-day course for free - and you get a 10% discount off the cost of the full course for yourself or a colleague.&lt;br /&gt;&lt;br /&gt;The course is very hands-on. If you bring a laptop (Windows or MacOS) we can provide you with the complete Eclipse development environment installation on a CD or memory stick - you'll be good to go in about five minutes. It will help if you've done a bit of Java programming before, but even this is not essential as you'll be paired with someone experienced.&lt;br /&gt;&lt;br /&gt;There's still time to book for SPA2009, but don't delay!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-797403603652258694?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-797403603652258694</guid>
         <pubDate>Wed, 18 Feb 2009 01:57:00 -0800</pubDate>
      </item>
      <item>
         <title>Agile and Lean - complementary or conflicting?</title>
         <link>http://aspsp.blogspot.com/2009/02/agile-and-lean-complementary-or.html</link>
         <description>Dave West has contributed an article entitled &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/articles/backlog-not-waste&quot;&gt;A Marriage Made in Heaven?&lt;/a&gt;. I found it very instructive to read that as well as the comments attached to it. To my mind, there are things that the software community can learn (and has learned) from lean manufacturing, but in many respects software development is much more of a joint creative act. As Dave says, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.naur.com/comp/c1-4.html&quot;&gt;Peter Naur&lt;/a&gt; as long ago as 1985 equated programming with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://zatoichi.homeip.net/~brain/wiki/index.php/Programming_as_theory_building&quot;&gt;collaborative theory-building&lt;/a&gt; - in other words, it has much in common with research at the forefront of physics or mathematics, where results are difficult to predict and effort is almost impossible to forecast.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-8653821927899887098?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-8653821927899887098</guid>
         <pubDate>Tue, 17 Feb 2009 02:53:00 -0800</pubDate>
      </item>
      <item>
         <title>BALPA refuses to co-operate with ID card scheme</title>
         <link>http://aspsp.blogspot.com/2009/02/balpa-refuses-to-co-operate-with-id.html</link>
         <description>Well done, the British Airline Pilots Association. It has refused to co-operate with the odious National ID register, as reported in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.timesonline.co.uk/tol/travel/news/article5741216.ece&quot;&gt;The Times&lt;/a&gt;. I especially enjoyed reading BALPA's clear views on the insidious methods the Government has chosen to bring in the ID cards:&lt;br /&gt;&lt;br /&gt;&quot;It is clear that the Government's staged introduction of biometric identity cards first to overseas students, then to migrant workers and then for aviation workers, represents a way of picking off what are seen as easy targets.&quot;&lt;br /&gt;&lt;br /&gt;It'll be interesting to see what the Home Office chooses to do next. They can't afford to be seen to back down in the face of such a challenge to their &quot;authority&quot;, yet they can't force airlines to sack valuable staff. So I expect that a technical pretext will be found for not requiring the airline pilots to carry the cards after all, and the department will go after another softer target first.&lt;br /&gt;&lt;br /&gt;It is beyond me why the Government keeps on trying to introduce this scheme. The Tories and LibDems have both pledged to scrap the whole thing as soon as Labour is voted out of office, which only gives them a couple more years at most to push it through. Sadly, the stubborn and unimaginative lot currently in power are likely to waste hundreds of millions of pounds of our money on this folly before it is finally sunk.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-8979223594732050242?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-8979223594732050242</guid>
         <pubDate>Mon, 16 Feb 2009 15:46:00 -0800</pubDate>
      </item>
      <item>
         <title>How To: Gitify Maven</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/outczSM4UAQ/how-to-gitify-maven.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/outczSM4UAQ&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8246849687665618345</guid>
         <pubDate>Sun, 15 Feb 2009 16:58:00 -0800</pubDate>
      </item>
      <item>
         <title>How To: Use Google Code as a Maven Repository</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/Aa2RrtWo5Ds/how-to-use-google-code-as-maven.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/Aa2RrtWo5Ds&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-5844464708922044371</guid>
         <pubDate>Sun, 15 Feb 2009 16:52:00 -0800</pubDate>
      </item>
      <item>
         <title>How To: Demo Flex Apps On Blogger or Google Sites</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/5N2Wk2y0FM4/how-to-demo-flex-apps-on-blogger-or.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/5N2Wk2y0FM4&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-3925594380627921828</guid>
         <pubDate>Sun, 15 Feb 2009 16:38:00 -0800</pubDate>
      </item>
      <item>
         <title>Darren on Flex: Flexins Project Launch</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/Z2YNvq5rwys/darren-on-flex-flexins-project-launch.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/Z2YNvq5rwys&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8963858371997746762</guid>
         <pubDate>Sun, 15 Feb 2009 16:35:00 -0800</pubDate>
      </item>
      <item>
         <title>Darren on Flex: Does Flex Have Serial Version Ids?</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/NI1NvC0_Vac/darren-on-flex-does-flex-have-serial.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/NI1NvC0_Vac&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8851794556685362338</guid>
         <pubDate>Thu, 12 Feb 2009 17:18:00 -0800</pubDate>
         <media:thumbnail width="72" url="http://4.bp.blogspot.com/_Q_F_ea5EKi0/SZTNwSJQaKI/AAAAAAAAAEE/MDQuV6cOfXI/s72-c/flex-serial-version-id.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Predictably Irrational: the international financial crisis</title>
         <link>http://aspsp.blogspot.com/2009/01/predictably-irrational-international.html</link>
         <description>My eternal gratitude to Dan Ariely and his &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.predictablyirrational.com/&quot;&gt;Predictably/Irrational blog&lt;/a&gt; for pointing out the existence of a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.thisamericanlife.org/Radio_Episode.aspx?episode=355&quot;&gt;radio programme&lt;/a&gt; and its &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.thisamericanlife.org/extras/radio/355_transcript.pdf&quot;&gt;transcript in PDF&lt;/a&gt;, which for the first time properly explained to me why we're in such a mess. I wonder what collective idiocy is next up.&lt;br /&gt;&lt;br /&gt;It also provides a sobering reminder that it's usually a bad idea to throw money at a problem. In this particular instance, Gordon Brown's fantastic idea to &quot;save the world&quot; by hosing all our cash and then some into the banks' pool of money supply was such a bad idea that it must stand as one of the most monumentally stupid decisions of all time. Read the transcript yourself to find out why.&lt;br /&gt;&lt;br /&gt;Anyone without the requisite quarter of an hour to hand can refer to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.duffbert.com/duffbert/blog.nsf/d6plinks/TDUF-6FGKJ5&quot;&gt;this&lt;/a&gt; very much more succinct, but necessarily less thorough, tale. It seems prescient, having been posted in 2005!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-7116574573300680206?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-7116574573300680206</guid>
         <pubDate>Mon, 26 Jan 2009 08:34:00 -0800</pubDate>
      </item>
      <item>
         <title>How to write conference session proposals</title>
         <link>http://aspsp.blogspot.com/2009/01/how-to-write-conference-session.html</link>
         <description>Most of you probably already know how to do this - after all, you get your papers accepted at conferences all over the world all the time, right?&lt;br /&gt;&lt;br /&gt;If (like me) you find your brilliant ideas trampled underfoot as often as not, read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://plg.uwaterloo.ca/~migod/research/beckOOPSLA.html&quot;&gt;Kent Beck's advice&lt;/a&gt;. It may have been written over 15 years ago, but I'm certain it applies equally well today. It's also charmingly self-referential.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-3230555523614508525?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-3230555523614508525</guid>
         <pubDate>Fri, 23 Jan 2009 09:15:00 -0800</pubDate>
      </item>
      <item>
         <title>The Inventor of the Wind-Up Radio</title>
         <link>http://change-challenge.blogspot.com/2009/01/inventor-of-wind-up-radio.html</link>
         <description>It is quite a good read about inventing, inventors and a couple of other relevant topics: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.bcs.org/server.php?show=ConWebDoc.23703&quot;&gt;Trevor Baylis OBE&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-1178403021896418231?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-1178403021896418231</guid>
         <pubDate>Tue, 20 Jan 2009 11:01:00 -0800</pubDate>
      </item>
      <item>
         <title>Don't Shout At Your Computer!</title>
         <link>http://change-challenge.blogspot.com/2009/01/dont-shout-at-your.html</link>
         <description>An engineer shows what happens to harddrive performance if the harddrive is subjected to vibration, in this case, loud noises emanating from his shouting near them. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.theregister.co.uk/2009/01/05/shouty_sun_engineer/print.html&quot;&gt;ARGHHHHHHHH!&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4115091529740912531?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4115091529740912531</guid>
         <pubDate>Sat, 17 Jan 2009 11:54:00 -0800</pubDate>
      </item>
      <item>
         <title>Another wiki going places...</title>
         <link>http://change-challenge.blogspot.com/2009/01/another-wiki-going-places.html</link>
         <description>While doing some research for a last minute Sri Lanka holiday, I found this wiki that I was previously unfamiliar with. Content is good, growing fast, recent and accurate (for Sri Lanka at this time). If you want to avoid using a tour operator for your trip, you could do worse...&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wikitravel.org/&quot;&gt;wikitravel&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4350270910663752488?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4350270910663752488</guid>
         <pubDate>Thu, 15 Jan 2009 03:22:00 -0800</pubDate>
      </item>
      <item>
         <title>SANS Institute Publishes Experts-Agreed List of Top 25 Coding Errors</title>
         <link>http://change-challenge.blogspot.com/2009/01/sans-institute-publishes-experts-agreed.html</link>
         <description>Some top people in the software industry, as well as critical organisations, have come together and agreed on a list of top 25 programming errors, and provided discussions and ratings on each. The information is well presented and easy to read: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sans.org/top25errors/&quot;&gt;Top 25 Programming Errors&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-7551181340774457916?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-7551181340774457916</guid>
         <pubDate>Thu, 15 Jan 2009 03:07:00 -0800</pubDate>
      </item>
      <item>
         <title>Mock external components using AOP</title>
         <link>http://aspsp.blogspot.com/2009/01/mock-external-components-using-aop.html</link>
         <description>Mark Nadelson has provided a well-written &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://java.sys-con.com/node/767418&quot;&gt;tutorial&lt;/a&gt; for a novel (to me, at any rate) use of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Aspect-oriented_programming&quot;&gt;Aspect-Oriented Programming&lt;/a&gt; in Java. Read the &quot;print&quot; version to get the whole article in one lump without the commercials.&lt;br /&gt;&lt;br /&gt;When you write &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://junit.org/&quot;&gt;jUnit&lt;/a&gt; tests, you often encounter a need to create mock objects (e.g. using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.jmock.org/&quot;&gt;JMock&lt;/a&gt; or &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.easymock.org/&quot;&gt;EasyMock&lt;/a&gt;) that can simulate some external dependency of the software under test. Mark has extended this idea to any external component that has an interface. In order to determine whether the software under test uses a mock component or the real one, he uses dynamic aspect-weaving by means of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://static.springframework.org/spring/docs/2.5.x/reference/aop.html&quot;&gt;Spring AOP&lt;/a&gt; with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-ataspectj&quot;&gt;AspectJ annotations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've got to have a play with this approach to see whether it can be used flexibly enough to support &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD&lt;/a&gt; fully. One problem I could foresee is that the pointcut specification is not in the test script but in the mock object (i.e. the class that implements the aspect). So it might be less than straightforward to link the mock object to specific test cases/steps. By contrast, when you use JMock in a jUnit test, you specify both the mock object and its expectations in one place.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-8533860011481975419?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-8533860011481975419</guid>
         <pubDate>Tue, 06 Jan 2009 10:11:00 -0800</pubDate>
      </item>
      <item>
         <title>XPath made simple</title>
         <link>http://aspsp.blogspot.com/2009/01/xpath-made-simple.html</link>
         <description>I know I'm a bit behind the curve on this one, but I've only just stumbled across a really useful tool:&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpath.alephzarro.com/&quot;&gt;XPather&lt;/a&gt; can&lt;br /&gt;&lt;ul&gt;&lt;li&gt;generate &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3.org/TR/xpath20/&quot;&gt;XPaths&lt;/a&gt; while browsing or inspecting HTML/XML/*ML documents&lt;/li&gt;&lt;li&gt;evaluate your XPaths and inspect the results&lt;/li&gt;&lt;li&gt;extract the content of *ML documents&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The latest version 1.4.1 was released on June 18 2008 (Firefox 3.0 compatible).&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpath.alephzarro.com/&quot;&gt;XPather&lt;/a&gt; is a simple &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mozilla.com/firefox/&quot;&gt;Firefox&lt;/a&gt; extension that integrates both with the browser and its &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://addons.mozilla.org/firefox/addon/6622&quot;&gt;DOMInspector&lt;/a&gt;. It is designed to be lightweight and cross-platform. It is valuable mainly as a web/XML-app development and debugging tool. In combination with the DOMInspector, which I can also highly recommend, it is particularly useful for developing &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://webtest.canoo.com/&quot;&gt;WebTest&lt;/a&gt; scripts: right-click in any element of a page that you want your script to compare or set, and the option &quot;Show in XPather&quot; pops up a new window with the precise XPath to select that element.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-5933741983634669762?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-5933741983634669762</guid>
         <pubDate>Mon, 05 Jan 2009 06:34:00 -0800</pubDate>
      </item>
      <item>
         <title>Is a Square a Rectangle?</title>
         <link>http://21ccw.blogspot.com/2009/01/is-square-rectangle.html</link>
         <description>I pre-ordered the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://clojure.org/&quot;&gt;Clojure&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pragprog.com/titles/shcloj/programming-clojure&quot;&gt;book&lt;/a&gt; today, so I downloaded Clojure and had a peek at something that I know is interesting - &quot;multimethods&quot;. I came across the following example statement:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:'courier new';&quot;&gt;(derive ::square ::rect)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;i.e. a Square IS-A Rectangle in the Object-Oriented sense.&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;This rang a bell for me. Not a nice melodious one, but one that's a little off-key. A good teacher asked some colleagues and me the question &quot;Is a Square a Rectangle?&quot; a few years ago, and the answer wasn't all that clear ti us. But he showed us a realitively easy way to determine to some extent the validity of any IS-A relationship.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will try and show you this principle by way of actually designing this hierarchy. First we design a simple Rectangle in Ruby:&lt;/div&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;class RectangleTest &amp;lt; Test::Unit::TestCase&lt;br /&gt; def test_width_height&lt;br /&gt;&lt;br /&gt; # Given&lt;br /&gt; r = Rectangle.new(1,1)&lt;br /&gt;&lt;br /&gt; # Then&lt;br /&gt; assert_equal 1, r.width&lt;br /&gt; assert_equal 1, r.height&lt;br /&gt;&lt;br /&gt; # When&lt;br /&gt; r.width = 5&lt;br /&gt;&lt;br /&gt; # Then&lt;br /&gt; assert_equal 5, r.width&lt;br /&gt; assert_equal 1, r.height&lt;br /&gt;&lt;br /&gt; # When&lt;br /&gt; r.height = 2&lt;br /&gt; &lt;br /&gt; # Then&lt;br /&gt; assert_equal 5, r.width&lt;br /&gt; assert_equal 2, r.height&lt;br /&gt;&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;If you think it's strange that I use a test as a design, I suggest you read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;this&lt;/a&gt;. I'm not even going to show the implementation since it's so simple. Next we will design our Square class:&lt;/div&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;class SquareTest &amp;lt; Test::Unit::TestCase&lt;br /&gt; def test_width_height&lt;br /&gt;&lt;br /&gt; # Given&lt;br /&gt; s = Square.new(3)&lt;br /&gt;&lt;br /&gt; # Then&lt;br /&gt; assert_equal 3, s.width&lt;br /&gt; assert_equal 3, s.height&lt;br /&gt;&lt;br /&gt; # When&lt;br /&gt; s.width = 5&lt;br /&gt;&lt;br /&gt; # Then&lt;br /&gt; assert_equal 5, s.width&lt;br /&gt; assert_equal 5, s.height&lt;br /&gt;&lt;br /&gt; # When&lt;br /&gt; s.height = 2&lt;br /&gt; &lt;br /&gt; # Then&lt;br /&gt; assert_equal 2, s.width&lt;br /&gt; assert_equal 2, s.height&lt;br /&gt;&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;And you can see that we make sure that when either the width or height has been set, we get the same value for both the width and height respectively. The same goes for the single-parameter constructor. Again, the implementation is trivial. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, you might think that this design is &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;OK&lt;/span&gt;, but it's not. We have to ensure that our inheritance doesn't break the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov Substritution Principle.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From Wikipedia:&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;Liskov's notion of 'subtype' is based on the notion of substitutability; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g., correctness).&quot;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;This means that for our designs, the unit test for the Rectangle should pass when I substitute the Rectangle instance with a Square instance. Will it? No it won't. Because in the rectangle test, we ensure that when the width is set, the height is not affected, and vice versa. Using a Square instance here will break the test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another way of looking at it is to think of the contract of the setters, and the pre and post conditions of those contracts. According to the Liskov princple, (again, from Wikipedia):&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;Preconditions cannot be strengthened in a subclass.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;Postconditions cannot be weakened in a subclass.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;If we design the Square to force the width to be set when setting the height (and vice versa), we are &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;weakening&lt;/span&gt; the postconditions of the Rectangle methods. I.e. the post condition that states that either the width or height should &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;not&lt;/span&gt; be altered when setting the height or width respectively has been weakened.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In conclusion, here we have a Square that is NOT a Rectangle. The lesson to be learnt is that (unfortunately for us), IS-A in the real world or other domains does not necessarily imply IS-A in the OO world! &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;P.S. If you remove the setters from the Rectangle, and only allow the fields to be set during construction, there is no violation of the Liskov Substitution Principle :)&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-7203639609804814726?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-7203639609804814726</guid>
         <pubDate>Thu, 01 Jan 2009 19:31:00 -0800</pubDate>
      </item>
      <item>
         <title>WikiLeaks - Oops!</title>
         <link>http://change-challenge.blogspot.com/2008/12/wikileaks-oops.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wikileaks.org/wiki/Wikileaks&quot;&gt;Wikileaks&lt;/a&gt; is a very interesting little web site that came to my attention because of some sensitive documents that were leaked in/by South African affairs recently. Some very interesting cartoons, names and documents, from some the most ?unlikely? people and countries I would not have guessed at.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-8926194282308707392?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-8926194282308707392</guid>
         <pubDate>Fri, 26 Dec 2008 17:29:00 -0800</pubDate>
      </item>
      <item>
         <title>Disk Defragmentation Tool</title>
         <link>http://change-challenge.blogspot.com/2008/12/disk-defragmentation-tool.html</link>
         <description>Thank you &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaksa.wordpress.com/&quot;&gt;Jaksa&lt;/a&gt; (my colleague) for this invaluable tip for a great Disk Defragmentation Tool! I've been a believer in defragmenting my hard disk drive on an annual or bi-annual basis (or major file system upheaval event) for many years. &lt;br /&gt;&lt;br /&gt;The problem I started experiencing over the past 5 odd years, is that as my hard drives became bigger, &quot;defragging&quot; took longer and longer. Worse, the tool provided with Windows only works properly when 30% of the hard drive is available! Now 30% of 120MB is only 36MB and is not such a bad temporary sacrifice. 30% of 100GB is a huge sacrifice that I just cannot afford! Not on my development workstation, nor on my personal home machine(s)!!&lt;br /&gt;&lt;br /&gt;Jaksa pointed in in the direction of independent evaluations listed on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://donnedwards.openaccess.co.za/2007/04/great-defrag-shootout-part-1.html&quot;&gt;Donn Edwards' web site&lt;/a&gt;. Or you can simply &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kessels.com/JkDefrag/&quot;&gt;download the winning defragmentation tool (JkDefrag) here&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-8523297358462940124?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-8523297358462940124</guid>
         <pubDate>Wed, 17 Dec 2008 08:17:00 -0800</pubDate>
      </item>
      <item>
         <title>Return of the Thick Client?</title>
         <link>http://aspsp.blogspot.com/2008/12/return-of-thick-client.html</link>
         <description>Web 2.0 is taking all sorts of unexpected directions. The latest to come to my attention are two initiatives aimed at offloading processor load from server to client.&lt;br /&gt;&lt;br /&gt;First up, Google announced a new developer project named &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://google-code-updates.blogspot.com/2008/12/native-client-technology-for-running.html&quot;&gt;Native Client&lt;/a&gt;. With Native Client, Google aims to &quot;give web developers access to the full power of the client's CPU while maintaining the browser neutrality, OS portability and safety that people expect from web applications.&quot; As far as I can see, it's what Java Applets were originally designed to do - and look how successful they've been. At least outside the enterprise environment (where desktop configurations tend to be strictly controlled), applets suffered from the &quot;write once, debug everywhere&quot; syndrome and have largely fallen out of use. It'll be interesting to see whether an Internet-savvy company like Google makes a success of this new approach.&lt;br /&gt;&lt;br /&gt;Next, a start-up named &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.thinkgos.com/&quot;&gt;Good OS&lt;/a&gt; has announced &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.thinkgos.com/cloud.php&quot;&gt;Cloud&lt;/a&gt;, &quot;a browser operating system&quot;. I am trying hard to get my head around that concept. They claim that it's an environment for enhancing the user's Internet experience and that it can be co-hosted on Windows, Linux or other operating systems. If I have read the scant information available correctly, the idea is that your machine will start up already logged on to your favourite portal (Yahoo, Google, Windows Live...) and that core applications such as Skype, which are accessed from a MacOS-like object dock, run within their own dedicated browser tab on top of Cloud's integrated compressed Linux kernel. Whenever you need to, you can switch to the native OS with a single key press.&lt;br /&gt;&lt;br /&gt;Unfortunately the &quot;Why Cloud?&quot; page on Good OS's web site is unfinished, so it is difficult to comprehend the vision behind the product. A clue might be that it is being bundled with the Gigabyte touch-screen &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gigabyte.com.tw/News/Notebook/News_List.aspx?NewsID=1398&quot;&gt;Netbook&lt;/a&gt; models and so looks like a lower-cost alternative to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;. Perhaps the company is aiming for an &quot;Internet Appliance&quot; niche. It made a name for itself by supplying the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.techcrunch.com/2007/11/04/gos-where-computers-are-headed/&quot;&gt;gOS Linux&lt;/a&gt; operating system for the ultra-low-cost &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.walmart.com/catalog/product.do?product_id=7754614&quot;&gt;Wal-Mart PCs&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-5547767157413916492?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-5547767157413916492</guid>
         <pubDate>Tue, 16 Dec 2008 01:22:00 -0800</pubDate>
      </item>
      <item>
         <title>Testing web applications? Cucumber is the cool new kid on the block</title>
         <link>http://aspsp.blogspot.com/2008/12/testing-web-applications-cucumber-is.html</link>
         <description>I've had quite complimentary things to say about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://webtest.canoo.com/&quot;&gt;Canoo WebTest&lt;/a&gt;, but one thing it doesn't provide out of the box is a representation of the tests that your average customer is able to read and understand intuitively - that is to say, a tabular format like &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://fit.c2.com/&quot;&gt;Fit&lt;/a&gt; or a narrative of the &quot;Given... when... then... &quot; form.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rubyinside.com/cucumber-the-latest-in-ruby-testing-1342.html&quot;&gt;Cucumber&lt;/a&gt; to the rescue! I heard several people mention this at the recent &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xpday.org/&quot;&gt;XP Day&lt;/a&gt; in London. I hope to investigate it in more depth soon.&lt;br /&gt;&lt;br /&gt;I would be interested to know whether it can be used to test anything other than &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ruby-lang.org/&quot;&gt;Ruby&lt;/a&gt; code and whether it can drive a web browser to interact with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Rich_Internet_Application&quot;&gt;Rich Internet Applications&lt;/a&gt; (RIAs). Stuart Ervine's and Nat Pryce's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/webtoolkit/overview.html&quot;&gt;GWT&lt;/a&gt; development demo at XP Day was truly impressive. Nat has combined &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/webdriver/&quot;&gt;WebDriver&lt;/a&gt; with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/windowlicker/&quot;&gt;WindowLicker&lt;/a&gt; to create a clean interface between a test script and synchronous or asynchronous RIAs. But telling a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://junit.sourceforge.net/&quot;&gt;jUnit&lt;/a&gt; test to move the mouse cursor into a particular widget and click the button was nothing if not verbose!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-6527401154696334594?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-6527401154696334594</guid>
         <pubDate>Mon, 15 Dec 2008 09:21:00 -0800</pubDate>
      </item>
      <item>
         <title>Sending SMS texts from the PC desktop</title>
         <link>http://aspsp.blogspot.com/2008/12/sending-sms-texts-from-pc-desktop.html</link>
         <description>Ever left your mobile at home and needed to send a text to someone? And even to receive that person's reply without access to your phone? Or just found that ten-finger typing is quicker than predictive TXTing with two thumbs?&lt;br /&gt;&lt;br /&gt;I've discovered &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://online.vodafone.co.uk/dispatch/Portal/appmanager/vodafone/wrp?_nfpb=true&amp;amp;_pageLabel=template10&amp;amp;pageID=BS_0011&quot;&gt;Vodafone Text Centre&lt;/a&gt; does the job (see feature summary in the attached message). You can install it for free, but note that the cost of SMS messages you send using Text Centre goes on to your normal Vodafone mobile account.&lt;br /&gt;&lt;br /&gt;There's a very comprehensive manual and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.vodafone.co.uk/textcentre&quot;&gt;online help&lt;/a&gt;. Make sure your Outlook isn't running before you start installing (use Task Manager to kill it if necessary).&lt;br /&gt;&lt;br /&gt;In a test here in the office, I found that my first outgoing message was delivered in just a few seconds, whereas the reply took around 10 minutes to reach my Outlook inbox (you can choose to have the reply routed to your mobile instead, of course, which is quicker but means that you don't have access to Outlook's convenience features when forwarding or filing the reply).&lt;br /&gt;&lt;br /&gt;If you're in the habit of leaving Outlook running when you leave the office, you can also get Text Centre to alert you by SMS when you receive an e-mail (or only for high-priority e-mails) or to send you an SMS alert of upcoming appointments.&lt;br /&gt;&lt;br /&gt;Overall, I am impressed. With Vodafone Text Centre you can:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Send text messages to individuals and groups from your PC, using your existing contacts and distribution lists.&lt;/li&gt;&lt;li&gt;Choose to have replies sent to your mobile phone or to your e-mail inbox.&lt;/li&gt;&lt;li&gt;Receive appointment reminders via text messages.&lt;/li&gt;&lt;li&gt;Choose to receive text messages to notify you of urgent e-mails.&lt;/li&gt;&lt;/ul&gt; Vodafone says that Text Centre will be upgraded on a regular basis, so suggests that you visit the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://online.vodafone.co.uk/dispatch/Portal/appmanager/vodafone/wrp?_nfpb=true&amp;amp;_pageLabel=template10&amp;amp;pageID=BS_0011&quot;&gt;website&lt;/a&gt; from time to time to ensure you have the most up-to-date version of the software.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-231689980296925246?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-231689980296925246</guid>
         <pubDate>Thu, 04 Dec 2008 10:09:00 -0800</pubDate>
      </item>
      <item>
         <title>Webapp stacks comparison update 1</title>
         <link>http://jaksa.wordpress.com/2008/12/01/webapp-stacks-comparison-update-1/</link>
         <description>We have received measurements from one of the remaining level 3 applications. It&amp;#8217;s Immo&amp;#8217;s implementation based on Ruby + Ramaze + MySQL. Here are the updated results: As soon as we confirm the measurements and get the numbers for the ASP implementation we will publish the updated point chart. &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=73&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=73</guid>
         <pubDate>Mon, 01 Dec 2008 03:26:03 -0800</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>We have received measurements from one of the remaining level 3 applications. It&#8217;s <a rel="nofollow" target="_blank" href="http://aspsp.blogspot.com/">Immo</a>&#8217;s implementation based on <span lang="EN-GB"><a rel="nofollow" target="_blank" href="http://www.ruby-lang.org/en/">Ruby</a><span> </span>+<span> </span><a rel="nofollow" target="_blank" href="http://ramaze.net/">Ramaze</a><span> </span>+<span> </span><a rel="nofollow" target="_blank" href="http://www.mysql.com/">MySQL</a></span>. Here are the updated results:</p>
<p><a rel="nofollow" target="_blank" href="http://jaksa.files.wordpress.com/2008/12/performance1.png"><img class="alignnone size-full wp-image-74" title="performance1" src="http://jaksa.files.wordpress.com/2008/12/performance1.png?w=580&#038;h=334" alt="performance1" width="580" height="334"/></a></p>
<p>As soon as we confirm the measurements and get the numbers for the ASP implementation we will publish the updated point chart.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/73/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=73&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2008/12/performance1.png" medium="image">
            <media:title>performance1</media:title>
         </media:content>
         <category>Uncategorized</category>
      </item>
      <item>
         <title>Webapp stacks comparison</title>
         <link>http://jaksa.wordpress.com/2008/11/30/webapp-stacks/</link>
         <description>Ever wondered what is the best technology stack for building web applications? I&amp;#8217;m sure you have.
Last week my company went on a workshop, during which we tried to answer that question. I wrote a requirements specification for a simple web application. Everyone had to choose the technology stack they&amp;#8217;re most familiar with and implement the [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=46&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=46</guid>
         <pubDate>Sun, 30 Nov 2008 06:34:27 -0800</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>Ever wondered what is the best technology stack for building web applications? I&#8217;m sure you have.</p>
<p>Last week my company went on a workshop, during which we tried to answer that question. I wrote a requirements specification for a simple web application. Everyone had to choose the technology stack they&#8217;re most familiar with and implement the application. Everyone received a benchmark script for the application and at the end of the day we compared the performance results. The application was just enough complex to require at least a day to implement. In the end we multiplied the performance by the level of functionality implemented.</p>
<p><strong>The Application</strong></p>
<p>The webapp I chose is the same one for the <a rel="nofollow" target="_blank" href="http://code.google.com/p/cloudspeed/">couldspeed project</a>. It is based on the model of social networking applicatins. <span>Once registered and logged in, users can add other users as </span><span>friends and submit posts. <span>The homepage will display the 20 most recent posts from all </span><span>user’s friends including the user himself.</span></span></p>
<p><span><span>There are 2 entities each with 2 attributes:</span></span></p>
<ul>
<li>users(email, password)</li>
<li>post(date, content)</li>
</ul>
<p><span><span>and there are 2 relationships</span></span></p>
<ul>
<li>users are friends with other users (n to n)</li>
<li>each post is written by a user (1 to n)</li>
</ul>
<p>there are 2 web pages: login and home.</p>
<p>From the login page, users can register themselves or log in.</p>
<p>The home page displays the number of friends, the 20 most recent posts (for each post, the date, author and content) and allows users to add posts, friends or logout.</p>
<p>Information has to be persisted somehow.</p>
<p><strong>The Benchmark</strong></p>
<p>Each developer got a copy of <a rel="nofollow" target="_blank" href="http://mirror.public-internet.co.uk/ftp/apache/jakarta/jmeter/binaries/jakarta-jmeter-2.3.2.zip">JMeter</a> and 3 scripts. The 3 scripts excercized 3 different levels of functionality:</p>
<ol>
<li>Register Users &#8211; registered a number of users (100)</li>
<li>Make Friends &#8211; created around 10 friends per user</li>
<li>Post Stuff &#8211; posted messages</li>
</ol>
<p>For the first level of functionality, the developer had to implement the functionality behind the Register button. Registered users had to be persisted. This level had a multiplier of 1.</p>
<p>For the second level of functionality, developers had to implement logging in, keeping session information, and the friendship relationship. The homepage should have shown the number of friends. This level had a multiplier of 3.</p>
<p>For the third level of functionality, developers had to implement everything: posting messages and showing the messages from all friends. Since this functionality included a complex query that ate a lot of processing power, the multiplier was 50.</p>
<p><strong>The Contenders</strong></p>
<p><a rel="nofollow" target="_blank" href="http://21ccw.blogspot.com/">Ben</a>: <a rel="nofollow" target="_blank" href="http://www.erlang.org/">Erlang</a> + <a rel="nofollow" target="_blank" href="http://incubator.apache.org/couchdb/">CouchDB</a></p>
<p>Team 2: Java + <a rel="nofollow" target="_blank" href="http://www.springframework.org/">Spring</a> + <a rel="nofollow" target="_blank" href="http://www.hibernate.org/">Hibernate</a> + <a rel="nofollow" target="_blank" href="http://www.postgresql.org/">Postgres</a></p>
<p>Team 3: Java + <a rel="nofollow" target="_blank" href="http://www.springframework.org/">Spring</a> + <a rel="nofollow" target="_blank" href="http://www.hibernate.org/">Hibernate</a></p>
<p>Team 4: <a rel="nofollow" target="_blank" href="http://www.rubyonrails.org/">Ruby On Rails</a> + <a rel="nofollow" target="_blank" href="http://www.mysql.com/">MySQL</a></p>
<p>Team 5: <a rel="nofollow" target="_blank" href="http://www.asp.net/">ASP</a> with <a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/vbasic/default.aspx">Visual Basic</a> + <a rel="nofollow" target="_blank" href="http://www.microsoft.com/sqlserver/2008/en/us/default.aspx">SQLServer</a></p>
<p><a rel="nofollow" target="_blank" href="http://aspsp.blogspot.com/">Immo</a>: <a rel="nofollow" target="_blank" href="http://www.ruby-lang.org/en/">Ruby</a> + <a rel="nofollow" target="_blank" href="http://ramaze.net/">Ramaze</a> + <a rel="nofollow" target="_blank" href="http://www.mysql.com/">MySQL</a></p>
<p><strong>The Results</strong></p>
<p><img class="alignnone size-full wp-image-54" title="performance" src="http://jaksa.files.wordpress.com/2008/11/performance.png?w=588&#038;h=342" alt="performance" width="588" height="342"/></p>
<p>Only three of the contenders implemented level 3 of functionality, but we were able to measure the performance only for the erlang implementation. The other 2 that made it to the 3rd level were ASP+SQLServer and Ramaze. We will soon publish the results of the two missing level 3 implementations. </p>
<p><img class="alignnone size-full wp-image-55" title="total-points" src="http://jaksa.files.wordpress.com/2008/11/total-points.png?w=588&#038;h=342" alt="total-points" width="588" height="342"/></p>
<p>The winner was Ben with 1111.1 points. Erlang + CouchDB proved to be quite fast and productive in the right hands.</p>
<p><strong>Conclusions</strong></p>
<p>Allthough just one day of development is not nearly enough to measure productivity, we noticed that choosing a particular language that promised a high level of productivity wasn&#8217;t as important as choosing the language you&#8217;re most familiar with.</p>
<p>Alltough Level 1 of functionality does not provide a meaningful scenario to measure performance, we can see that most of the implementations had the same performance, including Ruby, which has been measured to be <a rel="nofollow" target="_blank" href="http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&amp;lang=all">100 times slower</a> than C++, but in our scenario it actually showed the best performance.</p>
<p>Allthough we must point out that both ruby implementations and the ASP implementation showed instability. Errors ranging from 15% to 30% were reported during the benchmarks.</p>
<p>As a comparison, I have done some java implementations before the competition. They all provide level 3 functionality. They all use Servlets in the web tier, but the DAO tier changes: we have JDBC with MySQL, EJB3 with MySQL and pure in memory.</p>
<p>Compared to the Erlang implementation wich serves 15 req/s I have similar results for the JDBC (15 req/s). A &#8220;heavyweigth&#8221; stack such as EJBs actually manages to produce 38 req/s, but by far the fastest solution is keeping everything in memory that brings us to an impressive 2000 req/s. Obviously the in memory solution cannot be compared to the others because it doesn&#8217;t satisfy the persistence requirement. But can still be used as a comparison to see how much performance do we loose on the persistence layer.</p>
<p><strong>Future Work</strong></p>
<p>We have had requests from other people that were not taking part of the competition to submit their implementations. Since we have no way to measure productivity, all submissions now require level 3 of functionality. All implementations will be published on the <a rel="nofollow" target="_blank" href="http://code.google.com/p/cloudspeed/">cloudspeed website</a>. If you wish to contribute by improving an implementation or submitting your own just send me an email or leave a comment here.</p>
<p>Currently the benchmark is adapted to quickly give a very aproximative measure. 100 users is not a realistic number even for a small website. Our next goal is to create a benchmark that will register up to millions of users, have an average of 100 friends per user and post several million messages.</p>
<p>The final goal is to port these implementations to the cloud and measure their scalability. We don&#8217;t only want to see the performance on a single machine, but also how will the performance be when we reach the limits of a single server. Ideally we want to try to run these applications on clusters as big as we can get.</p>
<p>Stay tuned for updates&#8230;</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/46/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/46/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/46/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/46/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/46/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=46&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2008/11/performance.png" medium="image">
            <media:title>performance</media:title>
         </media:content>
         <media:content url="http://jaksa.files.wordpress.com/2008/11/total-points.png" medium="image">
            <media:title>total-points</media:title>
         </media:content>
      </item>
      <item>
         <title>Munging PDF files and pages</title>
         <link>http://aspsp.blogspot.com/2008/11/munging-pdf-files-and-pages.html</link>
         <description>Having scanned over a dozen handwritten pages from my notebook into a PDF file, I had to invert every other page to make it possible to read the whole thing. It took me a while to find the answer, but YOU can go straight to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pdfhacks.com/pdftk/&quot;&gt;the solution&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;The command line is&lt;pre&gt;&lt;br /&gt;pdftk.exe scannedfile.pdf cat 1 2S 3 4S 5 6S 7 8S 9 10S 11 12S output readablefile.pdf&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5605173550883974775-7777758610586214974?l=aspsp.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Immo Hüneke</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5605173550883974775.post-7777758610586214974</guid>
         <pubDate>Wed, 19 Nov 2008 09:17:00 -0800</pubDate>
      </item>
      <item>
         <title>Brain Rules</title>
         <link>http://change-challenge.blogspot.com/2008/11/brain-rules.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.brainrules.net/&quot;&gt;Brain Rules&lt;/a&gt; is quite a fun little web site that gives one possibly plausible explanation for how the human brain evolved over time and how it works for humans today. A collection of short entertaining videos and some writings.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-1974337012020878250?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-1974337012020878250</guid>
         <pubDate>Tue, 18 Nov 2008 10:30:00 -0800</pubDate>
      </item>
      <item>
         <title>Does Robert Mugabe use Powerpoint?</title>
         <link>http://21ccw.blogspot.com/2008/11/does-robert-mugabe-use-powerpoint.html</link>
         <description>I think most people will agree that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Robert_Mugabe&quot;&gt;Robert Mugabe&lt;/a&gt; is a terrible dictator who has scant disregard for the people he is supposed to be serving. The same goes for the likes of Stalin, Hitler, Idi Amin etc. That being said, I think most people will also agree that one of the reasons of their rise to power was specifically their ability to influence people. In other words&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;People listen[ed] to them, and they're not using Powerpoint&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My experience is that every time someone want to &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;say something&lt;/span&gt; to more than one person, there has to be a Powerpoint presentation to go along with it. And more often than not, this attempt at communication fails miserably, or succeeds only in some rudimentary fashion. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some of the causes of these failures are:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;People are reading the slides, so they're not listening to the speaker.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The presenter is reading the slides, so there is no connection with the audience.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The bullet-pointed slides are so mind-numbingly &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;boring&lt;/span&gt; that the audience members have gone to their happy place or are thinking of what to cook/order/kill for dinner and of course, they're &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;not listening.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;In contrast, I'll mention two very successful entrepeneurs and their presentation styles: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Steve_Jobs&quot;&gt;Steve Jobs&lt;/a&gt; (Apple, Pixar, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.nytimes.com/2008/11/12/opinion/12friedman.html?_r=1&amp;amp;partner=permalink&amp;amp;exprod=permalink&amp;amp;oref=slogin&quot;&gt;General Motors?&lt;/a&gt;) and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Elon_Musk&quot;&gt;Elon Musk&lt;/a&gt; (PayPal, Tesla Motors, SpaceX). In business it is absolutely essential that you can effectively communicate your ideas to people. And when you audience is holding the purse strings, and you can't convince them of your business ideas, you're doomed to become a (perhaps very successful) hobbyist.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I went to a talk by Elon Musk on his company &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.spacex.com/&quot;&gt;SpaceX&lt;/a&gt; a few months ago. The projector had been set up and the presentation was ready to proceed. The first slide was already on the screen, with text along the lines of &quot;Elon Musk, SpaceX&quot; with very nice picture of a rocket (on a Pacific island if I remember correctly). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Elon Musk came in and talked a bit. After a few minutes he proceeded to questions, and these went on for more than an hour. The first slide was the &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;only&lt;/span&gt; slide. Maybe the host created it when he realised there were no slides. &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;Are you crazy? &lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;No slides?! But how will you&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;....&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The talk was very effective, he had communicated his points, and gave the audience exactly what they wanted, since they were asking him what they wanted to know!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second example is Steve Jobs. I remember watching the first iPhone Keynote speech and how I got swept up in the presentation. It was a highly effective communication (helped by a great product). Let's look at some of the slides he used:&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;http://1.bp.blogspot.com/_bXDgUoT7V7o/SRws-5svzNI/AAAAAAAAAIM/WwqN3676wwM/s400/dsc_0236.jpg&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:400px;height:265px;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5268135123268652242&quot;/&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://2.bp.blogspot.com/_bXDgUoT7V7o/SRwtIIPj6FI/AAAAAAAAAIU/2bn3R_0PMxo/s1600-h/dsc_0245.jpg&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:400px;height:265px;&quot; src=&quot;http://2.bp.blogspot.com/_bXDgUoT7V7o/SRwtIIPj6FI/AAAAAAAAAIU/2bn3R_0PMxo/s400/dsc_0245.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5268135281791592530&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;http://1.bp.blogspot.com/_bXDgUoT7V7o/SRwtNIvaHWI/AAAAAAAAAIc/uURI3AxDKOE/s400/dsc_0175.jpg&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:400px;height:265px;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5268135367824514402&quot;/&gt;&lt;br /&gt;Do you see lots of bullet points? The last slide has the most text on it, but that slide is in the minority, and the bullets are actually very short. The first two slides had simple images, and minimal text, and I can assure you that people were &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;listening&lt;/span&gt; to what he was saying!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Do you think the response would have been the same if his slides looked like this:&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://2.bp.blogspot.com/_bXDgUoT7V7o/SRwuDpzhL7I/AAAAAAAAAIk/aTBoI-Ic_Uc/s1600-h/boring.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:400px;height:282px;&quot; src=&quot;http://2.bp.blogspot.com/_bXDgUoT7V7o/SRwuDpzhL7I/AAAAAAAAAIk/aTBoI-Ic_Uc/s400/boring.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5268136304413061042&quot;/&gt;&lt;/a&gt;&lt;div&gt;instead? I'm asleep already.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My highly opinionated advice for presentations would be:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Don't use PowerPoint/Keynote/[insert slide software here] to write your presentation. Decide what you want to say and how you want it to flow and only prepare your slides once you know the content of your presentation. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Don't use your slides as notes, have seperate notes if you don't know the topic that well or need some backup information.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Don't read you slides.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Don't have lots of bullet points on each slide.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(255, 0, 0);&quot;&gt;You don't &lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(255, 0, 0);&quot;&gt;need&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color:rgb(255, 0, 0);&quot;&gt; to use slides.&lt;/span&gt; Sometimes a white board is good enough, and in most cases it is probably better.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;What do you think?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-8710392401372419187?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-8710392401372419187</guid>
         <pubDate>Tue, 11 Nov 2008 17:07:00 -0800</pubDate>
         <media:thumbnail width="72" url="http://1.bp.blogspot.com/_bXDgUoT7V7o/SRws-5svzNI/AAAAAAAAAIM/WwqN3676wwM/s72-c/dsc_0236.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Zuhlke – Corporate Networking Event</title>
         <link>http://darynholmes.wordpress.com/2008/10/22/zuhlke-corporate-networking-event/</link>
         <description>Zuhlke Engineering is hosting a corporate networking event at Canada Square on the 20th November. There will be an informative one hour presentation, followed by lunch and a networking session.
Here is a short snippet from the leaflet:
Zuhlke will share thier experience in successfully helping CIO’s and Programme / Project Managers in Top Tier Banks and [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=117&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=117</guid>
         <pubDate>Wed, 22 Oct 2008 08:53:18 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p><a rel="nofollow" target="_blank" href="http://www.zuehlke.com/en/know-how/nach-technologien/agile-software-entwicklung/">Zuhlke Engineering</a> is hosting a corporate networking event at Canada Square on the 20th November. There will be an informative one hour presentation, followed by lunch and a networking session.</p>
<p>Here is a short snippet from the leaflet:<br />
Zuhlke will share thier experience in successfully helping CIO’s and Programme / Project Managers in Top Tier Banks and other Corporates to:</p>
<ul>
<li>Get the business on your side by capturing requirements in their language but with the precision you need</li>
<li>Win the battle for budgets, ensuring the right level of project funding throughout</li>
<li>Get compliance and audit without the pain</li>
<li>Corner suppliers into delivering only high quality software</li>
</ul>
<p>The speakers at the event are:<br />
<strong>Prof. Dr. Wolfgang Emmerich </strong>(Chairman, Zuhlke UK)<br />
Wolfgang is a Partner in the Zuhlke Technology Group of Switzerland. He was also co-founder of Zuhlke Engineering GmbH, Germany in 1998 and Zuhlke Engineering Ltd, London in 2001, where he is currently Chairman and part-time Principal Consultant, primarily to the investment banking sector.</p>
<p><strong>Keith Braithwaite</strong> (Head of Zuhlke’s Centre for Agile Practice)<br />
Keith is a Principal Consultant and Business Unit Leader with Zuhlke in the UK. He has trained, coached and managed development teams from New York to Sydney working on systems ranging from mobile telephone applications to enterprise scale financial systems. He is a regular presenter at conferences around the world.</p>
<p>This is a free event and seats are limited. If you would like to attend this event then please contact me.</p>
<p>Regards, Daryn</p>
Posted in General, Presentations Tagged: Corporate Networking, Presentations, Zuhlke <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/117/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/117/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/117/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/117/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/117/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=117&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Tuning the EJB3 Implementation</title>
         <link>http://jaksa.wordpress.com/2008/10/09/tuning-the-ejb3-implementation/</link>
         <description>During my evaluation of highly scalable technologies I incurred in some performance problems with the EJB3 implementation. It seems to me that it is a quite common problem Yesterday I was getting very dissappointing results from the benchmarks of the EJB3 implementation of the sample application. I have discovered some nice hints for optimizing Hybernate and EJB3 [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=38&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=38</guid>
         <pubDate>Thu, 09 Oct 2008 08:53:45 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>During my <a rel="nofollow" target="_blank" href="http://code.google.com/p/cloudspeed/">evaluation</a> of highly scalable technologies I incurred in some performance problems with the EJB3 implementation. It seems to me that it is a quite common problem</p>
<p><span id="more-38"></span></p>
<p>Yesterday I was getting <a rel="nofollow" target="_blank" href="http://jaksa.wordpress.com/2008/10/08/measuring-the-speed-of-clouds/">very dissappointing results </a>from the benchmarks of the EJB3 implementation of the <a rel="nofollow" target="_blank" href="http://code.google.com/p/cloudspeed/wiki/ApplicationSpecification">sample application</a>. I have discovered some nice <a rel="nofollow" target="_blank" href="http://blogs.jboss.com/blog/acoliver/2006/01/23/Hibernate_EJB3_Tuning.txt">hints</a> for optimizing Hybernate and EJB3 applications and a very good <a rel="nofollow" target="_blank" href="http://www.infoq.com/presentations/ejb-3">video on EJB3</a>. This hepled me understand why my EJBs were not updated properly, but most of all why I was getting such poor performance.</p>
<p>The performance problem was due to the use of eager fetching on a many to many relationship. The relationship in question was friendship between users. This is a many to many relationship with itself. This means eager fetching is propagated transitively, so each time I loaded a user, all the friends were loaded as well, and also the friends of the friends and the friends of&#8230; basically the whole table.</p>
<p>By default many to many relationships use lazy fetching, but I changed this to eager when I wrote the application. The reason I had eager fetching on this relationship is that when I tried to get the number of friends a user had, my appserver was complaining that it couldn&#8217;t be done with lazy fetching. My error was in performing this through user.getFriends().size(). What I&#8217;m doing now instead is asking the database to give me the number of friends by using a query like &#8220;SELECT count(f) FROM user u JOIN u.friends f WHERE&#8230;&#8221;.</p>
<p>After that I changed some transaction attributes so that read only operations do not require transactions. Given the semantic of the methods I don&#8217;t require a strong level on consistency, so it&#8217;s relatively safe to do this. This minimizes delays due to contention and increases the paralellizability (try pronouncing this aloud) of the applications.</p>
<p>The result was that now my application runs 10 times faster. Now I&#8217;m getting 79 requests per second if I run the server on an EC2 instance and the client on my machine. This is just a little slower than the 100 requests per second obtained by the pojo in memoty solution, which means that EJB3 is pretty fast. I still have to test this without the communication bottleneck to be sure of the actual performance.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/38/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/38/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/38/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/38/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/38/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=38&subd=jaksa&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
      </item>
      <item>
         <title>Measuring the Speed of Clouds</title>
         <link>http://jaksa.wordpress.com/2008/10/08/measuring-the-speed-of-clouds/</link>
         <description>I have started a project for benchmarking highly scalable technologies. My plan is to use cloud computing platforms and implement the same application using different stacks of technologies. The aspect I want to evaluate is performance when the number of nodes grows a lot.
Application specification
The application I&amp;#8217;m using for benchmarking is a simplified model of [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&amp;blog=2662408&amp;post=36&amp;subd=jaksa&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://jaksa.wordpress.com/?p=36</guid>
         <pubDate>Wed, 08 Oct 2008 09:39:24 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>I have started a project for benchmarking highly scalable technologies. My plan is to use cloud computing platforms and implement the same application using different stacks of technologies. The aspect I want to evaluate is performance when the number of nodes grows a lot.<span id="more-36"></span></p>
<p><strong>Application specification</strong><br />
The application I&#8217;m using for benchmarking is a simplified model of Facebook.</p>
<p><strong>Implementations</strong><br />
Currently I have 2 implementations:<br />
Servlets + EJB3<br />
Servlets + in memory Java</p>
<p><strong>Benchmark</strong><br />
As benchmarking client I&#8217;m using JMeter.<br />
The benchmark looks like this: a number of threads will start iterating over the following sequence</p>
<ol>
<li>load first page (redirection)</li>
<li>load login page</li>
<li>login</li>
<li>load main page</li>
<li>add post</li>
<li>add friend</li>
<li>logout</li>
</ol>
<p>There are no pauses so in theory, this should test the capacity of the server.</p></div>
<p>Ideally there would be a very large number of threads (users) performing requests occasionally.</p>
<p><strong>Configurations tested</strong><br />
I have tested everything <strong>on my machine </strong>before deploying on EC2. I have used JBoss and MySql for the EJB solution.<br />
The performance I obtained was around 10 requests per second, which is dissapointing. Probably I have a bottleneck somewhere and need to configure things properly.<br />
The In Memory Java implementation achieves more than 1000 requests per second, which is 100 times faster than using EJBs. However it occasionally throws ConcurrentModificationExceptions because I&#8217;m not synchronozing properly (fixing this will lower performance).</p>
<p>Then I deployed everything on <strong>one EC2 instance</strong>.<br />
When I run the client on the outside I get around 100 requests per second, which may be due to my internet connection speed. But when I execute the client on another EC2 instance, I expect no communication bottlenecks. Instead I get 3 requests per second. Either there is a huge traffic jam on the EC2 internal network or I have misconfigured the benchmark client.<br />
Running the benchmark on the EJB3 implementation shows a performance of 7 requests per second.</p>
<p>Next thing I need to do is some EJB3 tuning. I have the feeling I have not set up transactions correctly.<br />
If you have any suggestion or wish your technology stack to be evaluated or perhaps want to contribute, please leave a comment.</p> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/jaksa.wordpress.com/36/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jaksa.wordpress.com/36/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/jaksa.wordpress.com/36/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jaksa.wordpress.com/36/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/jaksa.wordpress.com/36/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jaksa.wordpress.com/36/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/jaksa.wordpress.com/36/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jaksa.wordpress.com/36/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/jaksa.wordpress.com/36/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jaksa.wordpress.com/36/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaksa.wordpress.com&blog=2662408&post=36&subd=jaksa&ref=&feed=1"/>]]></content:encoded>
         <media:content url="" medium="image">
            <media:title>jaksa</media:title>
         </media:content>
      </item>
      <item>
         <title>Ajax Fundamentals – Part 4</title>
         <link>http://darynholmes.wordpress.com/2008/09/23/ajax-fundamentals-part-4/</link>
         <description>Index &amp;#124; Part 1 &amp;#124; Part 2 &amp;#124; Part 3 &amp;#124; Part 4 &amp;#124; Part 5 5. Development and Debugging Tools
5.1. Documenting JavaScript
JSDoc is an open source tool used to add inline documentation to JavaScript source files. JSDoc is based on the javadoc tool. Many of the javadoc characteristics have been included in JSDoc. An example [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=99&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=99</guid>
         <pubDate>Tue, 23 Sep 2008 10:14:27 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p align="right"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-about-index/">Index</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-part-1/">Part 1</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/03/ajax-fundamentals-part-2/">Part 2</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/12/ajax-fundamentals-part-3/">Part 3</a><span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> </span>Part 4<span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> Part 5</span></p>
<p align="right">
<h2>5. Development and Debugging Tools</h2>
<h3>5.1. Documenting JavaScript</h3>
<p><a rel="nofollow" target="_blank" href="http://jsdoc.sourceforge.net/">JSDoc</a> is an open source tool used to add inline documentation to JavaScript source files. JSDoc is based on the javadoc tool. Many of the javadoc characteristics have been included in JSDoc. An example of using JSDoc can be found <a rel="nofollow" target="_blank" href="http://jsdoc.sourceforge.net/#usage">here</a>.</p>
<h3>5.2. Firefox Tools &amp; Extensions</h3>
<p><a rel="nofollow" target="_blank" href="http://www.mozilla.org/projects/inspector/">DOM Inspector</a> is included in the Mozilla Suite and Firefox browser. This tool provides a graphical user interface that enables a user to brows the document object model of any site. One can view, update and insert DOM attributes dynamically. In order to assist JavaScript developers, DOM Inspector can be switched to JavaScript Object mode. This shows all the properties and methods available to a JavaScript for a particular mode. DOM Inspector provides a JavaScript evaluation window that allows the user to execute JavaScript against selected nodes. There is the option to use CSS Style Rules and Computed Style information. This allows a user to examine the CSS attributes associated with different page elements.</p>
<p><a rel="nofollow" target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/1815">Firefox JavaScript Console</a> is a tool that logs JavaScript errors found on a page when the page is rendered. The Firefox JavaScript Console gives ‘compiler-type’ messages. It describes the error that occurred and the gives the line number.</p>
<p><a rel="nofollow" target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> integrates with Firefox and provides many development tools. Firebug has a version of a DOM inspector that enables a developer to find elements. CSS support allows settings to be altered and viewed. Firebug allows one to monitor the network activity in order to determine how long it takes for different sections of a page to download. A JavaScript Debugger allows one to debug and step through the JavaScript at runtime.</p>
<p><a rel="nofollow" target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/249/">HTML Validator</a> is a Mozilla extension that performs HTML validation within Firefox and Mozilla. HTML Validator validates the HTML locally and does not use a remote third party. The number of errors of a HTML page is seen on the form of an icon in the status bar when browsing. HTML Validator offers a set of tools to assist in validating and correcting HTML tags.</p>
<p><a rel="nofollow" target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/165">Checky</a> is Firefox extension tool for validating HTML. In addition to HTML, Checky can validate XHTML, CSS, RDF, RSS, XML and many more formats. Checky sends the source to third-party cites to be validated. The third-party cites may be free or commercial services.</p>
<p><a rel="nofollow" target="_blank" href="http://chrispederick.com/work/web-developer/">Pederick’s Firefox Web Developer</a> extension offers a large set of tools for a website developer. Web Developer provides an extensive set of tools, from highlighting table cells to converting ‘GET’ requests to ‘POST’ requests. This toolbar contains more than 80 tools and is an essential commodity.</p>
<h3>5.3. JavaScript Syntax Checking</h3>
<p><a rel="nofollow" target="_blank" href="http://www.jslint.com/">JSLint</a> is an online tool that evaluates JavaScript code. JSLint scans the JavaScript code and identifies syntax errors, structural problems and questionable coding-style conventions.</p>
<h3>5.4. Compression and Obfuscation</h3>
<p><a rel="nofollow" target="_blank" href="http://hometown.aol.de/_ht_a/memtronic/">MemTronic&#8217;s</a> FREEWARE HTML/JavaScript Cruncher-Compressor is a freeware tool that can perform both compression and obfuscation. The MemTronic&#8217;s website provides the following information. The tool can Crunch, Compress and Obfuscate. Crunching removes all comments and whitespace. Crunching has a bandwidth saving between 20%-50%. Compressing will compress the script with a real compression-scheme, with auto decompression added to the file. This results in bandwidth savings between 40% &#8211; 90%. The obfuscator has not been released at this stage. Once complete this tool will encode the script into a format that humans can not easily read. When using Compress, the file will undergo a level of obfuscation.</p>
<p align="right"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-about-index/">Index</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-part-1/">Part 1</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/03/ajax-fundamentals-part-2/">Part 2</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/12/ajax-fundamentals-part-3/">Part 3</a><span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> </span>Part 4<span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> Part 5</span></p>
<p align="right">
Posted in AJAX, Technologies Tagged: AJAX, JavaScript, Tools <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/99/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/99/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=99&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Darren on Flex: Overloading the Constructor - Revisted</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/mIvfs16AqCg/its-not-personal-darren-on-flex.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/mIvfs16AqCg&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-7772317346601653485</guid>
         <pubDate>Mon, 22 Sep 2008 12:38:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://2.bp.blogspot.com/_Q_F_ea5EKi0/SNgDXWOuHiI/AAAAAAAAADk/jZ3BXp9BZIk/s72-c/ScreenHunter_01+Sep.+22+21.42.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Darren on Flex: Overloading the Constructor</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/3ZlWzc0Z-TA/darren-on-flex-overloading-constructor.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/3ZlWzc0Z-TA&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-891141856223849476</guid>
         <pubDate>Sun, 21 Sep 2008 03:45:00 -0700</pubDate>
      </item>
      <item>
         <title>Darren on Flex: New FlexUnit 0.9 Out!</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/qvA3lLdLnPc/darren-on-flex-new-flexunit-out.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/qvA3lLdLnPc&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8796253195330868124</guid>
         <pubDate>Sat, 20 Sep 2008 01:41:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_Q_F_ea5EKi0/SNTC3zRJxyI/AAAAAAAAADc/Edo2KlXkO1s/s72-c/ScreenHunter_03+Sep.+20+10.08.jpg" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 12</title>
         <link>http://change-challenge.blogspot.com/2008/09/basics-of-web-site-optimisation-rule-12.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My number 12 rule: Test your own site with multiple web browsers!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;These days it takes just a few minutes to download and install different web browsing possilibities and I recommend you do it to test your own site. Nothing compares to a quick visual check that your web site still looks okay, or better, than doing so in a browser that you maybe do not often use.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/07/basics-of-web-site-optimisation-rule-4.html&quot;&gt;Analyse your web traffic analysis reports&lt;/a&gt; to check which browsers account for 90-95% of your traffic and then make sure that 90-95% of the time your site renders/displays as you wish it to. &lt;br /&gt;&lt;br /&gt;Also using your traffic analysis reports, you can verify which of your visitors turned into form submitters and became potential customers. Make sure your forms work correctly in their browsers before you publish changes!!&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Reasoning:&lt;/span&gt;&lt;br /&gt;1. It is just so darn tricky to know for sure that even if you are following the standards perfectly, the web browsers may not be. Best to check it out visually, using the tools that your clients use.&lt;br /&gt;2. It is very quick and simple to do - so do it. You will also see your site in new ways that might lead to further design benefits.&lt;br /&gt;&lt;br /&gt;And that is my Rule 12. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-2710034772162741011?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-2710034772162741011</guid>
         <pubDate>Mon, 08 Sep 2008 09:00:00 -0700</pubDate>
      </item>
      <item>
         <title>Iterative and Agile - the Venn Diagram of truth</title>
         <link>http://21ccw.blogspot.com/2008/09/iterative-and-agile-venn-diagram-of.html</link>
         <description>&lt;div&gt;I'm seeing a bit of this lately:&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space:pre;&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;Iterative software development is Agile software development.&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;and I have to say that I disagree quite strongly. The Venn diagram actually looks more like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;http://1.bp.blogspot.com/_bXDgUoT7V7o/SOI-BbG_ZmI/AAAAAAAAAIE/DfiQYsrWfI0/s400/agile_venn.png&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5251828309645289058&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This post has been prompted by two things. First, a few weeks ago a SCRUMmer made some comments along the following lines:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;We don't allow changing the iteration plan once the iteration has begun&quot; &lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;All the requirements for the stories for the iteration must have been gathered before it starts.&quot;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;&quot;If the customer want something else, they have to wait for the next iteration&quot;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;And some &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/news/2008/09/Short-Iterations-Mishkin-Berteig&quot;&gt;articles&lt;/a&gt;/&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://agile-commentary.blogspot.com/2008/09/shorten-your-iteration.html&quot;&gt;blogs&lt;/a&gt; about iteration lengths that jogged my memory about what I disagreed with. The root of my discomfort in equating iterative development to agile development is because&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;agile software development is a set of values, it is not a process. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In fact, one of the core values of Agile development is to &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;not&lt;/span&gt; value you process too much. There are some processes that try to embody Agile values, and they have different interpretations and practicalities around those values, but these &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;processes&lt;/span&gt; are not what defines &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;Agile&lt;/span&gt; development. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://agilemanifesto.org/&quot;&gt;reminder&lt;/a&gt; of what it means to be agile:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight:bold;&quot;&gt;Individuals and interactions&lt;/span&gt; over processes and tools &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight:bold;&quot;&gt;Working software&lt;/span&gt; over comprehensive documentation &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight:bold;&quot;&gt;Customer collaboration&lt;/span&gt; over contract negotiation &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight:bold;&quot;&gt;Responding to change&lt;/span&gt; over following a plan &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;It's very possible to do iterative development without embodying &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;any&lt;/span&gt; of these values. Treating each iteration like a waterfall with the usual waterfall suspects (requirements up front, little room for manoevering, opressive specification and documentation) is a case in point. And to me, valuing your plan over your customer by not responding to their needs is &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style:italic;&quot;&gt;not&lt;/span&gt; Agile.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You are, of course, invited to disagree...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-5384711924776737130?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-5384711924776737130</guid>
         <pubDate>Sun, 07 Sep 2008 22:31:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://1.bp.blogspot.com/_bXDgUoT7V7o/SOI-BbG_ZmI/AAAAAAAAAIE/DfiQYsrWfI0/s72-c/agile_venn.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Me and my dog on Google Chrome</title>
         <link>http://21ccw.blogspot.com/2008/09/me-and-my-dog-on-google-chrome.html</link>
         <description>Like every man and his dog I feel compelled to say something about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/chrome&quot;&gt;Chrome&lt;/a&gt;, Google's new browser. Most impressions I have read have been favourable, and my personal experience so far is very positive. Most reviews I have scanned have been thumbs-up, and have focussed on the usual suspects, i.e. rendering and javascript performance, stability, usability etc. etc.&lt;div style=&quot;text-align:center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For me, there is something subtle and extremely powerful that comes with Chrome. It fields a combination of features with very powerful implications. A &quot;whole being more that the sum of the parts&quot; kind of situation.&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the past year or two there has been a lot of focus in the &quot;richer&quot; web experience, and on ways of getting the web to feel more like the desktop. Newish technologies like Flex and Silverlight have received significant attention, and DHTML (Javascript+CSS+DOM+HTML) seems to have become the cousin that you are obliged to invite to your wedding party (or application party), but don't really want to. I believe that part of the reason for this has been Javascript performance, but there are several efforts underway (e.g. TraceMonkey and now Chrome's V8 Javascript engine) that will bring huge leaps in performance to Javascript. Also, I prefer to support non-proprietary technologies such as DHTML over vendor-based alternatives like Flex and Silverlight.&lt;/div&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second feature that's important in Chrome is process isolation for tabs. This enables each tab to be completely isolated from other processes. One tab going down doesn't take the whole browser with it (which is something that has plagued my Firefox quite a bit).&lt;/div&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thirdly, we have &quot;application-like&quot; OS integration in Chrome. Chrome has the ability to make a single tab look like an application window, with normal window decorations:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SMUU8kz1zyI/AAAAAAAAAH8/B0hxkM8SvUQ/s400/titlebar.png&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5243620372048629538&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In your taskbar it looks like an application, there is quick lauch icon for you app:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;http://4.bp.blogspot.com/_bXDgUoT7V7o/SMUTlKE0ksI/AAAAAAAAAHs/P4OOCC6YjoI/s400/taskbar.png&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5243618870223475394&quot;/&gt;There's also a Start Menu item (not shown) and a Desktop icon:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SMUT16R0EhI/AAAAAAAAAH0/pMHvbHYvCzI/s400/shortcut.png&quot; style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5243619158040777234&quot;/&gt;&lt;div&gt;&lt;br /&gt;The combination of these three is a significant step towards blurring the lines between the desktop and the web. Chrome is an application platform with (potentially) desktop-like application performance (DHTML + V8), process isolation (a key feaure of an application platform) and the web apps look like desktop apps (Operating system integration). And it's all standards based.&lt;br /&gt;&lt;br /&gt;There have been some rumours of a Google OS...&lt;br /&gt;&lt;br /&gt;You're looking at it.&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-4962382545561174872?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-4962382545561174872</guid>
         <pubDate>Wed, 03 Sep 2008 02:29:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_bXDgUoT7V7o/SMUU8kz1zyI/AAAAAAAAAH8/B0hxkM8SvUQ/s72-c/titlebar.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 11</title>
         <link>http://change-challenge.blogspot.com/2008/09/basics-of-web-site-optimisation-rule-11.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My number 11 rule: Do not use JavaScript for navigation effects, especially not dynamic menus&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;JavaScript is a small very powerful programming language for programming web sites in order to give them more functionality than is available in straight static HTML. It is a fantastic language from many perspectives that I will not go into on this entry. People use it to do form validations, image manipulation, dynamic menus and other miscellaneous bits that need to respond to whatever the visitor is doing, or where the visitor comes from in order for the visitor to have an interactive experience with the web site.&lt;br /&gt;&lt;br /&gt;Read more about JavaScript at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/JavaScript&quot;&gt;wikipedia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I follow the mantra &quot;Use as little JavaScript as possible, whilst still making the web site look good, and work well.&quot; I use &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/07/basics-of-web-site-optimisation-rule-7.html&quot;&gt;CSS&lt;/a&gt; as much as possible to make it look good, and as little JavaScript as possible to provide a little tasteful motion, and to do some form validation in order to partially constrict the flood of the requests that could otherwise be submitted via the contact &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/07/basics-of-search-engine-optimisation.html&quot;&gt;forms&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Reasoning:&lt;/span&gt;&lt;br /&gt;1. Search engines can not follow dynamic Java Script menus, thus large parts of your site will go unindexed.&lt;br /&gt;2. Your site will appear smaller and less important to the search engines when they rank you against your competitors.&lt;br /&gt;3. Your site will appear badly organised and less usable to the search engines when they rank you against your competitors.&lt;br /&gt;4. Different versions of browsers treat JavaScript differently, meaning even more testing and &quot;fiddling&quot; in order to get your JavaScript to work correctly and consistently across all your targetted browsers.&lt;br /&gt;&lt;br /&gt;And that is my Rule 11. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-8506782475946997983?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-8506782475946997983</guid>
         <pubDate>Tue, 02 Sep 2008 11:00:00 -0700</pubDate>
      </item>
      <item>
         <title>Getting around in a &quot;locked down&quot; environment</title>
         <link>http://change-challenge.blogspot.com/2008/09/getting-around-in-locked-down.html</link>
         <description>I probably should not really be blogging this little entry, but I just can't help myself! Please continue reading or using these little details at your own peril.&lt;br /&gt;&lt;br /&gt;Recently I discovered myself in a &quot;locked down&quot; environment, yet I still had a tonne of software to install, and I desperately needed it installed &quot;today&quot; rather than after 1 month. (the contract in this case was for this primary purpose - installations, configurations and support) (something completely different to what I've been doing for many years now, but not so different from what I was doing 10 odd years ago, so I had the skills)&lt;br /&gt;&lt;br /&gt;My first step in any new site is to meet as many people as I can, and then to make friends with those that I desperately need, in the order that I need them. It is a hard cold fact, and they know it, and I know it. I am ... for want of a better word ... using them. By doing this though, I suddenly start avoiding official processes, official documents filled out in triplicate, and actually get things done rather quickly. Which makes me look good, compared to the rule followers.&lt;br /&gt;&lt;br /&gt;So with enough friends on my side, around day 2, I learned 1 useful tidbit about the so-called &quot;locked down environment&quot;.... it is not so locked down as made out to be. Thanks to XP's security model, the thing that really enforces lockdown policies is done via LDAP ... when you login or logout of the domain.&lt;br /&gt;&lt;br /&gt;And again, with enough friends on my side, I managed to secure just a slightly better than completely useless level of workstation usage. And here comes the fun bit. Many of the GUI widgets for changing a workstation are stripped out of your view, and some that could not be stripped throw you an error message if you try to access them.&lt;br /&gt;&lt;br /&gt;So ... you find the command line equivalent and use that instead. No security to stop you. Thank goodness for XP! I have no idea what I'll do if I find myself in a Vista or better security modelled domain with the same deadlines - probably make even more friends instead, and take them to the pub every other lunch!&lt;br /&gt;&lt;br /&gt;Here are the 4 that I am using frequently:&lt;br /&gt;&lt;br /&gt;regedit - reg.exe&lt;br /&gt;Data Sources (ODBC) - odbcad32.exe&lt;br /&gt;RemoteDesktop - mstsc.exe&lt;br /&gt;Add/Remove programs - MSIexec&lt;br /&gt;&lt;br /&gt;I am sure there are others, but fortunately I have not needed more than these so far!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-6106976009202070178?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-6106976009202070178</guid>
         <pubDate>Tue, 02 Sep 2008 07:57:00 -0700</pubDate>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 10</title>
         <link>http://change-challenge.blogspot.com/2008/08/basics-of-web-site-optimisation-rule-10.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My number 10 rule: Create a web site/shortcut icon&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is one of the simplest and most overlooked goodies in a web site's &quot;bag of tricks&quot;!&lt;br /&gt;&lt;br /&gt;Ever wonder why some web sites have a little icon in the address bar? For instance the little white-on-orange background &quot;B&quot; in the address bar right now? It is because they have created a &quot;favicon.ico&quot; in the root of their web directory. Not only is it displayed by the browser in the address bar when your visitor visits, but if the visitor bookmarks it, it is displayed in the bookmark view as well - which makes your site stand out from all the others without favicon.ico's! (and vice-versa, makes your site stand out stand out negatively, if all the others do)&lt;br /&gt;&lt;br /&gt;The favicon.ico's that I have created were all based on the old specification of 16x16 pixels in the icon format. These days it is possible to use bigger images, with different formats, but I am still preferring the older specification as it is a very small overhead for your visitor and whatever old browser they may be using 5 years from now. Read more on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Favicon&quot;&gt;wikipedia's Favicon entry&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Reasoning:&lt;/span&gt;&lt;br /&gt;1. This is more a marketing and branding tool/optimisation than a search engine optimisation. It is extremely subtle in the world of too many messages and by using it, you have an opportunity to reinforce your company/site's brand in the visitor's mind - a very good thing. In the world of marketing, brand awareness is key - no one is going to buy &quot;you&quot; if they don't even &quot;know you&quot; - so first seek to build awareness, then start your &quot;trust campaign&quot;. &lt;br /&gt;2. It looks professional and is becoming expected these days&lt;br /&gt;3. And a reminder waiting for each bookmarker is a great place to be&lt;br /&gt;&lt;br /&gt;And that is my Rule 10. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4459796110543026020?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4459796110543026020</guid>
         <pubDate>Sun, 24 Aug 2008 23:00:00 -0700</pubDate>
      </item>
      <item>
         <title>Whiteboarding with Rails and Tomcat: Part II, The Infrastructure</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/oVTZKG9XIIE/whiteboarding-with-rails-and-tomcat.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/oVTZKG9XIIE&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-4227173962273152031</guid>
         <pubDate>Sun, 24 Aug 2008 02:30:00 -0700</pubDate>
      </item>
      <item>
         <title>Whiteboarding with Rails and Tomcat: Part I, The Debate</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/fRLb68OxsSk/ror-passengermodrails-tomcat6comet-part.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/fRLb68OxsSk&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-5330744053238147188</guid>
         <pubDate>Sun, 24 Aug 2008 01:54:00 -0700</pubDate>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 9</title>
         <link>http://change-challenge.blogspot.com/2008/08/basics-of-web-site-optimisation-rule-9.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My number 9 rule: Use these 9 Meta Tags&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;These are probably &quot;over kill&quot; as far as Meta Tag usage is concerned, but I prefer this approach to lesser, until I learn something concrete that differs from my experience which has seen some rapid and sustained visitor rate growth where I applied them.&lt;br /&gt;&lt;br /&gt;Place Meta Tags in all of your page header sections. There are smart tools for generating the content-related ones, but it is better if they fit into your whole marketing and supporting web site design approach, making them very manageable in a manual way on static web sites. On dynamic, use a clever algorithm to assist you in carefully crafted statements.&lt;br /&gt;&lt;br /&gt;Make sure the web page content, including words, links, image names - everything where you can specify text, all aligns with the Keywords, Description and Abstract Meta Tags!&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;Keywords&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[5 comma separated keywords that are present at least twice or more on the page!]&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;Description&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[enter a short statement containing as many of the keywords as possible]&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;Date&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[last update date]&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt; - NOT STRICTLY meta tag legitimate or required but I use it to track the date I last made a change to the page - and use this date to facilitate track which page version search engines have in their cache&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;abstract&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[enter a short statement containing as many of the keywords as possible, possibly reusing the Description meta tag]&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;revisit-after&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[a number that is tuned to the amount of maintenance you do on the site - initially I use 7 because I perform so much tuning and generally I roll out content in a staged approach to ensure high quality and maintain control over the site's visitor growth]&lt;/span&gt; days&quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;rating&quot; content=&quot;&lt;span style=&quot;font-weight:bold;&quot;&gt;general&lt;/span&gt;&quot;&amp;gt; &lt;br /&gt; - there are a number of options here for instance &quot;adult&quot;, but I only use general&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;next&quot; content=&quot;&lt;span style=&quot;font-style:italic;&quot;&gt;[choose or use your site metrics to research the next web page from your site that most visitors normally go to]&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt; - some web browsers (Firefox) will pre-cache the html page you specify here, making the user experience of your web site seem quicker, if they actually follow your &quot;directions&quot;. Very difficult to get right without careful web site design, and if wrong actually wastes your visitors' bandwidth and makes their internet experience slower unnecessarily.&lt;br /&gt;&lt;br /&gt;&amp;lt;META name=&quot;robots&quot; content=&quot;&lt;span style=&quot;font-weight:bold;&quot;&gt;index,follow&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt; - instruct search engines to index this web page, and follow all links on the page&lt;br /&gt; - in the old days of restricted bandwidth, and depending on what I was marketing on the site, I would instruct the search engine to &quot;noindex&quot;&lt;br /&gt;&lt;br /&gt;&amp;lt;META content=&quot;&lt;span style=&quot;font-weight:bold;&quot;&gt;text/html; charset=ISO-8859-1&lt;/span&gt;&quot;&amp;gt;&lt;br /&gt; - very important to clarify to the web browsers what the page content is, and which character set is intended otherwise some foreign visitors could end up with strange symbols unintentionally, making your web site difficult to use&lt;br /&gt;&lt;br /&gt;Reasoning:&lt;br /&gt;1. By using Meta Tags at all the search engines will rank you higher&lt;br /&gt;2. By using the correctly completed Meta Tags, the search engines will rank you even higher&lt;br /&gt;3. They should repeat your key messages you are trying to convey to your visitors - they serve as a check point for detecting if your message is clear and the page is correctly aligned to achieve maximum impact at the search engines AND visitors&lt;br /&gt;4. Search engine spiders, web crawling bots, web caching servers and even web site blocker software use the tags in their &quot;decision&quot; software to decide whether to analyse, cache, or allow the page to be displayed. &lt;br /&gt;&lt;br /&gt;And that is my Rule 9. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-5779119171363209219?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-5779119171363209219</guid>
         <pubDate>Sat, 23 Aug 2008 11:35:00 -0700</pubDate>
      </item>
      <item>
         <title>Light Motivational Relief</title>
         <link>http://change-challenge.blogspot.com/2008/08/light-motivational-relief.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.despair.com/viewall.html&quot;&gt;Despair.com&lt;/a&gt; for wonderful miscellaneous motivational posters and sayings....all twisted into a very cynical viewpoint. It is a really good laugh!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-698758842934802105?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-698758842934802105</guid>
         <pubDate>Sat, 16 Aug 2008 06:43:00 -0700</pubDate>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 8</title>
         <link>http://change-challenge.blogspot.com/2008/08/basics-of-web-site-optimisation-rule-8.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My number 8 rule: Register on Web Directories&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Web Directories are huge databases of links and brief descriptions of web sites, and usually are maintained by actual humans. They are not Search Engines, but in some ways they are similar because they try to get (encourage web masters/site owners) to register on them so that they become ever bigger repositories of information that is similar to library catalogues.&lt;br /&gt;&lt;br /&gt;To be accepted, your site needs to be up to a certain standard - which is a good thing! The editors of these Web Directories see 1000's of sites and it should be reassuring to you that someone has assessed your application form, and your web site, and found you/your idea/your web site acceptable to the rest of the world!&lt;br /&gt;&lt;br /&gt;For more up to the date information of the Web Directories, access wikipedia's &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/List_of_web_directories&quot;&gt;List of Web Directories&lt;/a&gt; and get registered everywhere suitable!&lt;br /&gt;&lt;br /&gt;Your time is obviously limited and therefore over time it is apparent that in general the most important one is the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://dmoz.org/&quot;&gt;Open Directory Project&lt;/a&gt;. Be very careful to select the right categorisation for your web site. VERY CAREFUL! Like all good information clustering, and all good search engine ranking systems, things need to be as aligned as possible for optimal benefit. Be as specific with your categorisation as possible, and make sure your web site is reflecting that profile!!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Reasoning:&lt;/strong&gt;&lt;br /&gt;1. All of the major search engines use the web directories as a starting point for their &quot;entire web crawl&quot;. &lt;br /&gt;2. Search engines rate sites that are reviewed by real human editors of various Web Directories and accepted in them, quite highly. &lt;br /&gt;3. Search engines will use the web directory classification of your web site to create a cluster for your site, and clustered information/sites rank more highly than complete &quot;unknowns&quot; for search engines.&lt;br /&gt;4. While you are registering, and you are accepted, you will find competitor web sites that you can examine for marketing insights.&lt;br /&gt;5. After you are accepted, it should be possible for you to form alliances (link swap) with some of the other sites registered in the same area, or in similar but alternate categories of the web directory - a very good thing!&lt;br /&gt;&lt;br /&gt;And that is my Rule 8. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-6676775685111844526?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-6676775685111844526</guid>
         <pubDate>Fri, 15 Aug 2008 05:00:00 -0700</pubDate>
      </item>
      <item>
         <title>Basics of Web Site Optimisation - Rule 7</title>
         <link>http://change-challenge.blogspot.com/2008/07/basics-of-web-site-optimisation-rule-7.html</link>
         <description>This post is mainly aimed at small to medium businesses that are just starting out and are keen to get something going, or have just gone live. I can't tell you how many times I have taught people over the past few years just a handful of strategically important things. So...here goes again, this time in a way that I can now simply refer to. As for my credibility - I would rather not divulge that here, read my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/search/label/web%20site%20optimisation&quot;&gt;Web Site Optimisation Rules&lt;/a&gt; and you decide. They are, after all, common sense, and common knowledge....like most things I blog about!&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;My number 7 rule: Use Cascading Style Sheets (CSS) to configure your site's look and feel and store in separate files&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most of the target audience of these rules I am writing up, commission web sites from friends, or friend-of-friends, or recommendations of small web site development shops ... who don't seem to know, or know enough about Cascading Style Sheets (CSS).&lt;br /&gt;&lt;br /&gt;The basics are that with your CSS stored in a separate file, you can edit the look and feel of your entire web site, without having to know much about what you are doing. CSS is a very simple and easy to understand configurable set of options for which there are a large number of cheap (and free even) tools to help you make your site exactly the way you would like - independently of some technical person. (I once taught a very busy CEO just enough about CSS for him to take ownership of that aspect of his 1000 page web site!). You name the different sets something useful which makes them easier to use throughout your site such as &quot;ProductDescription&quot;.&lt;br /&gt;&lt;br /&gt;People who implement web sites typically are more interested in the underlying functionality and more technical aspects than about how pretty it looks, or how well it matches the site owner's evolving branding efforts. By making use of CSS, anyone can be placed in charge of actually experimenting and figuring out ideal combinations of colours and font styles, text sizes, margins, borders and spacings that work in harmony together to create a truly unique and excellent user web experience.&lt;br /&gt;&lt;br /&gt;To see what you can do with CSS's, have a look at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.csszengarden.com/&quot;&gt;The CSS Zen Garden&lt;/a&gt;. This site contains beautiful samples of completely different CSS competitive entries for the same web page...and it is completely amazing with what the entrants have come up with - radical differences!&lt;br /&gt;&lt;br /&gt;In some ways this CSS rule is related to my rule 5: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://change-challenge.blogspot.com/2008/07/basics-of-web-site-optimisation-rule-5.html&quot;&gt;Comply with web standards - html&lt;/a&gt; as CSS's are also governed by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3.org/&quot;&gt;W3C&lt;/a&gt; standards! You can teach yourself about them by following the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3schools.com/css/&quot;&gt;CSS Tutorials&lt;/a&gt; from the W3C.&lt;br /&gt;&lt;br /&gt;And, because there is a standard for them, the W3C have once again provided an online checking facility for you to use to validate your own, or your supplier's efforts: simply submit your HTML or CSS web document to the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jigsaw.w3.org/css-validator/&quot;&gt;Online Cascading Style Sheet (CSS) Checker&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Reasoning:&lt;/span&gt;&lt;br /&gt;1. With CSS you can evolve really really very good looking web sites! It is almost impossible to get a web site perfect in just 1 attempt!&lt;br /&gt;2. Anyone can configure and maintain them - making your site's look and feel very easy to update and preferably maintained by someone who really cares!&lt;br /&gt;3. Separate your CSS definitions from your HTML web pages by placing them in separate files that you include in your header tags. Web browsers cache the CSS definition files and thus your HTML pages are smaller, easier to maintain, faster to download and even more focussed for search engine optimisation strategies.&lt;br /&gt;4. By using CSS's it is possible to test updates of the look and feel against the production web site without having to go live first! It is possible to configure modern web browers to use alternatve CSS definition files against any web site! &lt;br /&gt;&lt;br /&gt;And that is my Rule 7. I will be uploading the others as time allows!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6989989674376899020-4491447486111732540?l=change-challenge.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Rob Brown</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-6989989674376899020.post-4491447486111732540</guid>
         <pubDate>Mon, 04 Aug 2008 06:57:00 -0700</pubDate>
      </item>
      <item>
         <title>Scalaris Released</title>
         <link>http://21ccw.blogspot.com/2008/07/scalaris-released.html</link>
         <description>If you were at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/&quot;&gt;Erlang Exchange&lt;/a&gt; in London last month, you should know that one of the hottest talks was given by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/alexander-reinefeld&quot;&gt;Alexander Reinefeld&lt;/a&gt;, &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://skillsmatter.com/podcast/erlang/building-a-transactional-distributed-data-store-with-erlang&quot;&gt;Building a transactional distributed data store with Erlang&lt;/a&gt;&quot;&lt;br /&gt;&lt;br /&gt;Joe Armstrong seems to like it too:&lt;br /&gt;&lt;br /&gt;&quot;I might be wrong, but my gut feeling is that what Alexander Reinefeld showed us will be the first killer application in Erlang.&quot;&lt;br /&gt;&lt;br /&gt;&quot;So my take on this is that this is one of the sexiest applications I've seen in many a year. I've been waiting for this to happen for a long while. The work is backed by quadzillion Ph.D's and is really good &lt;span style=&quot;font-style:italic;&quot;&gt;believe me.&quot;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;- http://armstrongonsoftware.blogspot.com/2008/06/itching-my-programming-nerve.html&lt;br /&gt;&lt;br /&gt;Well, seems like Scalaris has been released! The link went up on the website in the last 24-48 hours. I haven't had the time to look at it yet, but you can grab it &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/scalaris/&quot;&gt;here&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-1549559424813718640?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-1549559424813718640</guid>
         <pubDate>Wed, 23 Jul 2008 21:46:00 -0700</pubDate>
      </item>
      <item>
         <title>Ajax Fundamentals – Part 3</title>
         <link>http://darynholmes.wordpress.com/2008/07/12/ajax-fundamentals-part-3/</link>
         <description>Index &amp;#124; Part 1 &amp;#124; Part 2 &amp;#124; Part 3 &amp;#124; Part 4 &amp;#124; Part 5
3. Security Issues
The XMLHttpRequest object is restricted to run within the browser’s security sandbox. Any resources requested by the XMLHttpRequest object must reside within the same domain from which the calling script originated. Therefore the XMLHttpRequest object is constrained to [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=86&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=86</guid>
         <pubDate>Sat, 12 Jul 2008 01:39:01 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p align="right"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-about-index/">Index</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-part-1/">Part 1</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/03/ajax-fundamentals-part-2/">Part 2</a> | Part 3<span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> </span><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/09/23/ajax-fundamentals-part-4/">Part 4</a><span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> Part 5</span></p>
<h2>3. Security Issues</h2>
<p>The XMLHttpRequest object is restricted to run within the browser’s security sandbox. Any resources requested by the XMLHttpRequest object must reside within the same domain from which the calling script originated. Therefore the XMLHttpRequest object is constrained to requesting resources that reside within the same domain from which the script was originally served. The W3C <a rel="nofollow" target="_blank" href="http://www.w3.org/TR/XMLHttpRequest/">states</a>, that in the future The XMLHttpRequest Object specification will define a way of doing cross-site requests.</p>
<p>There is an overabundance of online documentation stating that Ajax introduces multiple security threats. These threats include fake requests, denial of service, cross-site scripting (XSS), reliance on client-side security, and more. Jeremiah Grossman’s article, <a rel="nofollow" target="_blank" href="http://jeremiahgrossman.blogspot.com/2006/11/myth-busting-ajax-in-security.html">Myth-Busting AJAX (In)security</a>, maintains that these security issues existed before Ajax and the recommended security best practices remain unchanged. Part of internet security basics is to distrust the client. Ajax is a client side technology and requests need to be treaded with the same caution as all other calls.</p>
<h2>4. Disadvantages</h2>
<h3>4.1. Usability Problems</h3>
<p>Web users have become familiar with using classic web pages. Users have become accustomed to using browser features such as the back and next buttons. Ajax calls are not loaded onto the browsers navigation stack. Therefore the back button will not undo the last ‘Ajax operation’. Developers need to explicitly cater for undo operations.</p>
<p>Ajax enabled pages have a notion of state; this state is altered as the user navigates through the site. The browser is unaware of this state, and it is not reflected in the address bar. Therefore users are not always able to book mark a certain page state. Developers need to consider this when deciding on when to use Ajax.</p>
<p>The asynchronous nature may make page updates difficult for the user to notice. The developer needs a way of drawing the user’s attention to the modified section of the page. The ‘yellow-fade technique’ has become common practice. In this technique the changes are highlighted with a yellow background, and the yellow fades gradually. These and other techniques are becoming familiar to web users.</p>
<h3>4.2. JavaScript Disabled</h3>
<p>If a user has disabled JavaScript no JavaScript will be executed and certainly no Ajax requests will be sent. A site that relies too heavily on JavaScript will be crippled if the user disables JavaScript, <a rel="nofollow" target="_blank" href="http://www.gucci.com/">Gucci</a> is an example of this. This site used to show a blank white page if a user browsed to it after disabling JavaScript. Now it explains that you need to have JavaScript enabled to use the site.</p>
<p>A site that relies on JavaScript for core functionality restricts its users to those who have JavaScript enabled. Having said that we should look at how many users are allowing JavaScript to run in there browsers. The following statistics from <a rel="nofollow" target="_blank" href="http://www.thecounter.com/">The Counter</a> show JavaScript statistics.</p>
<p><span id="more-86"></span></p>
<p><span style="text-decoration:underline;">Wed Mar 1 00:01:01 2000 &#8211; Fri Mar 17 23:59:01 2000</span><br />
Javascript 1.2+: 260153365 (79%)<br />
Javascript &lt;1.2: 7790575 (2%)<br />
Javascript false: 59884983 (18%)</p>
<p><span style="text-decoration:underline;">Thu Mar 1 00:01:01 2007 &#8211; Thu Mar 22 13:58:01 2007</span><br />
Javascript 1.2+: 56607094 (95%)<br />
Javascript &lt;1.2: 193622 (0%)<br />
Javascript false: 2524217 (4%)</p>
<p>These stats show that most users are using JavaScript, therefore many stake holders would approve of the use of Ajax on their sites. Although there are cases where limiting access is unacceptable.</p>
<h3>4.3. Search Engine Indexing</h3>
<p>Web crawlers automatically navigate through the web by following link tags e.g. href, src etc. Current web crawlers do not examine client side scripts. Search engines skip the JavaScript code that executes the Ajax calls. Content loaded by Ajax calls will not be indexed by search engines.</p>
<p>Multiple solutions have been proposed to solve this problem. Most of these are workarounds and do not solve the underlying problem. In fact some approaches are considered as <a rel="nofollow" target="_blank" href="http://www.softwaredeveloper.com/features/google-ajax-play-nice-061907/">cloaking</a> and can get the site black listed by Google. Google have stated that they will improve there searches, at present they do not follow Ajax calls. In order to make sure that specific content will be found by search engines, the site should have standard HTML links that web crawlers can follow.</p>
<p align="right"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-about-index/">Index</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/02/ajax-fundamentals-part-1/">Part 1</a> | <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/03/ajax-fundamentals-part-2/">Part 2</a> | Part 3<span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> </span><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/09/23/ajax-fundamentals-part-4/">Part 4</a><span style="color:#c0c0c0;"> <span style="color:#000000;">|</span> Part 5</span></p>
<p align="right"><span style="color:#c0c0c0;"></span></p>
<p align="right">
<p align="right">
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/86/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/86/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/86/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/86/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/86/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/86/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/86/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=86&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Thinking in Rails – Part 1</title>
         <link>http://darynholmes.wordpress.com/2008/07/10/private-thinking-in-rails-%e2%80%93-part-1/</link>
         <description>Part 0
In this part we look at the basic set of requirements for our text editor. I have no doubt that these requirements will change, but let’s have a quick look to get an idea of the direction we are heading in.
Text Editor Requirements
As mentioned in part 0, the text editor is going to be [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=79&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=79</guid>
         <pubDate>Thu, 10 Jul 2008 08:55:50 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/10/thinking-in-rails-%E2%80%93-part-0/">Part 0</a></p>
<p>In this part we look at the basic set of requirements for our text editor. I have no doubt that these requirements will change, but let’s have a quick look to get an idea of the direction we are heading in.</p>
<h2>Text Editor Requirements</h2>
<p>As mentioned in part 0, the text editor is going to be a very basic editor. It will maintain a version history that will allow users to roll back to a previous version of a document. This requirement is what will make this task interesting and worthwhile.</p>
<p>We would like to end up with screens similar to this:</p>
<p>The documents index page:</p>
<p><a rel="nofollow" target="_blank" href="http://darynholmes.files.wordpress.com/2008/07/document-index.png"><img class="alignnone size-full wp-image-82" src="http://darynholmes.files.wordpress.com/2008/07/document-index.png?w=439&#038;h=175" alt="" width="439" height="175"/></a></p>
<p><span id="more-79"></span></p>
<p>Clicking ‘show’ will show the related document and give the user an option to edit it.</p>
<p>Clicking ‘edit’ will show a form that allows the user to edit the document. When the user clicks ‘save’, the application creates a new version, without overwriting existing versions.<br />
<em>We will be providing this behaviour with a slight ‘twist of hand’. I will come back to this point when we actually implement it.</em></p>
<p>Clicking ‘delete’ will completely remove the document and all its versions – this is not a roll back.</p>
<p>If the user clicks on ‘History’ on ‘Second one’. We expect to see a screen similar to this:</p>
<p><a rel="nofollow" target="_blank" href="http://darynholmes.files.wordpress.com/2008/07/show-document-2.png"><img class="alignnone size-full wp-image-85" src="http://darynholmes.files.wordpress.com/2008/07/show-document-2.png?w=398&#038;h=212" alt="" width="398" height="212"/></a></p>
<p>Clicking ‘show’ will show the relevant version.<br />
Clicking ‘rollback’ will delete the latest version, thus rolling back to the previous version – this is deleting one version only, not the entire document.</p>
<h3>What is next?</h3>
<p>Next we will have a quick look at the database schema and then we finally move onto Rails code! We will not be using the scaffolding features of Ruby on Rails. We will create our application from the ground up – generating models, controllers and views independently. We will also be coding using TDD. If you are new to Rails, I am sure you will enjoy the upcoming posts.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/79/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/79/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/79/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/79/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/79/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/79/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/79/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/79/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/79/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/79/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/79/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/79/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=79&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
         <media:content url="http://darynholmes.files.wordpress.com/2008/07/document-index.png" medium="image"/>
         <media:content url="http://darynholmes.files.wordpress.com/2008/07/show-document-2.png" medium="image"/>
      </item>
      <item>
         <title>Thinking in Rails – Part 0</title>
         <link>http://darynholmes.wordpress.com/2008/07/10/thinking-in-rails-%e2%80%93-part-0/</link>
         <description>Part 1
This is ‘part 0’ as it is an explanation of the tutorial, no Rails code is covered in this part &amp;#8211; I still need to write the code. This post explains what you can expect to see in future parts of this tutorial. If there is a topic you would like me to cover [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=77&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=77</guid>
         <pubDate>Thu, 10 Jul 2008 08:37:06 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p style="text-align:right;"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/10/private-thinking-in-rails-%E2%80%93-part-1/">Part 1</a></p>
<p>This is ‘part 0’ as it is an explanation of the tutorial, no Rails code is covered in this part &#8211; <em>I still need to write the code</em>. This post explains what you can expect to see in future parts of this tutorial. If there is a topic you would like me to cover then please feel free to make a request…</p>
<h3>What is the purpose of this tutorial?</h3>
<p>Ruby is not just another OOP language. It has many idioms and constructs which seem foreign at first. Once a developer becomes familiar with these aspects the developer tends to program in a new way – the once foreign code starts to feel very natural.</p>
<p>Moving from Java or .Net to Ruby (and Ruby on Rails) is a challenge, but it is worth the effort. Once you start thinking in the Ruby and Rails way code starts falling into place. To cross the conceptual chasm you need to read many articles, books and as much code as you can. This tutorial aims to assist you as you crossover. Use it as a stepping stone on your path to the land of the <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Duck_typing">ducks</a>.</p>
<h3>How did this tutorial come to be?</h3>
<p>This tutorial is a spin-off from the ‘Routing in Rails’ tutorial. The ‘text editor’ application covered here was originally intended to be the practical section of <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/06/beginners-tutorial-routing-in-rails-20-with-rest-part-6-of-n/">part 6</a>. I started developing the application and soon realised that the actual routing work was very small, and was being lost amongst the rest of the code. I felt that the application still covered many useful topics, therefore I decided to move it into its own tutorial – and here it is.</p>
<p><span id="more-77"></span></p>
<h3>What does this tutorial cover?</h3>
<p>This tutorial attempts to answer two questions posted to me in previous comments and emails. One question was with regards to one to many relationships and nested resources. This was covered in part 6 of the ‘Routing Tutorial’ – here we use them to build the ‘text application’ below.</p>
<p>The second question was from Tom made here: “When you get to RESTful routing I would like to see an example of how to add a Save As function. This would allow the user to derive a new record in a table from an existing record. So it would start as an edit function but end as a create action instead of an update action”</p>
<p><em>The second question poses an interesting REST problem. Some readers may not agree with the solution I am suggesting here. If you have any objections to this solution, please voice your objection in a comment, this will help all of us.</em></p>
<p>In addition to answering these questions, this tutorial will cover some common Rails problems e.g. using 2 models with 1 form, has many function, YAML, testing in Rails, replacing link_to with button_to etc.</p>
<p>As you can see, this tutorial covers many topics. I do not intend to cover each topic in detail &#8211; <em>I would like to, I just don’t have the time</em>. The ‘Rails Routing Tutorial’ focused on one specific topic. This tutorial shows you a bigger picture; the aim is to help you to start thinking in Rails.</p>
<h3>What is not covered in this tutorial?</h3>
<p>We will not be creating the definitive Rails application. The application being developed here should be thought of as the output of iteration one. While following along you should find yourself thinking: ‘would it not be better to do this?’, ‘if we did this, the test would be much cleaner’, ‘I wonder if we can add this information to the view’. If you start thinking like that, then you are starting to think in the Rails way.</p>
<p>Even though it is a good idea to add CSS to your Rails application from a very early stage, I do not intend to cover CSS. I would rather focus on other topics, at least for the first few parts of this tutorial – <em>I may include it at a later stage</em>.</p>
<p>This tutorial will cover the default Rails testing and not RSpec. RSpec is good and I recommend that you look into it. The only reason I am not using it here is because it requires plug-ins. These plug-ins are version dependant and I would rather avoid the potential versioning conflicts that may result from this. The testing lessons learned here can be carried over to RSpec.</p>
<h3>What about the Music Store?</h3>
<p>In this tutorial we will not be using the <em>amazing</em> Music Store application from the Routing tutorial. Instead we can create a new application. This new application will be a plain text editor. The text editor will have a version history. This will allow a user to ‘roll back’ to a previous version of the document.</p>
<p>This will be a basic text editor. The intension is not to create a fully fledged text editor. The aim is to familiarise ourselves with the Rails development process so that we begin to think in Rails.</p>
<h3>What is next?</h3>
<p>Next we look at the basic set of requirements of the text editor application. Please let me know if you would like to know more about a specific Rails topic, I will try to work it into the tutorial.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/77/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/77/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/77/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/77/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/77/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/77/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/77/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=77&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Subscribing to Label Feeds</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/rR7IqyqJBBs/subscribing-to-label-feeds.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/rR7IqyqJBBs&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-8721672579310268833</guid>
         <pubDate>Thu, 10 Jul 2008 02:18:00 -0700</pubDate>
      </item>
      <item>
         <title>Short-listed!?!</title>
         <link>http://darynholmes.wordpress.com/2008/07/08/short-listed/</link>
         <description>About a week ago I noticed some incoming links from Computer Weekly.com. I assumed that someone had commented on one of my posts, so I browsed there wondering if it was a positive or negative comment. Once the page loaded, I was completely surprised. It turns out that this blog has been short-listed for the [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=75&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=75</guid>
         <pubDate>Tue, 08 Jul 2008 14:17:25 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>About a week ago I noticed some incoming links from Computer Weekly.com. I assumed that someone had commented on one of my posts, so I browsed there wondering if it was a positive or negative comment. Once the page loaded, I was completely surprised. It turns out that this blog has been short-listed for the <a rel="nofollow" target="_blank" href="http://www.computerweekly.com/Articles/2008/06/30/230439/programming-and-development-blogs-computerweekly.com-it-blog-awards.htm">Computer Weekly.com IT Blog Awards</a>! This came as a complete surprise to me.</p>
<p>This blog had really humble beginnings. In fact it was not even my idea to start a blog, it was my <a rel="nofollow" target="_blank" href="http://www.zuehlke.com/en/know-how/nach-technologien/agile-software-entwicklung/">work</a> that encouraged me to start one. Initially I felt that I did not have that much to contribute to the world at large. In fact I still don&#8217;t feel that my blog is as innovative as some others, although judging by the response to my &#8216;<a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/03/15/beginners-tutorial-routing-in-rails-20-with-rest-part-1-of-n/">Routing In Rails Tutorial</a>&#8216; it appears as if I do have a nice way of explaining things. I guess this is one of the main reasons I have been voted onto the shortlist.</p>
<p>The competition ends on the 31st of July 2008. If you would like to vote please go to this <a rel="nofollow" target="_blank" href="http://www.computerweekly.com/blogawards.htm">on-line voting page</a>. This blog can be found under the &#8216;Programming and technical blogs&#8217;<strong> </strong>drop-down list. It is a surprisingly painless exercise, it takes less then a minute and no registration is required.</p>
<p>Thank you to all of you who have voted for this blog.</p>
<p>Daryn</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/75/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/75/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/75/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/75/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/75/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/75/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/75/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=75&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>See, Agile Isn't Just Good Sense, It's Common Sense</title>
         <link>http://feedproxy.google.com/~r/ItsNotPersonal/~3/bIe_lMSgh1U/see-agile-isnt-just-good-sense-its.html</link>
         <description>&lt;img src=&quot;http://feeds.feedburner.com/~r/ItsNotPersonal/~4/bIe_lMSgh1U&quot; height=&quot;1&quot; width=&quot;1&quot;/&gt;</description>
         <author>noreply@blogger.com (Darren Bishop)</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3826577489563855618.post-2015565646549443464</guid>
         <pubDate>Mon, 07 Jul 2008 22:08:00 -0700</pubDate>
      </item>
      <item>
         <title>Beginners Tutorial: Routing in Rails 2.0 (with REST) – Part 6 of n</title>
         <link>http://darynholmes.wordpress.com/2008/07/06/beginners-tutorial-routing-in-rails-20-with-rest-part-6-of-n/</link>
         <description>In part 5 we looked at RESTful routing. In this part we continue to explore RESTful routing, by examining nested resources.
I originally planned to cover nested routes and to cover two questions posted to me in previous comments and emails. One question was with regards to &amp;#8216;one to many relationships&amp;#8217; e.g. an album has many [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=73&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=73</guid>
         <pubDate>Sun, 06 Jul 2008 13:33:00 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>In <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/05/26/beginners-tutorial-routing-in-rails-20-with-rest-part-5-of-n/">part 5</a> we looked at RESTful routing. In this part we continue to explore RESTful routing, by examining nested resources.</p>
<p>I originally planned to cover nested routes and to cover two questions posted to me in previous comments and emails. One question was with regards to &#8216;one to many relationships&#8217; e.g. an album has many songs. The second question was from Tom in part 3; this was about adding save as functionality.</p>
<p>In trying to answer these questions I created a new application – a text editor with a version history. This has turned out to be a fairly interesting piece of work. I then changed my mind and decided to include it in a follow up post. I am hoping to have that out later this week (before Friday the 11th of July). As the ‘follow up’ post will have a practical example of nested resources, this post will not have the usual practical section with the experiments.</p>
<h2>Part 6</h2>
<h3>Introduction to Nested Resources</h3>
<h4>The Nested URI</h4>
<p>Returning to the familiar Music Store application, imagine we added songs to the application. Like Albums, Songs are resources and we could expect to access a song with this URI:</p>
<p>/songs/124</p>
<p>We could then perform the required CRUD operations on that URI based on the REST API as discussed in part 5.</p>
<p>An album has many songs. We can express this within the URI e.g.</p>
<p>/albums/10/songs/124</p>
<p>Once again we could make use of the HTTP verbs to perform CRUD in a RESTful way.</p>
<p><strong>In this particular implementation</strong>, this URI does not mean that this is the  124<sup>th</sup> song of album 10 -<em> it is possible for it to be the fist song of album 10</em>. The URI is pointing to the 124<sup>th</sup> song in the system.</p>
<p>If we wanted the URI to state the song&#92;track number of the specified album then we could alter the above implementation. Then we could expect to see URIs of:</p>
<p>/albums/10/songs/5<br />
and<br />
/albums/11/songs/5</p>
<p>This would not result in a URI conflict.</p>
<p><span id="more-73"></span></p>
<h3>Implementing Nested resources in Rails</h3>
<p>If we decided to add songs to the Music Store application, we could start off by aiming for a URI of:</p>
<p>/songs/124</p>
<p>As you may recall, we can achieve this by declaring this resource in the routes.rb file:</p>
<pre>
map.resources :songs
</pre>
<p>This will give us access to helper methods such as songs_url, song_url (@song) etc. This was discussed in part 5 under ‘Experiment 5.2 Showing the Index Page’.</p>
<p>Next we could aim for a nested URI:</p>
<p>/albums/10/songs/124</p>
<p>To achieve this we use the following construct:</p>
<pre> map.resources :albums do |albums| albums.resources :songs end
</pre>
<p>Note that it is <span style="text-decoration:underline;">albums</span>.resources :songs and not <span style="text-decoration:underline;">map</span>.resources.</p>
<p>With this routing rule, Rails will generate slightly different helper methods. To view these routes we could use the method described in part one. There is also a more convenient rake task: <strong>rake routes</strong>.<br />
<em>This is one of the ‘things’ I have been meaning to mention. You may have read it in a previous comment.</em></p>
<p>If you use ‘rake routes’ you will notice that there are a quite a lot helper methods being generated, more than the 7 I pointed out in part 5. The ‘extra’ methods are there to create URIs for different formats.<em><br />
</em><br />
Below is filtered output from ‘rake routes’</p>
<pre style="border:1px solid black;overflow:auto;width:98%;height:160px;"> album_songs GET /albums/:album_id/songs {:action=&gt;"index", :controller=&gt;"songs"} POST /albums/:album_id/songs {:action=&gt;"create", :controller=&gt;"songs"} new_album_song GET /albums/:album_id/songs/new {:action=&gt;"new", :controller=&gt;"songs"} edit_album_song	GET /albums/:album_id/songs/:id/edit {:action=&gt;"edit", :controller=&gt;"songs"} album_song GET /albums/:album_id/songs/:id {:action=&gt;"show", :controller=&gt;"songs"} PUT /albums/:album_id/songs/:id {:action=&gt;"update", :controller=&gt;"songs"} DELETE /albums/:album_id/songs/:id {:action=&gt;"destroy", :controller=&gt;"songs"}</pre>
<p>As you can see, we now have helper methods which look like album_songs_url and album_song_url(@song). The path versions are also available.</p>
<p>Inside the view we could have:<br />
link_to &#8216;Edit&#8217;, edit_album_song(@album, @song)</p>
<p>Looking at the rake routes output above, we can see that the songs controller can get access to the album ID via params[:album_id]. The song ID can be obtained using params[:id].</p>
<p>Now we have helper methods that generate URIs of the form:</p>
<p>/albums/10/songs/124</p>
<p>Our routing system also knows how to deal with incoming URIs of that form.<br />
Now we would like an implementation that allows us to use URIs like:</p>
<p>/albums/10/songs/5</p>
<p>Where song 5 really is the 5th song in album 10. Therefore we could have:</p>
<p>/albums/10/songs/5<br />
and<br />
/albums/20/songs/5</p>
<p>As with most things, it is easy once you know how. To achieve this we simply need to override the ‘to_param’ method in the song model. I imagine that would look something like this:</p>
<pre>
def to_param
number # number is the track number of this song on the album
end</pre>
<p>After this change we would need to modify the controller as params[:id] would return the song number and not the song id. The controllers would need to use</p>
<p>@song = Song.find_by_number(params[:id])<br />
and not<br />
@song = Song.find(params[:id])</p>
<p>There will be more on this in the follow up text editor post.</p>
<h3>Deep Nesting</h3>
<p>Jamis Buck recommends that resources should never be nested more than one level deep. You can find his original post about that <a rel="nofollow" target="_blank" href="http://weblog.jamisbuck.org/2007/2/5/nesting-resources">here</a>. The Rails community seems to be divided about this ‘rule of thumb’. I recommend that you follow this guideline – although remember it is just a guideline, you can use deeper nesting if the need arises.</p>
<h2>End of Part 6</h2>
<p>This was a quick and short introduction to nested resources. There is a bit more to them, but this enough to start writting Rails applications.</p>
<p>In the follow up, &#8216;plain text editor&#8217;, post we will see a nested route being used a slightly larger application. In that post we will look far more than just routing, that is why I took it out of this part. I will finish that up ASAP. I hope you have enjoyed this post&#8230;</p>
<p>- Thank you, Daryn</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/73/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/73/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/73/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/73/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=73&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Notes from Erlang Exchange</title>
         <link>http://21ccw.blogspot.com/2008/07/notes-from-erlang-exchange.html</link>
         <description>I was at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/&quot;&gt;Erlang Exchange&lt;/a&gt; in London last week, which I really enjoyed. It was really great to see &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/joe-armstrong&quot;&gt;Joe Armstrong&lt;/a&gt;, and to see the faces behind the projects, e.g. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/klacke-wikstrom&quot;&gt;Claes Wikström&lt;/a&gt; (Yaws, Bluetail, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kreditor.se/&quot;&gt;Kreditor&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tail-f.com/&quot;&gt;Tail-f&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/steve-vinoski&quot;&gt;Steve Vinoski&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/eric-merrit-and-martin-logan&quot;&gt;Eric Merrit&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/eric-merrit-and-martin-logan&quot;&gt;Martin Logan&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlware.org/&quot;&gt;Erlware&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/matthias-radestock-and-tony-garnock-jones&quot;&gt;Matthias Radestock&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.lshift.net/&quot;&gt;LShift &lt;/a&gt;&amp;amp; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/mickael-remond&quot;&gt;Mickaël Rémond&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ejabberd.im/&quot;&gt;ejabberd&lt;/a&gt;) etc. etc.&lt;br /&gt;&lt;br /&gt;Something that Joe said reminded me of a comment that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/&quot;&gt;Keith&lt;/a&gt; made about 6 months ago. I think this is something that gets lost in the hype around Erlang and multicore computing:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style:italic;&quot;&gt;Erlang was designed to program fault tolerant systems. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It was not designed to program multicore computers. It was designed 15-20 years ago when multicore-everywhere was not even on the horizon. As a side-effect, it is a good language for multicore systems, since the only way to actually &lt;span style=&quot;font-style:italic;&quot;&gt;achieve&lt;/span&gt; fault tolerance is to have &lt;span style=&quot;font-style:italic;&quot;&gt;independant&lt;/span&gt; processes (read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ml.osdir.com/lang.erlang.general/2003-04/msg00350.html&quot;&gt;here&lt;/a&gt; for some more on this).&lt;br /&gt;&lt;br /&gt;I think it's important for us as to remember to advocate this, and instead of marketing Erlang/OTP as &quot;the application system for multicore&quot;, we should be marketing it as &quot;the application system for fault tolerance&quot;. Oh, and by the way &quot;this is one of the few systems that will actually use those cores that are coming your way&quot;.&lt;br /&gt;&lt;br /&gt;The second point that I have been pondering, was brought on my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/gordon-guthrie&quot;&gt;Gordon Guthrie&lt;/a&gt;'s talk about Erlang/OTP vs Google Apps as an application engine. At this moment, there aren't many application systems to choose from, Erlang/OTP, Google Apps and Amazon EC2 come to mind. In the context of the talk, an Application System (A/S) would be something that takes care of a lot of the non-functional requirements of you system, e.g. reliability, scalability (+distribution) etc.&lt;br /&gt;&lt;br /&gt;For some businesses, using Google Apps or EC2 would be a good fit, but then you're tied into the value chain of that business, and in some instances you just cannot (for legal and other reasons) put your data on servers you don't own. If you go the OTP route you have full control over your application(s), but there's a lot of extra infrastructure that you will have to supply yourself.&lt;br /&gt;&lt;br /&gt;If you start thinking of Erlang/OTP in this way, you realise that the terms should be reversed and it should actually be OTP/Erlang. The platform is actually the important thing. The &lt;span style=&quot;font-style:italic;&quot;&gt;platform&lt;/span&gt; is the thing that gives you the reliability, scalability, distribution and hot code swapping etc. that you require. Erlang becomes this awesome language that you use to build things on the &lt;span style=&quot;font-style:italic;&quot;&gt;platform&lt;/span&gt;. Looking at things from a different perspective can lead to some interesting insights.&lt;br /&gt;&lt;br /&gt;If I'm standing at this vantage point, heated discussions like the recent meme-storm in the blogosphere of &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt;Erlang&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt; vs &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt;Scala&lt;/a&gt;&quot; become much less relevant. Is there a platform that gives you reliability, scalability, distribution, hot code replacement that uses Scala as a language? No? Oh. What a pity...&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-2790488996638110334?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-2790488996638110334</guid>
         <pubDate>Tue, 01 Jul 2008 21:09:00 -0700</pubDate>
      </item>
      <item>
         <title>Programming While Stupid</title>
         <link>http://darynholmes.wordpress.com/2008/06/21/programming-while-stupid/</link>
         <description>Over engineering is a major problem within the software industry. This problem has led to the adoption of ‘lean software development’ &amp;#8211; at least amongst the agile folk. Lean software development is writing code to support the current set of requirements and nothing more. This is not as easy to do as one might think.
As [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=69&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=69</guid>
         <pubDate>Sat, 21 Jun 2008 07:37:23 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>Over engineering is a major problem within the software industry. This problem has led to the adoption of ‘lean software development’ &#8211; <em>at least amongst the agile folk</em>. Lean software development is writing code to support the current set of requirements and nothing more. This is not as easy to do as one might think.</p>
<p>As developers we naturally tend to make assumptions as to what the user, or system, will need. In truth, it is very difficult to accurately predict the future requirements of a system. Coding to meet our assumptions will inevitably lead to over engineering.</p>
<p>We should not let our intuition guide us into false requirements. As strange as it may sound, it takes a concious effort to stop ourselves from doing extra work. We need to adopt a &#8216;lean coding culture&#8217;. We need to constantly remind our selves to stick to lean software development. In agile teams it is common to hear developers reminding each other with certain acronyms and expressions e.g. &#8216;do the simplest thing that works&#8217;.</p>
<p>‘Do the simplest thing that works’ is in-line with lean software development, although it can be misleading. Some people interpret this as &#8216;do the first thing that comes to mind&#8217; e.g. slap on another if statement &#8211; that is a simplistic solution and not a simple solution. If you take a quick and dirty simplistic approach you will end up with a <a rel="nofollow" target="_blank" href="http://www.laputan.org/mud/mud.html#BigBallOfMud">big ball of mud</a>. You need to do the simplest thing that <em>works</em>. The thing that <em>works</em> is something that can be tested, it is something that does not add unnecessary complexity. Therefore the simplest thing that works is not necessarily the quickest and easiest thing to do.</p>
<p><span id="more-69"></span>When talking about lean software development we often refer to KISS (Keep It Simple Stupid). I agree with keeping things simple but I don’t like to be called stupid, <em>the truth hurts</em>. I prefer to use: Keep It Simple and Sensible. This is more positive and the sensible part indicates that we should give some thought to our code. For example, instead of littering your code with conditional statements you could refactor the code to use an established design pattern. Having said that, design patterns are not always a good idea.</p>
<p>You should not implement a design pattern unless there are real signs indicating that you need a smarter solution. It can be detrimental to implement a design pattern for the sake of having one. You are likely to implement the wrong pattern and that code will be a hindrance. Only do what you really <em>need</em> to do. This is also referred to as YAGNI.</p>
<p>YAGNI (You Ain’t Gonna Need It) – This is a term used by Russ Olsen in <a rel="nofollow" target="_blank" href="http://www.rubyinside.com/design-patterns-in-ruby-by-russ-olsen-695.html">Design Patterns in Ruby</a>. In this book, Russ Olsen does a fantastic job of explaining design patterns. He also explains when not to use certain patterns and the problems that come with using each pattern &#8211; <em>After all, software is about trade off&#8217;s.</em></p>
<p>Russ Olsen explains that we should not write code or implement patterns in anticipation of a requirement that might emerge. Firstly that requirement may never surface, and if it does it may have a stipulation which makes the pre-emptive solution void. It is safer to code to meet the current and real requirements of the system. To drive this point home, here is a <em>delightful </em>paragraph from Russ Olsens’ Design Patterns in Ruby:</p>
<p>“Look at it this way: Barring a sharp blow to the head, as you stand here today you are as dumb as you ever will be. We are all learning, getting smarter every day. This is especially true in software projects: You can be sure that you will have a better grasp of the requirements, technology, and design of any software that you work on at the end of the project then at the beginning. Whenever you put in a feature before you really need it, you are guilty of programming while stupid; if you wait until you really do need the thing, you are likely to have a better understanding of what you need to do and how you should go about doing it.”</p>
<p>The moral is: Don&#8217;t be guilty of programming while stupid</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/69/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/69/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/69/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/69/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/69/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/69/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/69/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=69&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Migrating a native Erlang interface to RESTful Mochiweb (with a bit of TDD)</title>
         <link>http://21ccw.blogspot.com/2008/06/migrating-native-erlang-interface-to.html</link>
         <description>The title is a bit of a mouthful, but it does contain in essence what I will show you:&lt;br /&gt;&lt;br /&gt;1. I will convert an existing native erlang &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt; interface (a simple client-server) to use a HTTP layer.&lt;br /&gt;2. The HTTP calls will be &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST&lt;/a&gt;ful.&lt;br /&gt;3. I will be using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/mochiweb/&quot;&gt;Mochiweb&lt;/a&gt;.&lt;br /&gt;4. I will show you how to do a bit of Test-Driven-Development (TDD) for this exercise using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://support.process-one.net/doc/display/CONTRIBS/EUnit&quot;&gt;EUnit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As an introduction, I suggest you read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://steve.vinoski.net/blog/&quot;&gt;Steve Vinoski&lt;/a&gt;'s &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/articles/vinoski-erlang-rest&quot;&gt;RESTful Services with Erlang and Yaws&lt;/a&gt;&quot;, and &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.socklabs.com/2008/04/a_restful_web_service_demo_in/&quot;&gt;A RESTful web service demo in yaws&lt;/a&gt;&quot; by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.socklabs.com/&quot;&gt;Nick Gerakines.&lt;/a&gt; They are both excellent posts, and Nick's post has a lot of interesting details, including some OTP goodness. Also check out &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://darynholmes.wordpress.com/2008/03/15/beginners-tutorial-routing-in-rails-20-with-rest-part-1-of-n/&quot;&gt;Daryn&lt;/a&gt;'s posts for a Rails twist on this topic.&lt;br /&gt;&lt;br /&gt;I will NOT be showing much error handling, simply returning a 501 response if the REST Url has&lt;br /&gt;some mistake in it.&lt;br /&gt;&lt;br /&gt;This is the plan:&lt;br /&gt;1. We will start with a working set of tests for a native CRUD interface. I will &lt;span style=&quot;font-style:italic;&quot;&gt;not&lt;/span&gt; show you the actual implementation, but it is simple enough to do yourself using a process dictionary.&lt;br /&gt;2. I will show a very simple REST interface with Mochiweb, that just returns the request method type as a plaintext string. This will be tested using Inets, the native Erlang OTP internet module.&lt;br /&gt;3. We will write a translators to and from plaintext and native erlang terms (again, unit tested).&lt;br /&gt;4. We will combine all these into the REST interface, tested using Inets again.&lt;br /&gt;&lt;br /&gt;Right, here is the unit tests for the CRUD interface:&lt;pre class=&quot;code&quot;&gt;crud_test_() -&amp;gt; &lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; start() end,&lt;br /&gt; fun(_) -&amp;gt; stop() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(ok == create(#person{id = 1})),&lt;br /&gt; ?_assert(already_exists == create(#person{id=1})),&lt;br /&gt; ?_assert(#person{id=1} == retrieve(1)),&lt;br /&gt; ?_assert(ok == update(#person{id = 1, name=&quot;Ben&quot;})),&lt;br /&gt; ?_assert(#person{id=1, name=&quot;Ben&quot;} == retrieve(1)),&lt;br /&gt; ?_assert(ok == delete(1)),&lt;br /&gt; ?_assert(undefined == delete(2)),&lt;br /&gt; ?_assert(undefined == update(#person{id = 2}))&lt;br /&gt; ]&lt;br /&gt; end}.&lt;/pre&gt;The CRUD interface is container in a module &quot;crud&quot;, and start() and stop() are methods to start and stop the CRUD server. For EUnit, you can define a test with a setup, teardown and tests, and this is the form that I've used here. There are many forms of tests for EUnit, and I suggest you consult the EUnit documentation (contained in the EUnit distribution).&lt;br /&gt;&lt;br /&gt;EUnit automatically creates a test() function on the module when you include &quot;eunit.hrl&quot;, so let's run the crud tests:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;75&amp;gt; crud:test().&lt;br /&gt;All 8 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;We know that are CRUD interface is working OK.&lt;br /&gt;&lt;br /&gt;Onto Step 2! If you're not familiar with Mochiweb, it's a lightweight web server developed by the guys at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mochimedia.com/&quot;&gt;Mochi Media&lt;/a&gt;. It's very easy to integrate into you application, and has very little configuration.&lt;br /&gt;&lt;br /&gt;Here are the tests for the simple Mochiweb demo:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;-define(URL, &quot;http://127.0.0.1:8888&quot;).&lt;br /&gt;&lt;br /&gt;rest_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; inets:start(), start_simple() end,&lt;br /&gt; fun(_) -&amp;gt; inets:stop(), stop_simple() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(http_result('GET') =:= &quot;GET&quot;),&lt;br /&gt; ?_assert(http_result('PUT') =:= &quot;PUT&quot;),&lt;br /&gt; ?_assert(http_result('POST') =:= &quot;POST&quot;),&lt;br /&gt; ?_assert(http_result('DELETE') =:= &quot;DELETE&quot;)&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;br /&gt;parse_result(Result) -&amp;gt;&lt;br /&gt; {ok, {{_Version, 200, _ReasonPhrase}, _Headers, ResultBody}} = Result,&lt;br /&gt; ResultBody.&lt;br /&gt;&lt;br /&gt;rest_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; inets:start(), start_simple() end,&lt;br /&gt; fun(_) -&amp;gt; inets:stop(), stop_simple() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(http_result('GET') =:= &quot;GET&quot;),&lt;br /&gt; ?_assert(http_result('PUT') =:= &quot;PUT&quot;),&lt;br /&gt; ?_assert(http_result('POST') =:= &quot;POST&quot;),&lt;br /&gt; ?_assert(http_result('DELETE') =:= &quot;DELETE&quot;)&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;/pre&gt;start_simple() starts the simple version of the server and stop_simple() stops it. We're just using the base URL, and the server just returns a plain-text string of the request method. The http:request() functions are part of Inets (documentation &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/doc/apps/inets/index.html&quot;&gt;here&lt;/a&gt;). You will notice that the put and post functions have extra parameters (which we will use later for the request body).&lt;br /&gt;&lt;br /&gt;Here's the solution:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;start_simple() -&amp;gt;&lt;br /&gt; mochiweb_http:start(&lt;br /&gt; [{ip, &quot;127.0.0.1&quot;},&lt;br /&gt; {loop, {?MODULE, simple_response}}]).&lt;br /&gt;stop_simple() -&amp;gt;&lt;br /&gt; mochiweb_http:stop().&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;simple_response(Req, Method) -&amp;gt;&lt;br /&gt; Req:ok({&quot;text/plain&quot;, atom_to_list(Method)}).&lt;br /&gt;simple_response(Req) -&amp;gt;&lt;br /&gt; simple_response(Req, Req:get(method)).&lt;br /&gt;&lt;/pre&gt;We've started Mochiweb, and told it that the &quot;simple_response&quot; function in the current module should be used to handle requests. It takes one parameter, which contains the request data. The data can be queried with different methods to extract data from it, e.g. Req:get(method), gives you the method used.&lt;br /&gt;&lt;br /&gt;The Req:ok() function is used to respond to a request, and we simply return plain text (with the text/plain MIME type).&lt;br /&gt;&lt;br /&gt;And let's run the tests:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;77&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 4 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;Nice. The next bit of code we need is to translate Erlang terms to and from plain text. We'll use Base64 encoding for this. Erlang also has very hand term to binary and binary to term functions that we can use to achieve the translation.&lt;br /&gt;&lt;br /&gt;The tests for the translation:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;term_to_plaintext_test_() -&amp;gt;&lt;br /&gt; A = anatom,&lt;br /&gt; B = {a, 23, &quot;abc&quot;},&lt;br /&gt; C = {props, [{a,3},{b,4}]},&lt;br /&gt; [&lt;br /&gt; ?_assert(A == ptt(ttp(A))),&lt;br /&gt; ?_assert(B == ptt(ttp(B))),&lt;br /&gt; ?_assert(C == ptt(ttp(C)))&lt;br /&gt; ].&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &quot;ttp&quot; would be &quot;term_to_plaintext&quot; and &quot;ptt&quot; is&lt;br /&gt;&quot;plaintext_to_term&quot;. Here's the implementation:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;ttp(Term) -&amp;gt;&lt;br /&gt; base64:encode_to_string(term_to_binary(Term)).&lt;br /&gt;&lt;br /&gt;ptt(PlainText) -&amp;gt;&lt;br /&gt; binary_to_term(base64:decode(PlainText)).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the test result:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;77&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 7 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;(7 tests, since we have the first 4 and now the extra 3). Now things are getting a bit more complicated. We now have to ensure that the response to the request is converted from the native Erlang terms to plaintext, this result is then returned, and we also need a function to convert the request result into the native form.&lt;br /&gt;&lt;br /&gt;Here we go:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;result_to_terms(Result) -&amp;gt;&lt;br /&gt; {ok, {{_Version, 200, _ReasonPhrase}, _Headers, ResultBody}} = Result,&lt;br /&gt; ptt(ResultBody).&lt;br /&gt;&lt;br /&gt;rest_api('GET', Path) -&amp;gt;&lt;br /&gt; Result = http:request(get, {?URL ++ Path, []}, [], []),&lt;br /&gt; result_to_terms(Result);&lt;br /&gt;rest_api('DELETE', Path) -&amp;gt;&lt;br /&gt; Result = http:request(delete, {?URL ++ Path, []}, [], []),&lt;br /&gt; result_to_terms(Result).&lt;br /&gt;&lt;br /&gt;rest_api('POST', Path, Data) -&amp;gt;&lt;br /&gt; Result = http:request(post, {?URL ++ Path, [], [], ttp(Data)}, [], []),&lt;br /&gt; result_to_terms(Result);&lt;br /&gt;rest_api('PUT', Path, Data) -&amp;gt;&lt;br /&gt; Result = http:request(put, {?URL ++ Path, [], [], ttp(Data)}, [], []),&lt;br /&gt; result_to_terms(Result).&lt;br /&gt;&lt;br /&gt;crud_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; crud:start(), inets:start(), start() end,&lt;br /&gt; fun(_) -&amp;gt; stop(), inets:stop(), crud:stop() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(ok == rest_api('POST', &quot;/person&quot;, #person{id = 1})),&lt;br /&gt; ?_assert(already_exists == rest_api('POST', &quot;/person&quot;, #person{id = 1})),&lt;br /&gt; ?_assert(#person{id=1} == rest_api('GET', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(ok == rest_api('PUT', &quot;/person/1&quot;, #person{name=&quot;Ben&quot;})),&lt;br /&gt; ?_assert(#person{id=1, name=&quot;Ben&quot;} == rest_api('GET', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(ok == rest_api('DELETE', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(undefined == rest_api('DELETE', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(undefined == rest_api('PUT', &quot;/person/1&quot;, #person{id = 2}))&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;/pre&gt;There is a bit of duplication here, but for illustration I've kept the functions seperate. You will notice that the data is converted to plaintext for the PUT and POST requests. result_to_terms() converts the HTTP result from the plain text to the native Erlang terms.&lt;br /&gt;&lt;br /&gt;You can scroll back to the original CRUD tests, and notice that the tests do exactly the same thing as on the CRUD interface, but we would have to do a &quot;GET&quot; + &quot;/person/1&quot; to get person 1, instead of doing a crud:retrieve(1).&lt;br /&gt;&lt;br /&gt;The mapping between the CRUD and REST method are as follows:&lt;br /&gt;GET &amp;lt;=&amp;gt; RETRIEVE&lt;br /&gt;POST &amp;lt;=&amp;gt; CREATE&lt;br /&gt;PUT &amp;lt;=&amp;gt; UPDATE&lt;br /&gt;DELETE &amp;lt;=&amp;gt;DELETE&lt;br /&gt;&lt;br /&gt;Here's the final product:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;start() -&amp;gt;&lt;br /&gt; mochiweb_http:start(&lt;br /&gt; [{ip, &quot;127.0.0.1&quot;},&lt;br /&gt; {loop, {?MODULE, crud_response}}]).&lt;br /&gt;stop() -&amp;gt;&lt;br /&gt; mochiweb_http:stop().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'GET', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Response = crud:retrieve(Id),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'DELETE', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Response = crud:delete(Id),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'POST', &quot;/person&quot;) -&amp;gt;&lt;br /&gt; Body = Req:recv_body(),&lt;br /&gt; Person = ptt(Body),&lt;br /&gt; Response = crud:create(Person),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'PUT', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Body = Req:recv_body(),&lt;br /&gt; PersonWithNewValues = ptt(Body),&lt;br /&gt; UpdatedPerson = #person{id = Id, &lt;br /&gt; name = PersonWithNewValues#person.name, &lt;br /&gt; email_address = PersonWithNewValues#person.email_address},&lt;br /&gt; Response = crud:update(UpdatedPerson),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt; &lt;br /&gt;crud_response(Req, _Method, Path) -&amp;gt;&lt;br /&gt; Req:respond({501, [], Path}).&lt;br /&gt;&lt;br /&gt;crud_response(Req) -&amp;gt;&lt;br /&gt; crud_response(Req, Req:get(method), Req:get(path)).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once again, there is some duplication, but it's easier to grasp when we split the functions. The GET and DELETE requests are simple to handle, since we just convert the Id string to an integer (which could throw an exception, you would have to handle that in some way), and call the CRUD interface.&lt;br /&gt;&lt;br /&gt;POST is not much more complicated, we just get the body of the request using Req:recv_body().&lt;br /&gt;&lt;br /&gt;The PUT function has a problem. There is duplication of the Id of the person, in both the URL &quot;/person/1&quot;, and the actual term, #person{id=1,...}. I'm not sure how to handle this, comments are welcome. Perhaps you can generate an error response if the Ids don't match. Or you can make sure the posted record does NOT contain an Id field, and return an error if it does.&lt;br /&gt;&lt;br /&gt;The solution as I've given it, uses the fields in the record, and ignores the Id of the record, using the Id in the URL instead.&lt;br /&gt;&lt;br /&gt;The last function generates an error if the request could not be matched.&lt;br /&gt;&lt;br /&gt;And the moment of truth:&lt;pre class=&quot;console&quot;&gt;81&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 15 tests successful.&lt;br /&gt;ok&lt;/pre&gt;Looks so simple now, but I can asure you that it took some effort to get all the tests to pass!&lt;br /&gt;&lt;br /&gt;Well I hope I've shown you something that you didn't know before, or even encouraged you to learn some Erlang. &lt;br /&gt;&lt;br /&gt;Comments and criticisms are most welcome :)&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-8901001959287642946?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-8901001959287642946</guid>
         <pubDate>Mon, 16 Jun 2008 23:07:00 -0700</pubDate>
      </item>
      <item>
         <title>Restful Charts</title>
         <link>http://21ccw.blogspot.com/2008/06/restful-charts.html</link>
         <description>What would you normally expect of a graph-generation library? I'm talking about the pie charts, bar charts etc. You would normally expect an output to some file format, it being PNG or SVG if you're lucky. BUT, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/articles/bass-google-charts-gchartrb;jsessionid=C2188665B07E95A7BDFC4CD39A1C78D3&quot;&gt;gchartrb&lt;/a&gt; doesn't do this, it creates a URL that you would use to GET the graph from the Google charts API.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style:italic;&quot;&gt;So what? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well, it's interesting because it means that &lt;span style=&quot;font-style:italic;&quot;&gt;some&lt;/span&gt; people at least consider that generating the graph using a REST API is as reliable as disk, and as convenient as a local library. I've used Google charts before, but I've never thought about integrating it into another program as a service, and I think it's pretty neat. And &lt;span style=&quot;font-style:italic;&quot;&gt;easy&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I'm placing my chips on REST.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-2111907712393486859?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-2111907712393486859</guid>
         <pubDate>Sun, 08 Jun 2008 07:19:00 -0700</pubDate>
      </item>
      <item>
         <title>Beginners Tutorial: Routing in Rails 2.0 (with REST) – Part 5 of n</title>
         <link>http://darynholmes.wordpress.com/2008/05/26/beginners-tutorial-routing-in-rails-20-with-rest-part-5-of-n/</link>
         <description>Part 6
In part 4 we explored named routes. In this session we move onto Rails&amp;#8217; REST.
Part 5
The Critics
Before we begin you should know that there are many critics of the Rails implementation of REST. There are many reasons for arguments against Rails&amp;#8217; REST e.g. Rails uses server side session state and client side cookies. Some [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=65&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=65</guid>
         <pubDate>Mon, 26 May 2008 07:32:32 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p style="text-align:right;"><strong><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/06/beginners-tutorial-routing-in-rails-20-with-rest-part-6-of-n/"><strong>Part 6</strong></a></strong></p>
<p>In <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/05/11/beginners-tutorial-routing-in-rails-20-with-rest-part-4-of-n/">part 4</a> we explored named routes. In this session we move onto Rails&#8217; REST.</p>
<h2>Part 5</h2>
<h3>The Critics</h3>
<p>Before we begin you should know that there are many critics of the Rails implementation of REST. There are many reasons for arguments against Rails&#8217; REST e.g. Rails uses server side session state and client side cookies. Some people say that this is not REST compliant. Rails&#8217; REST might not be 100% REST compliant, but you can still benefit from using REST in your Rails applications. In <a rel="nofollow" target="_blank" href="http://www.samedaybooks.co.uk/details.php?isbn=9780321445612&amp;s=gb">The Rails Way</a>, <a rel="nofollow" target="_blank" href="http://blog.obiefernandez.com/">Obie Fernandez</a> explains that the benefits from using Rails&#8217; REST fall into two categories:</p>
<ul>
<li>Convenience and automatic best practices for you</li>
<li>A REST interface to your application for the rest of the world</li>
</ul>
<p>Therefore it is worth learning and using Rails&#8217; REST.</p>
<h3>The Standard Introduction</h3>
<p><strong>Re</strong>presentational <strong>S</strong>tate <strong>T</strong>ransfer (REST) is an architectural style. It was first introduced by <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Roy_Fielding">Roy Fielding</a> in his <a rel="nofollow" target="_blank" href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">PhD thesis</a>. Roy Fielding is one of the principal authors of HTTP.</p>
<h3>The Mindset</h3>
<p>When developing a Rails application in the RESTful way it helps to change your mindset. You should not think that you are developing a web site for users accessing the site via a browser. It is better to think of the application as being a service. The service performs actions for clients. These clients may be humans or other machines on the network.</p>
<p>This service will typically be placed on the internet. Therefore we could call it a web service. When I hear the term <em>web service</em> I immediately start thinking about SOAP and all the WS-* specifications. Let&#8217;s be clear, we are not talking about ‘those&#8217; web services. We are talking about RESTful web services. These two technologies provide similar functionality, but RESTful web services are simple and sensible.</p>
<h3>The Terminology</h3>
<p>As previously stated, programming in REST requires a change in the way we think about the system. This naturally leads to a change in the way we talk about the system. The following provides a brief description of some of the key terms used in discussions about REST and HTTP.</p>
<p>A <strong>resource</strong> is one of the key concepts in REST. Many discussions on REST claim that a resource is anything and everything. This is neither true nor helpful. Let&#8217;s examine this concept with the aid of an example.</p>
<p>Let&#8217;s assume that the music store has started selling albums. The database may have the following schema:</p>
<p><a rel="nofollow" target="_blank" href="http://darynholmes.files.wordpress.com/2008/05/orders-erd.png"><img class="alignnone size-full wp-image-66" src="http://darynholmes.files.wordpress.com/2008/05/orders-erd.png?w=450&#038;h=132" alt="orders erd" width="450" height="132"/></a></p>
<p>The data in the database is the raw data. There is data which, given in isolation, is of no real value to a client. For instance it is unlikely that a client will want only one row from the LineItems table. This means that a LineItem (on its own) is not a resource within the context of the music store service.</p>
<p>A client would want all the information pertaining to an order. This would include data from one or more tables. Some data would not be included e.g. database keys. Some information may be added e.g. the total cost of the order might be calculated and included in the ‘order information&#8217;. This ‘order information&#8217; is an example of a resource. <em>Order resource is the type, there will be one order resource instance for each order made</em>.</p>
<p>Each resource must be given a globally unique identifier. This is done using a URI. This could look like this:</p>
<p>http://www.example.com/orders/65</p>
<p>A client, in an admin role, may want a list of all the orders. This collection of orders would be another resource. Following the REST architecture, the orders resource would be assigned the following URL:</p>
<p>http://www.example.com/orders</p>
<p>It is important to note that these resources are not HTML documents. Roy Fielding describes a resource as a conceptual mapping. As a resource is a conceptual entity it can not be used by a client. The service provides the client with a <strong>representation</strong> of the resource.</p>
<p>When the client is a browser, the service typically provides an HTML representation of the resource. If the client is another machine then the service may provide an XML representation of the resource. Other representations could include a PDF file, an image, csv etc. A representation is only supported by the service if it is applicable and required.</p>
<p>Resources are often referred to as <strong>nouns</strong>. This is often done when talking about HTTP to assist learning. The term ‘noun&#8217; is more abstract. For our purposes, resources and ‘nouns&#8217; are synonymous.</p>
<p>HTTP also has the notion of <strong>verbs</strong>. These are the HTTP operations. We are all familiar with the POST and GET operations. In addition to these two operations, HTTP also supports: DELETE and PUT.</p>
<p>There are a few more terms to cover, but we can do that later. The core terms have been explained.</p>
<p><span id="more-65"></span></p>
<h3>Joining The Dots&#8230;</h3>
<p>REST is an architecture style which makes full use of HTTP. Some say that it makes proper use of HTTP.</p>
<p>As previously explained, HTTP supports GET, POST, DELETE and PUT. One of the main ideas behind REST is to use these HTTP operations to determine the correct action to perform. Let&#8217;s clarify this with an example.</p>
<p>If the RESTful music store server receives a URL of: /albums/4 sent with a GET, then the server will invoke the show action of the albums controller. The response may be an HTML page showing details of the 4th album.</p>
<p>If the server receives a URL of: /albums/4 sent with a DELETE, then the server will invoke the destroy action of the albums controller. This will result in the 4th album being deleted.</p>
<p>Note that the URL did not contain explicit ‘show&#8217; or ‘delete&#8217; information. The server was able to infer the action by examining the HTTP operation. Therefore show and delete were implicitly called.</p>
<p>The form of that URL is REST compliant. If the music store had to include Artists and Songs, we could expect to see URLs like this:<br />
/artists/2<br />
/songs/8</p>
<p>As you can see a consistent API is forming, this is the REST API. It becomes intuitive once you start getting familiar with it. For instance I am sure you can tell what would happen if we did a DELETE on this URL:<br />
/songs/154</p>
<p>An application typically performs the full set of CRUD operations &#8211; Create Read Update and Delete. The following table shows the mapping between database CRUD operations, the HTTP verbs, and REST compliant URLs.</p>
<table border="1" cellpadding="5">
<tbody>
<tr>
<th>Database</th>
<th>HTTP Operation</th>
<th>URL Path</th>
</tr>
<tr>
<td>Create</td>
<td>POST</td>
<td>/albums</td>
</tr>
<tr>
<td>Read</td>
<td>GET</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Update</td>
<td>PUT</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Delete</td>
<td>DELETE</td>
<td>/albums/1</td>
</tr>
</tbody>
</table>
<p>When creating a new album, the plural /albums is used. This is because we are adding a one new album to the collection of albums.</p>
<p>In previous posts in this series, creating and editing an album has always involved two controller actions being invoked. When we create an album we:</p>
<ol>
<li>Call the new action to retrieve a form with empty fields</li>
<li>Call the create action which creates a new album extracting the information from that form</li>
</ol>
<p>When doing an update we:</p>
<ol>
<li>Call the edit action to get a form with fields filled in with data from the relevant album</li>
<li>Call the update action which then performs the actual database update</li>
</ol>
<p>This is the typical behaviour of a website. We need to fit this behaviour in with REST. When doing an edit we can&#8217;t obtain the albums details by doing a GET on /album/1 &#8211; that is already used for showing an album.</p>
<p>This functionality is achieved with <strong>modifiers</strong> (also called <strong>adjectives</strong>). The modifiers we need are ‘new&#8217; and ‘edit&#8217;. This results in the following mapping:</p>
<table border="1" cellpadding="5">
<tbody>
<tr>
<th>Database</th>
<th>Controller Action</th>
<th>HTTP Operation</th>
<th>URL path</th>
</tr>
<tr>
<td>Create</td>
<td>create</td>
<td>POST</td>
<td>/albums</td>
</tr>
<tr>
<td>Read</td>
<td>show</td>
<td>GET</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Update</td>
<td>update</td>
<td>PUT</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Delete</td>
<td>destroy</td>
<td>DELETE</td>
<td>/albums/1</td>
</tr>
<tr>
<td>-</td>
<td>new</td>
<td>GET</td>
<td>/albums/new</td>
</tr>
<tr>
<td>Read</td>
<td>edit</td>
<td>GET</td>
<td>/albums/1/edit</td>
</tr>
<tr>
<td>Read</td>
<td>index</td>
<td>GET</td>
<td>/albums</td>
</tr>
</tbody>
</table>
<p>Note the last line which calls the index action.</p>
<p>As you can tell, we are moving towards Rails specific terminology. I guess this means it is time to step into the code&#8230;</p>
<h3>Experiment 5.0 Preparation</h3>
<p>In <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/05/11/beginners-tutorial-routing-in-rails-20-with-rest-part-4-of-n/">part 4</a> we created named routes. The routes.rb file looked like this:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" map.album 'album/:id', :controller =&gt; "albums", :action =&gt; "show" map.edit_album 'albums/:id/edit', :controller =&gt; "albums", :action =&gt; "edit" map.update_album 'albums/:id/update', :controller =&gt; "albums", :action =&gt; "update" map.destroy_album 'albums/:id/destroy', :controller =&gt; "albums", :action =&gt; "destroy" map.new_album 'albums/new', :controller =&gt; "albums", :action =&gt; "new" map.create_album 'albums/create', :controller =&gt; "albums", :action =&gt; "create" #map.connect ':controller/:action/:id' #map.connect ':controller/:action/:id.:format' end
</pre>
<p>In this session we move from named routes to RESTful routing. Therefore we can delete these named routes. Empty the routes.rb file:</p>
<pre>
ActionController::Routing::Routes.draw do |map| #map.connect ':controller/:action/:id' #map.connect ':controller/:action/:id.:format' end
</pre>
<p>Once again we have a broken music store. Let&#8217;s fix it and make it REST compliant.</p>
<h3>Experiment 5.1 Including REST Routes</h3>
<p>We want the music store application to be REST compliant. At the moment we don&#8217;t make use of the HTTP operations, instead we explicitly state the intentions within the URL. At the end of part 4 the site worked like this:</p>
<table border="1" cellpadding="2">
<tbody>
<tr>
<th>Database</th>
<th>Controller Action</th>
<th>HTTP Operation</th>
<th>URL path</th>
</tr>
<tr>
<td>Create</td>
<td>create</td>
<td>POST</td>
<td bgcolor="#cc0000">/albums/create</td>
</tr>
<tr>
<td>Read</td>
<td>show</td>
<td>GET</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Update</td>
<td>Update</td>
<td bgcolor="#cc0000">POST</td>
<td bgcolor="#cc0000">/albums/1/update</td>
</tr>
<tr>
<td>Delete</td>
<td>destroy</td>
<td bgcolor="#cc0000">GET</td>
<td bgcolor="#cc0000">/albums/1/destroy</td>
</tr>
<tr>
<td>-</td>
<td>new</td>
<td>GET</td>
<td>/albums/new</td>
</tr>
<tr>
<td>Read</td>
<td>edit</td>
<td>GET</td>
<td>/albums/1/edit</td>
</tr>
<tr>
<td>Read</td>
<td>index</td>
<td>GET</td>
<td>/albums</td>
</tr>
</tbody>
</table>
<p>The application was fairly similar to REST. This is because the named routes created in part 4 were based on the REST style. To make the application more RESTful we need to make use of the HTTP verbs. We could update each of our named routes to explicitly state the HTTP operation e.g.</p>
<pre> map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index", :method =&gt; "get" </pre>
<p>Rails has made this easier for us. Update the routes.rb file to:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.resources :albums #map.connect ':controller/:action/:id' #map.connect ':controller/:action/:id.:format' end
</pre>
<p>Thanks to this one line, Rails will create a set of named routes &#8211; intelligent named routes. They are intelligent because they examine the request URL as well as the specified HTTP operation. Therefore the same URL can be routed to deferent controller actions.</p>
<p>As you may recall from part 4, when you use named routes Rails dynamically generates routing helper methods. These helper methods are also available on these new &#8216;intelligent&#8217; named routes.</p>
<h3>Experiment 5.2 Showing the Index Page</h3>
<p>Let&#8217;s have a look at the table:</p>
<table border="1" cellpadding="5">
<tbody>
<tr>
<th>Database</th>
<th>Controller Action</th>
<th>HTTP Operation</th>
<th>URL path</th>
</tr>
<tr>
<td>Create</td>
<td>create</td>
<td>POST</td>
<td>/albums</td>
</tr>
<tr>
<td>Read</td>
<td>show</td>
<td>GET</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Update</td>
<td>update</td>
<td>put</td>
<td>/albums/1</td>
</tr>
<tr>
<td>Delete</td>
<td>destroy</td>
<td>DELETE</td>
<td>/albums/1</td>
</tr>
<tr>
<td>-</td>
<td>new</td>
<td>GET</td>
<td>/albums/new</td>
</tr>
<tr>
<td>Read</td>
<td>edit</td>
<td>GET</td>
<td>/albums/1/edit</td>
</tr>
<tr>
<td>Read</td>
<td>index</td>
<td>GET</td>
<td>/albums</td>
</tr>
</tbody>
</table>
<p>To show a list of albums we need to perform a GET with a URL of /albums. We can perform a get by simply typing the URL into the browser and pressing enter. If you try that you should end up with an error.</p>
<p>undefined method `destroy_album_path&#8217; for #</p>
<p>This is good news as we did not get a route not found error. To get the index page up and running we need to replace the named route helper methods we introduced in part 4 with the helper methods created by &#8216;map.resources :albums&#8217;. The following table shows these ‘new&#8217; helper methods.</p>
<table border="1" cellpadding="5">
<tbody>
<tr>
<th>Helper Method</th>
<th>Controller Action</th>
<th>HTTP Operation</th>
<th>URL Path</th>
</tr>
<tr>
<td>albums_url</td>
<td>create</td>
<td>POST</td>
<td>/albums</td>
</tr>
<tr>
<td>album_url(@album)</td>
<td>show</td>
<td>GET</td>
<td>/albums/1</td>
</tr>
<tr>
<td>album_url(@album)</td>
<td>update</td>
<td>put</td>
<td>/albums/1</td>
</tr>
<tr>
<td>album_url(@album)</td>
<td>destroy</td>
<td>DELETE</td>
<td>/albums/1</td>
</tr>
<tr>
<td>new_album_url</td>
<td>new</td>
<td>GET</td>
<td>/albums/new</td>
</tr>
<tr>
<td>edit_album_url</td>
<td>edit</td>
<td>GET</td>
<td>/albums/1/edit</td>
</tr>
<tr>
<td>albums_url</td>
<td>index</td>
<td>GET</td>
<td>/albums</td>
</tr>
</tbody>
</table>
<p>This table shows methods ending with _url, the _path versions also exist. This was explained in part 4. By making use of these helper methods we can update the index.html.erb.</p>
<p>Thanks to our foresight in part 4, we only need to change the call to delete, from:</p>
<p>link_to &#8216;Destroy&#8217;, destroy_album_path(album.id), :confirm =&gt; &#8216;Are you sure?</p>
<p>To</p>
<p>link_to &#8216;Destroy&#8217;, album_path(album), :confirm =&gt; &#8216;Are you sure?&#8217;, :method =&gt; :delete</p>
<p>Just to be clear, the index.html.erb should look like this:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Title&lt;/th&gt;
&lt;th&gt;Review&lt;/th&gt;
&lt;/tr&gt;
&lt;% for album in @albums %&gt;
&lt;tr&gt;
&lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Show', album_path(album) %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Edit', edit_album_path(album) %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Destroy', album_path(album), :confirm =&gt; 'Are you sure?', :method =&gt; :delete %&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;% end %&gt;&lt;/table&gt;
&lt;%= link_to 'New album', new_album_path %&gt;
</pre>
<p>A URL of /albums should show the index page &#8211; test it if you like.</p>
<p><em><span style="color:#ff0000;">Alert!</span></em><br />
Link_to obtains the URL by making use of another Rails method called ‘url_for&#8217;. The following quote is from the Rails documentation and it refers to the parameters being passed into url_for.</p>
<p>&#8220;If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter, you‘ll trigger the named route for that record. The lookup will happen on the name of the class. So passing a Workshop object will attempt to use the workshop_path route&#8221;</p>
<p>This means that we can replace<br />
link_to &#8216;Show&#8217;, album_path(album)<br />
with<br />
link_to &#8216;Show&#8217;, album</p>
<p>And<br />
link_to &#8216;Destroy&#8217;, album_path(album), :confirm =&gt; &#8216;Are you sure?&#8217;, :method =&gt; :delete<br />
with<br />
link_to &#8216;Destroy&#8217;, album, :confirm =&gt; &#8216;Are you sure?&#8217;, :method =&gt; :delete</p>
<p>I am sure this bit of Rails magic has been the cause of much confusion.<br />
This magic is also used in other methods e.g. redirect_to, form_for etc.</p>
<p>The index.html.erb can now look like this:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Title&lt;/th&gt;
&lt;th&gt;Review&lt;/th&gt;
&lt;/tr&gt;
&lt;% for album in @albums %&gt;
&lt;tr&gt;
&lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Show', album %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Edit', edit_album_path(album) %&gt;&lt;/td&gt;
&lt;td&gt;&lt;%= link_to 'Destroy', album, :confirm =&gt; 'Are you sure?', :method =&gt; :delete %&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;% end %&gt;&lt;/table&gt;
&lt;%= link_to 'New album', new_album_path %&gt; </pre>
<p>A URL of /albums should now render the index page.</p>
<h3>Experiment 5.3 The RESTful Show</h3>
<p>Thanks to the naming convention we used in part 4, we do not need to do anything to make show work. Show.html.erb remains like this:</p>
<pre> &lt;b&gt;Title:&lt;/b&gt; &lt;%=h @album.title %&gt; &lt;b&gt;Review:&lt;/b&gt; &lt;%=h @album.review %&gt; &lt;%= link_to 'Edit', edit_album_path(@album) %&gt; |
&lt;%= link_to 'Back', albums_path %&gt; </pre>
<h3>Experiment 5.4 Edit RESTfully</h3>
<p>To fix update we need to make use of the following methods in the edit view.</p>
<table border="1" cellpadding="5">
<tbody>
<tr>
<th>Helper Method</th>
<th>Controller Action</th>
<th>HTTP Operation</th>
<th>URL Path</th>
</tr>
<tr>
<td>album_url(@album)</td>
<td>update</td>
<td>put</td>
<td>/albums/1</td>
</tr>
<tr>
<td>edit_album_url</td>
<td>edit</td>
<td>GET</td>
<td>/albums/1/edit</td>
</tr>
</tbody>
</table>
<p>The form_for allows us to use more syntactic sugar.</p>
<p>We could use:<br />
form_for (@album), :url =&gt; album_path(@album)</p>
<p>Or we could use:<br />
form_for (@album)</p>
<p>This means the edit.html.erb should look like this:</p>
<pre>
&lt;h1&gt;Editing album&lt;/h1&gt;
&lt;%= error_messages_for :album %&gt; &lt;% form_for (@album) do |f| %&gt; &lt;b&gt;Title&lt;/b&gt; &lt;%= f.text_field :title %&gt; &lt;b&gt;Review&lt;/b&gt; &lt;%= f.text_area :review %&gt; &lt;%= f.submit "Update" %&gt; &lt;% end %&gt; &lt;%= link_to 'Show', @album %&gt; |
&lt;%= link_to 'Back', albums_path %&gt;
</pre>
<h3>Experiment 5.5 Putting Delete to REST</h3>
<p>This was fixed when we modified the index.html.erb.</p>
<p>The line was:</p>
<p>link_to &#8216;Destroy&#8217;, album, :confirm =&gt; &#8216;Are you sure?&#8217;, :method =&gt; :delete</p>
<h3>Experiment 5.6 A RESTful Addition</h3>
<p>In order to restore the ‘new’ functionality, make new.html.erb look like this:</p>
<pre>
&lt;h1&gt;New album&lt;/h1&gt;
&lt;%= error_messages_for :album %&gt; &lt;% form_for (@album) do |f| %&gt; &lt;b&gt;Title&lt;/b&gt; &lt;%= f.text_field :title %&gt; &lt;b&gt;Review&lt;/b&gt; &lt;%= f.text_area :review %&gt; &lt;%= f.submit "Create" %&gt; &lt;% end %&gt; &lt;%= link_to 'Back', albums_path %&gt;
</pre>
<h3>Experiment 5.7 Updating the Controller to use the Syntactic Sugar</h3>
<p>When using a resource the controller must implement these specific methods:<br />
index, show, new, edit, create, update, destroy.<br />
Our controller already meets this condition.</p>
<p>Although the music store is fully operational, we can make some minor modifications in the controller. This is just to leave the controller in the way Rails generated it in part 1. These changes are in the create and update actions e.g. redirect_to(@album)</p>
<p>The controller should look as follows:</p>
<pre> class AlbumsController &lt; ApplicationController # GET /albums # GET /albums.xml def index @albums = Album.find(:all) @cont = "The controller is:" + params[:controller] respond_to do |format| format.html # index.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @albums } end end # GET /albums/1 # GET /albums/1.xml def show @album = Album.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album } end end # GET /albums/new # GET /albums/new.xml def new @album = Album.new respond_to do |format| format.html # new.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album } end end # GET /albums/1/edit def edit @album = Album.find(params[:id]) end # POST /albums # POST /albums.xml def create @album = Album.new(params[:album]) respond_to do |format| if @album.save flash[:notice] = 'Album was successfully created.' format.html { redirect_to(@album) } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album, :status =&gt; :created, :location =&gt; @album } else format.html { render :action =&gt; "new" } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album.errors, :status =&gt; :unprocessable_entity } end end end # PUT /albums/1 # PUT /albums/1.xml def update @album = Album.find(params[:id]) respond_to do |format| if @album.update_attributes(params[:album]) flash[:notice] = 'Album was successfully updated.' format.html { redirect_to(@album) } format.xml { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'/> k } else format.html { render :action =&gt; "edit" } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album.errors, :status =&gt; :unprocessable_entity } end end end # DELETE /albums/1 # DELETE /albums/1.xml def destroy @album = Album.find(params[:id]) @album.destroy respond_to do |format| format.html { redirect_to(albums_url) } format.xml { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'/> k } end end
end
</pre>
<p>And that is that – our music store is exactly how it was when we generated it in part 1.</p>
<h3>End of Part 5</h3>
<p>To keep things ‘simple’ I have been skipping over certain aspects of routing. I will draft one more post in this series where I will mention some of these topics. Some of the readers have asked questions, I will still answer those questions but they won’t form part of this tutorial.</p>
<p>That concludes part 5. Hopefully you have a better understanding of what is going on under the hood.</p>
<p>Thank you, Daryn</p>
<p style="text-align:right;"><strong><strong><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/07/06/beginners-tutorial-routing-in-rails-20-with-rest-part-6-of-n/"><strong>Part 6</strong></a></strong></strong></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/65/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/65/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/65/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/65/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/65/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/65/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/65/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=65&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
         <media:content url="http://darynholmes.files.wordpress.com/2008/05/orders-erd.png" medium="image">
            <media:title>orders erd</media:title>
         </media:content>
      </item>
      <item>
         <title>Beginners Tutorial: Routing in Rails 2.0 (with REST) – Part 4 of n</title>
         <link>http://darynholmes.wordpress.com/2008/05/11/beginners-tutorial-routing-in-rails-20-with-rest-part-4-of-n/</link>
         <description>Part 5
The routes we have discussed so far are known as simple routes. I have been referring to them as custom routes, but ‘simple routes’ is the correct term. The default route we discussed in part 3 is also a simple route. The aim is to move onto RESTful routes, sometimes called resource routes. RESTful [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&amp;blog=2505811&amp;post=64&amp;subd=darynholmes&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://darynholmes.wordpress.com/?p=64</guid>
         <pubDate>Sun, 11 May 2008 14:26:03 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p style="text-align:right;"><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/05/26/beginners-tutorial-routing-in-rails-20-with-rest-part-5-of-n/"><strong>Part 5</strong></a></p>
<p>The routes we have discussed so far are known as <strong>simple routes</strong>. I have been referring to them as custom routes, but ‘simple routes’ is the correct term. The <strong>default route</strong> we discussed in <a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/04/27/beginners-tutorial-routing-in-rails-20-with-rest-part-3-of-n/">part 3</a> is also a simple route. The aim is to move onto <strong>RESTful routes</strong>, sometimes called resource routes. RESTful routes are built on top of <strong>named routes</strong>. Therefore we must first cover named routes, and that is what part 4 is all about.</p>
<h2>Part 4</h2>
<h3>Introduction</h3>
<p>Referring back to part 1, the routing system has two main functions:<br />
Interpreting a request URL<br />
Generating a request URL</p>
<p>We had a detailed look at route generation and interpretation in part 2, but let’s have another quick look at it. Let’s assume, for some insane reason, that we defined the following route in the music_store routes.rb file:</p>
<p>map.connect &#8216;apples/bananas/:id&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;show&#8221;</p>
<p>link_to would use this rule to generate a URL, this can be seen in the following line extracted from index.html.erb:</p>
<p>link_to &#8216;Show&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;show&#8221;, :id =&gt; album.id</p>
<p>This could generate a URL of: http://localhost:3000/apples/bananas/7<br />
And when given this request, Rails would handle it correctly e.g. the show action will be called on the albums controller and the show view will be sent as the response to the browser.</p>
<p>Coming back to the real world, we are more likely to define the routing rule like this:<br />
map.connect &#8216;albums/show/:id&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;show&#8221;</p>
<p>link_to (and friends) would then generate a URL like this:<br />
http://localhost:3000/albums/show/7.</p>
<p>To show the index (the listing of the albums) we could define a rule like this:<br />
map.connect &#8216;albums/index&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;</p>
<p>The matching link_to in edit.html.erb is:<br />
link_to &#8216;Back&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;</p>
<p>Looking at the last example, there is some repetition. Both lines contain:<br />
:controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;</p>
<p>The link_to method needs this (controller, action) information to obtain the URL. If we had the URL stored as some global variable, or method, then we could simply pass that into link_to. link_to could use this ‘literal’ URL without needing to generate one.<br />
This could look something like: link_to &#8216;Back&#8217;, albums_index_url<br />
This is one of the main ideas behind named routes.</p>
<p><span id="more-64"></span></p>
<h3>Named Routes</h3>
<p>Named routes provide a way to ‘clean up’ code, specifically the code within link_to and other similar functions. When a named route is defined, new helper methods are dynamically generated. These helper methods provide a simplified way of obtaining the required request URL. The names of these helper methods are based on the name of the route. Let’s clarify this by coding.</p>
<h3>Experiment 4.0 Preparation</h3>
<p>At the end of part 3 the routes.rb had the default route in it:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.connect ':controller/:action/:id' end
</pre>
<p>It is common to accompany the default route with this:<br />
map.connect &#8216;:controller/:action/:id.:format&#8217;<br />
We can think of this as a default route which allows clients to request a different format for the response. :format was discussed in part 1, under the title of Experimenting 1 &#8211; View the generated routes.</p>
<p>To prepare for this session, we want to remove all the routes and completely break the site. Therefore you should make your routes.rb look like this:</p>
<pre>
ActionController::Routing::Routes.draw do |map| # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end
</pre>
<p>Now the site is good for two things, serving up routing errors and learning about named routes…</p>
<h3>Experiment 4.1 Adding a Named Route for the Albums Index</h3>
<p>In part 2 we defined a route which invoked the index action on the albums controller. That route looked like this: map.connect &#8216;music&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;</p>
<p>To follow Rails convention, we should write it like this:<br />
map.connect &#8216;albums&#8217;, :controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;</p>
<p>Making it more readable we could write it like this:<br />
map.connect &#8216;albums&#8217;,<br />
:controller =&gt; &#8220;albums&#8221;,<br />
:action =&gt; &#8220;index&#8221;</p>
<p>The pattern string is ‘albums’, therefore a URL of /albums would match.</p>
<p>In order to name this route, we need to decide what to name or call it. A top down approach is recommended for this. We want to show a list of albums, so it seems reasonable to call the route ‘<strong>albums</strong>’.</p>
<p>To name the route, we make a small change to our route definition. We change the route definition from:</p>
<p>map.connect &#8216;albums&#8217;,<br />
:controller =&gt; &#8220;albums&#8221;,<br />
:action =&gt; &#8220;index&#8221;</p>
<p>To:</p>
<p>map.albums &#8216;albums&#8217;,<br />
:controller =&gt; &#8220;albums&#8221;,<br />
:action =&gt; &#8220;index&#8221;</p>
<p>All we had to do is change map.<strong>connect</strong> to map.<strong>albums</strong>. Modify your routes.rb file to look like this:</p>
<pre> ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end
</pre>
<p>Once this file is saved, you will have created a named route. We are still missing most of the routes our site requires therefore we can’t run the site just yet. Let’s simplify the index page. Make the index.html.erb look like this:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt;
</pre>
<p>Now you should be able to see the simplified index page. Next we will take a look at the methods that Rails generates when using named routes.</p>
<h3>Experiment 4.2 Exploring the ‘Named Route’ Generated Methods</h3>
<p>When a named route is defined, Rails will dynamically generate two methods, these are:<br />
name_url and name_path (where name is the name of the route). name_url will return the fully qualified URL, name_path returns the relative path – it does not include the protocol and host.</p>
<p>In our case, we have a route named albums. When we run the site, rails will generate albums_url and albums_path. Let’s make the view display these values, change the index.html.erb to this:<br />
<em>I had to use different formatting to stop WordPress from getting up to its shenanigans&#8230; </em></p>
<pre>&lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt;
albums_url: &lt;%= albums_url %&gt;
&lt;br /&gt;
albums_path: &lt;%= albums_path %&gt;</pre>
<p>Brows to http://localhost:3000/albums and you should see:<br />
albums_url: http://localhost:3000/albums<br />
albums_path: /albums</p>
<p>Now that we have seen the output of these methods, you can now remove those last three lines.</p>
<p>Academically speaking it is probably more correct to use name_url but name_path also works in most cases. The Rails way is to use name_path if you can. These methods are available in the views and controllers.</p>
<h3>Experiment 4.3 Defining a Named Route for Show</h3>
<p>Showing the index is fairly straight forward as it is basically a static URL. Now we look at defining a named route for show. Show needs to pass through the ID of the specific album. When defining a simple route, we could use:</p>
<p>map.connect &#8216;album/:id&#8217;,<br />
:controller =&gt; &#8220;albums&#8221;,<br />
:action =&gt; &#8220;show&#8221;</p>
<p>Once again, we can convert this into a named route by replacing connect with the name of the route. Let’s name the route ‘album’. Update the routes.rb to look as follows:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" map.album 'album/:id', :controller =&gt; "albums", :action =&gt; "show" # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end
</pre>
<p>Rails realises that it needs a value for :id, therefore the helper methods accept a parameter to be assigned to it. Therefore link_to can use album_url(3). This will hard code 3, but it illustrates the point.</p>
<p>In the code we are likely to use:<br />
link_to &#8216;Show&#8217;, album_path(album.id)<br />
Thanks to some syntactic sugar we can also use:<br />
link_to &#8216;Show&#8217;, album_path(album)</p>
<p>Let’s get the ‘show’ functionality working again. Update index.erb.html to look like this:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Show', album_path(album) %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt;
</pre>
<p>And update show.erb.html to:</p>
<pre>
&lt;p&gt; &lt;b&gt;Title:&lt;/b&gt; &lt;%=h @album.title %&gt;
&lt;/p&gt; &lt;p&gt; &lt;b&gt;Review:&lt;/b&gt; &lt;%=h @album.review %&gt;
&lt;/p&gt; &lt;%= link_to 'Back', albums_path %&gt;
</pre>
<p>We have removed the link to ‘edit’, we will replace it later.</p>
<p>At this stage the site should be able:</p>
<ul>
<li>to show the list of albums in the index page</li>
<li>show a single album</li>
</ul>
<h3>Experiment 4.4 Defining a Named Route for Edit</h3>
<p>Now lets fix the edit functionality. Update routes.rb to look like this:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" map.album 'album/:id', :controller =&gt; "albums", :action =&gt; "show" map.edit_album 'albums/:id/edit', :controller =&gt; "albums", :action =&gt; "edit" map.update_album 'albums/:id/update', :controller =&gt; "albums", :action =&gt; "update" # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end </pre>
<p>You may have noticed that I am using slightly different pattern strings to what we have been using. The pattern strings (and URLs) that I am using now are fairly close to those used in REST. Therefore we are already getting familiar with the RESTful interface.</p>
<p>Update the index.erb.html to:</p>
<pre> &lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Show', album_path(album) %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Edit', edit_album_path(album) %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt; </pre>
<p>Edit.erb.html should look like this:</p>
<pre>
&lt;h1&gt;Editing album&lt;/h1&gt; &lt;%= error_messages_for :album %&gt; &lt;% form_for (@album), :url =&gt; update_album_path(@album) do |f| %&gt; &lt;p&gt; &lt;b&gt;Title&lt;/b&gt;&lt;br /&gt; &lt;%= f.text_field :title %&gt; &lt;/p&gt; &lt;p&gt; &lt;b&gt;Review&lt;/b&gt;&lt;br /&gt; &lt;%= f.text_area :review %&gt; &lt;/p&gt; &lt;p&gt; &lt;%= f.submit "Update" %&gt; &lt;/p&gt;
&lt;% end %&gt; &lt;%= link_to 'Show', album_path(@album) %&gt; |
&lt;%= link_to 'Back', albums_path %&gt;
</pre>
<p>Add the edit link back to show.erb.html</p>
<pre> &lt;p&gt; &lt;b&gt;Title:&lt;/b&gt; &lt;%=h @album.title %&gt;
&lt;/p&gt; &lt;p&gt; &lt;b&gt;Review:&lt;/b&gt; &lt;%=h @album.review %&gt;
&lt;/p&gt; &lt;%= link_to 'Edit', edit_album_path(@album) %&gt; |
&lt;%= link_to 'Back', albums_path %&gt;
</pre>
<p>At this stage the site should be able:</p>
<ul>
<li>to show the list of albums in the index page</li>
<li>show a single album</li>
<li>Edit an existing album</li>
</ul>
<h3>Experiment 4.5 Defining a Named Route for Destroy</h3>
<p>Update the routes.rb to this:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" map.album 'album/:id', :controller =&gt; "albums", :action =&gt; "show" map.edit_album 'albums/:id/edit', :controller =&gt; "albums", :action =&gt; "edit" map.update_album 'albums/:id/update', :controller =&gt; "albums", :action =&gt; "update" map.destroy_album 'albums/:id/destroy', :controller =&gt; "albums", :action =&gt; "destroy" # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end
</pre>
<p>The index.erb.html should look like this:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Show', album_path(album) %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Edit', edit_album_path(album) %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Destroy', destroy_album_path(album.id), :confirm =&gt; 'Are you sure?' %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt;
</pre>
<p>I am sure that you are getting a feel for named routes now…</p>
<p>At this stage the site should be able:</p>
<ul>
<li>to show the list of albums in the index page</li>
<li>show a single album</li>
<li>Edit an existing album</li>
<li>Delete an album</li>
</ul>
<h3>Experiment 4.6 Defining a Named Route for New</h3>
<p>Change the routes.rb file to this:</p>
<pre>
ActionController::Routing::Routes.draw do |map| map.albums 'albums', :controller =&gt; "albums", :action =&gt; "index" map.album 'album/:id', :controller =&gt; "albums", :action =&gt; "show" map.edit_album 'albums/:id/edit', :controller =&gt; "albums", :action =&gt; "edit" map.update_album 'albums/:id/update', :controller =&gt; "albums", :action =&gt; "update" map.destroy_album 'albums/:id/destroy', :controller =&gt; "albums", :action =&gt; "destroy" map.new_album 'albums/new', :controller =&gt; "albums", :action =&gt; "new" map.create_album 'albums/create', :controller =&gt; "albums", :action =&gt; "create" # map.connect ':controller/:action/:id' # map.connect ':controller/:action/:id.:format' end
</pre>
<p>The index.erb.html should now be:</p>
<pre>
&lt;h1&gt;Listing albums&lt;/h1&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Review&lt;/th&gt; &lt;/tr&gt; &lt;% for album in @albums %&gt; &lt;tr&gt; &lt;td&gt;&lt;%=h album.title %&gt;&lt;/td&gt; &lt;td&gt;&lt;%=h album.review %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Show', album_path(album) %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Edit', edit_album_path(album) %&gt;&lt;/td&gt; &lt;td&gt;&lt;%= link_to 'Destroy', destroy_album_path(album.id), :confirm =&gt; 'Are you sure?' %&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;
&lt;br /&gt;&lt;%= link_to 'New album', new_album_path %&gt;
</pre>
<p><em>To stop WordPress from deleting my code, I put link_to &#8216;New album&#8217; on the same line as the br tag. They are on separate lines in my actual code.</em></p>
<p>With new.erb.html looking like this:</p>
<pre> &lt;h1&gt;New album&lt;/h1&gt; &lt;%= error_messages_for :album %&gt; &lt;% form_for :album, @album, :url =&gt; create_album_path do |f| %&gt; &lt;p&gt; &lt;b&gt;Title&lt;/b&gt;&lt;br /&gt; &lt;%= f.text_field :title %&gt; &lt;/p&gt; &lt;p&gt; &lt;b&gt;Review&lt;/b&gt;&lt;br /&gt; &lt;%= f.text_area :review %&gt; &lt;/p&gt; &lt;p&gt; &lt;%= f.submit "Create" %&gt; &lt;/p&gt;
&lt;% end %&gt; &lt;%= link_to 'Back', albums_path %&gt;
</pre>
<p>At this stage the site should be able:</p>
<ul>
<li>to show the list of albums in the index page</li>
<li>show a single album</li>
<li>Edit an existing album</li>
<li>Add a new album</li>
</ul>
<p>Are we done? What about the controller?</p>
<h3>Experiment 4.7 Using Named Route Helper Methods in the Controller</h3>
<p>Open the controller and look at the destroy action, you will notice this line:</p>
<p>format.html { redirect_to(:controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;) }</p>
<p>This shows you that we can still generate routes as if we were using the simple routes. We have defined named routes, we can use the helper methods in the controller, so we might as well.</p>
<p>Make the controller look like this:</p>
<pre>
class AlbumsController &lt; ApplicationController # GET /albums # GET /albums.xml def index @albums = Album.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @albums } end end # GET /albums/1 # GET /albums/1.xml def show @album = Album.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album } end end # GET /albums/new # GET /albums/new.xml def new @album = Album.new respond_to do |format| format.html # new.html.erb format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album } end end # GET /albums/1/edit def edit @album = Album.find(params[:id]) end # POST /albums # POST /albums.xml def create @album = Album.new(params[:album]) respond_to do |format| if @album.save flash[:notice] = 'Album was successfully created.' format.html { redirect_to(album_path(@album)) } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album, :status =&gt; :created, :location =&gt; @album } else format.html { render :action =&gt; "new" } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album.errors, :status =&gt; :unprocessable_entity } end end end # PUT /albums/1 # PUT /albums/1.xml def update @album = Album.find(params[:id]) respond_to do |format| if @album.update_attributes(params[:album]) flash[:notice] = 'Album was successfully updated.' format.html { redirect_to(album_path(@album)) } format.xml { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'/> k } else format.html { render :action =&gt; "edit" } format.xml { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley'/> ml =&gt; @album.errors, :status =&gt; :unprocessable_entity } end end end # DELETE /albums/1 # DELETE /albums/1.xml def destroy @album = Album.find(params[:id]) @album.destroy respond_to do |format| format.html { redirect_to(albums_path) } format.xml { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'/> k } end end
end
</pre>
<p>Sure we have a larger routes.rb file, but I am sure you will agree that redirect_to(albums_path)</p>
<p>is much better than redirect_to(:controller =&gt; &#8220;albums&#8221;, :action =&gt; &#8220;index&#8221;)</p>
<h2>The End of Part 4</h2>
<p>I hope this has helped you to get familiar with named routes. There is a lot more to them, and there is also a lot more syntactic sugar. Once I have completed the section on RESTful routing, I might do a summary post. This would be a recap and it will show some tips and tricks that I skipped over in these posts. I am skipping certain topics as I would like to get onto RESTful routing as soon as possible.</p>
<p>Speaking of RESTful routing, the way we have named the routes is very close to the RESTful way. You will see this in the next post.</p>
<p>It is very easy to make mistakes when writing a tutorial like this. Especially with the gremlins inside of the WordPress formatting engine. If you are one of the first to complete this session successfully then please inform me. More importantly, if you find a problem please let me know.</p>
<p>Thank you, Daryn</p>
<p style="text-align:right;"><strong><a rel="nofollow" target="_blank" href="http://darynholmes.wordpress.com/2008/05/26/beginners-tutorial-routing-in-rails-20-with-rest-part-5-of-n/"><strong>Part 5</strong></a></strong></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/darynholmes.wordpress.com/64/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/darynholmes.wordpress.com/64/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/darynholmes.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/darynholmes.wordpress.com/64/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/darynholmes.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/darynholmes.wordpress.com/64/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/darynholmes.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/darynholmes.wordpress.com/64/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/darynholmes.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/darynholmes.wordpress.com/64/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/darynholmes.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/darynholmes.wordpress.com/64/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=darynholmes.wordpress.com&blog=2505811&post=64&subd=darynholmes&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://1.gravatar.com/avatar/be1f59e4118912d487c5330586f39b72?s=96&amp;amp;d=identicon" medium="image">
            <media:title>Daryn</media:title>
         </media:content>
      </item>
      <item>
         <title>Parallel Quicksort in Erlang - Part II</title>
         <link>http://21ccw.blogspot.com/2008/05/parallel-quicksort-in-erlang-part-ii.html</link>
         <description>In my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2008/04/parallel-quicksort-in-erlang.html&quot;&gt;previous post&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaksa.wordpress.com/&quot;&gt;Jaksa&lt;/a&gt; pointed out that there's a problem, in that although there may be multiple processes, they will be blocked and waiting (sequencially) for the first peval to complete, then the second peval, etc. Which will result in a pseudo-parallel depth-first quicksort, instead of a breadth-first quicksort. This is the offending line:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;peval(fun pqsort/1, Left) ++ [Pivot] ++ peval(fun pqsort/1, Right).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I was hoping Erlang would be clever enough to execute the two functions in parallel, but that's a fairly unreasonable (and completely incorrect) assumption! &lt;br /&gt;&lt;br /&gt;But how to fix it? There is a parallel implementation of the map function in &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/dp/193435600X?tag=21scencodwor-20&amp;camp=14573&amp;creative=327641&amp;linkCode=as1&amp;creativeASIN=193435600X&amp;adid=0S65GZ2QK77VXZX40RD5&amp;&quot;&gt;Joe's book&lt;/a&gt;, and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://montsamu.blogspot.com/2007/02/erlang-parallel-map-and-parallel.html&quot;&gt;Montsamu&lt;/a&gt; has a variation of it on his blog:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;-module(plists).&lt;br /&gt;-export([pmap/2]).&lt;br /&gt;&lt;br /&gt;pmap(F, L) -&amp;gt;&lt;br /&gt; S = self(),&lt;br /&gt; Pids = lists:map(fun(I) -&amp;gt; spawn(fun() -&amp;gt; pmap_f(S, F, I) end) end, L),&lt;br /&gt; pmap_gather(Pids).&lt;br /&gt;&lt;br /&gt;pmap_gather([H|T]) -&amp;gt;&lt;br /&gt; receive&lt;br /&gt; {H, Ret} -&amp;gt; [Ret|pmap_gather(T)]&lt;br /&gt; end;&lt;br /&gt;pmap_gather([]) -&amp;gt;&lt;br /&gt; [].&lt;br /&gt;&lt;br /&gt;pmap_f(Parent, F, I) -&amp;gt;&lt;br /&gt; Parent ! {self(), (catch F(I))}.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The pmap_gather function is the interesting one. It will traverse the list of Pids, and wait for each to send back its result. Using pmap, we update pqsort as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;pqsort([]) -&amp;gt; [];&lt;br /&gt;pqsort([Pivot]) -&amp;gt; [Pivot];&lt;br /&gt;pqsort([Pivot|Rest]) -&amp;gt;&lt;br /&gt; io:format(&quot;+&quot;, []),&lt;br /&gt; Left = [X || X &amp;lt;- Rest, X &amp;lt; Pivot],&lt;br /&gt; Right = [Y || Y &amp;lt;- Rest, Y &amp;gt;= Pivot],&lt;br /&gt; [SortedLeft, SortedRight] = plists:pmap(fun pqsort/1, [Left, Right]),&lt;br /&gt; io:format(&quot;-&quot;, []),&lt;br /&gt; SortedLeft ++ [Pivot] ++ SortedRight.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And with a perfectly unbalanced (for quicksort) list to sort, we expect 1 process, then 3 as the first spawns 2 new ones, then down again to zero:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;(emacs@21ccw.blogspot.com)47&amp;gt; pqsort:pqsort([4,2,1,3,6,5,7]).&lt;br /&gt;+++---[1,2,3,4,5,6,7]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For the same example we had last time, sorting 100 random numbers, the number of concurrent process graph during execution looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SCGdnRJGWeI/AAAAAAAAAHM/3_fhZemNZPs/s1600-h/pqsort.png&quot;&gt;&lt;img style=&quot;display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;&quot; src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SCGdnRJGWeI/AAAAAAAAAHM/3_fhZemNZPs/s400/pqsort.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5197608742904289762&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Much better!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-6668255548224137560?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-6668255548224137560</guid>
         <pubDate>Tue, 06 May 2008 22:14:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_bXDgUoT7V7o/SCGdnRJGWeI/AAAAAAAAAHM/3_fhZemNZPs/s72-c/pqsort.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Parallel Quicksort in Erlang</title>
         <link>http://21ccw.blogspot.com/2008/04/parallel-quicksort-in-erlang.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaksa.wordpress.com/2008/04/22/graph-algorithms-with-forkjoin/&quot;&gt;Jaksa&lt;/a&gt; is doing some posts on parallel graph algorithm in Java using fork/join, and he mentions &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Quicksort&quot;&gt;quicksort&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;i&gt; &quot;The equivalent of the hello world for parallel languages is the quicksort algorithm&quot;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Now I'm tempted to say something like &quot;Oh yea? You know how many lines of code quicksort is in Erlang? 3!&quot; Yes &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Erlang_(programming_language)&quot;&gt;really&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;qsort([]) -&amp;gt; [];&lt;br /&gt;qsort([Pivot|Rest]) -&amp;gt;&lt;br /&gt; qsort([ X || X &amp;lt;- Rest, X &amp;lt; Pivot]) ++ [Pivot] ++ qsort([ Y || Y &amp;lt;- Rest, Y &amp;gt;= Pivot]).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But this would be wrong, as the terseness of the quicksort implementation says more about the power of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://egarson.blogspot.com/2008/03/erlang-list-comprehensions-by-necessity.html&quot;&gt;list comprehensions&lt;/a&gt; than about Erlang's concurrency-supporting language features.&lt;br /&gt;&lt;br /&gt;So then let's see how you could implement a concurrent quicksort in Erlang, which &lt;i&gt;will&lt;/i&gt; say something about the way in which we can implement concurrency in Erlang. We'll start with the original Wikipedia quicksort from above, and alter it a little bit to make it more obvious what I'm going to do next:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;qsort([]) -&amp;gt; [];&lt;br /&gt;qsort([Pivot|Rest]) -&amp;gt;&lt;br /&gt; Left = [X || X &amp;lt;- Rest, X &amp;lt; Pivot],&lt;br /&gt; Right = [Y || Y &amp;lt;- Rest, Y &amp;gt;= Pivot],&lt;br /&gt; qsort(Left) ++ [Pivot] ++ qsort(Right).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the two calls to qsort at the end. Since there is no shared state between these two functions, they can be executed in parallel, and the results can be concatenated to yield the sorted result. Depending on the distribution of the input, each of these calls could be split up into 2 more qsort calls etc. etc. Note that you could do a hybrid recursive-tail-recursive solution which sorts the smallest partition using normal recursion and the largest using tail-recusrion, but that is not the aim here.&lt;br /&gt;&lt;br /&gt;Let's assume that we already have a function that executes any input function in a separate Erlang process called &quot;peval&quot;. (Note Erlang processes are extremely light-weight and take very little time to construct. They're are &lt;i&gt;not&lt;/i&gt; modelled as operating system processes). peval takes two arguments, a function to execute, and the arguments to the function. When called, it looks like a normal function call:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;(emacs@21ccw.blogspot.com)38&amp;gt; pqsort:peval(fun(X) -&amp;gt; X*X end, 13).&lt;br /&gt;169&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But, in the background, it spawns a process and the function is evaluated on this new process. The result is then returned to the calling process. Using peval, we now have a parallel quicksort:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;pqsort([]) -&amp;gt; [];&lt;br /&gt;pqsort([Pivot|Rest]) -&amp;gt;&lt;br /&gt; Left = [X || X &amp;lt;- Rest, X &amp;lt; Pivot],&lt;br /&gt; Right = [Y || Y &amp;lt;- Rest, Y &amp;gt;= Pivot],&lt;br /&gt; peval(fun pqsort/1, Left) ++ [Pivot] ++ peval(fun pqsort/1, Right).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now there is a significant observation to make. The concurrent and non-concurrent versions look remarkably similar, we only had to substitute the original function evaluations with parallel versions. This is one of the reasons why I think functional languages are better suited to concurrency that OO ones.&lt;br /&gt;&lt;br /&gt;Let's look at peval. peval creates a new process using spawn_link. spawn_link() is used instead of spawn(), so that the creator process receives exception when the new child process throws an exception.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;peval(Fun, Args) -&amp;gt;&lt;br /&gt; Pid = spawn_link(fun() -&amp;gt; wait() end),&lt;br /&gt; Pid ! {self(), Fun, Args},&lt;br /&gt; receive &lt;br /&gt; {Pid, R} -&amp;gt; R&lt;br /&gt; end.&lt;br /&gt;&lt;br /&gt;wait() -&amp;gt;&lt;br /&gt; receive&lt;br /&gt; {From,Fun,Args} -&amp;gt; &lt;br /&gt; From ! {self(), Fun(Args)}&lt;br /&gt; end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it! Parallel quicksort in about &lt;i&gt;15&lt;/i&gt; lines of Erlang code. If I add a &quot;+&quot; output to console on every entry to peval, and &quot;-&quot; on every exit from peval, you get the following output:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;(emacs@21ccw.blogspot.com)18&amp;gt; L1 = lists:map(fun(X) -&amp;gt; trunc(random:uniform()*100) end, lists:seq(1,100)).&lt;br /&gt;[57,33,2,85,59,65,61,71,83,75,94,94,19,5,79,53,31,54,39,61,&lt;br /&gt; 61,79,55,6,37,35,86,31,88|...]&lt;br /&gt;&lt;br /&gt;(emacs@21ccw.blogspot.com&amp;gt; pqsort:pqsort(L1).&lt;br /&gt;+++-++++-+--++-+++++-+--+--+--+++-+--++-+------+++&lt;br /&gt;+-++-+---+++-+--+---++-+-----+++++-+--++-+---+++++&lt;br /&gt;-+--+--+++-+--+---++-+----++-++-++-+------++++-+--&lt;br /&gt;++++-+--++-+---++++-+--++-+---++++-+--+++-++-+---+&lt;br /&gt;++-+--+----+-----+++-+++-+--+++-++-+---+----++-+--&lt;br /&gt;--&lt;br /&gt;[2,4,5,6,7,9,11,13,14,17,18,19,20,21,22,24,27,31,32,33,35,&lt;br /&gt; 37,38,39,40,42,44,47,48|...]&lt;br /&gt;&lt;br /&gt;(emacs@21ccw.blogspot.com)5&amp;gt; pqsort:integrate_output(&quot;+++-++++-+--++-+++++-+--+--+--+++-+--++-+------+++&quot;).&lt;br /&gt;0123234565654565678910910989878767898987898987654345...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can see that for the first few pevals, by integrating over the output, that number of parallel processes goes up to around 8-10. This will depend on the distribution, and the relative times it takes to initialise processes to doing the actual computation etc. &lt;br /&gt;&lt;br /&gt;Now that we've got pqsort going, I'm looking forward to doing the parallel graph algorithms of Jaksa's fork/join graph algorithms. There will be an obstacle to ensure that no nodes are visited more than once, but this could (possibly) be solved by partitioning the graph into subgraphs first where no children have multiple parents. We'll see...&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;updates&quot;&gt;Update (7 May 2008): This implementation is wrong! (see comments). There's a follow-up post here: &lt;/span&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2008/05/parallel-quicksort-in-erlang-part-ii.html&quot;&gt;Parallel Quicksort in Erlang - Part II&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-6885360353804589417?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-6885360353804589417</guid>
         <pubDate>Wed, 23 Apr 2008 22:36:00 -0700</pubDate>
      </item>
      <item>
         <title>Migrating CVS to SVN with cvs2svn – Basics for a Windows user</title>
         <link>http://ruthklempel.wordpress.com/2008/04/22/migrating-cvs-to-svn-with-cvs2svn-basics-for-a-windows-user/</link>
         <description>This tutorial shows the first steps how to test the cvs2svn tool in a Windows environment requiring minimal knowledge about CVS and SVN. The steps described have the purpose introduce you in the simplest ways how to create a CVS and a SVN repository and migrate CVS repositories to SVN repositories.
To run the cvs2svn tool [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=ruthklempel.wordpress.com&amp;blog=3517514&amp;post=5&amp;subd=ruthklempel&amp;ref=&amp;feed=1&quot;/&gt;</description>
         <guid isPermaLink="false">http://ruthklempel.wordpress.com/?p=5</guid>
         <pubDate>Tue, 22 Apr 2008 04:38:17 -0700</pubDate>
         <content:encoded><![CDATA[<div class='snap_preview'><br /><p>This tutorial shows the first steps how to test the cvs2svn tool in a Windows environment requiring minimal knowledge about CVS and SVN. The steps described have the purpose introduce you in the simplest ways how to create a CVS and a SVN repository and migrate CVS repositories to SVN repositories.</p>
<p>To run the <em>cvs2svn</em> tool and make use of some Linux tools, I opted to use a Linux-like environment for Windows called <em>cygwin</em>.</p>
<p>You can make all the steps simply using <em>cygwin</em>. However, as a Windows user, I think using the clients <em>TortoiseCVS</em> and <em>TortoiseSVN</em> could be more convenient, so is up to you to choose the most convenient way for you.</p>
<p>The commands mentioned in this tutorials that begin with <em><strong>$</strong></em> are for cygwin, the ones that begin with <em><strong>&gt;</strong></em> are for MS-DOS.</p>
<h3>Tools required</h3>
<ul>
<li>Install cygwin (with python, cvs, svn, gnutls, optionally rxvt, which I recommend). If you want to use rxvt on top of cygwin, create an icon with following target and start it: <em>C:&#92;cygwin&#92;bin&#92;rxvt.exe -bg black -fg yellow -cr blue -bd pink -fn &#8220;Lucida Console-16&#8243; -ls -st -sr -sl 2000 -tn xterm -e /usr/bin/bash &#8211;login -i</em></li>
<li>Install <em>TortoiseCVS</em> and <em>TortoiseSVN</em>.</li>
<li>Install the SVN Server for windows (or optionally use the svn server in <em>cygwin</em>)</li>
<li>Install <em>cvs2svn</em> using <em>cygwin</em>: download the <em>cvs2svn</em> file and unpack (e.g. in C:/Program Files).<code><br />
$ cd /c/Program&#92; Files/cvs2svn-2.1.0/<br />
$ make install</code></li>
</ul>
<h3>Create a CVS repository</h3>
<p>Using MS-DOS:</p>
<p><span style="font-family:Courier New;">&gt; set CVSROOT=C:/CVSServer<br />
&gt; cvs init</span></p>
<p>Using <em>cygwin</em>:</p>
<p><span style="font-family:Courier New;">$ export CVSROOT=C:/CVSServer<br />
$ cvs init</span></p>
<h3>Create and checkout a new CVS Module</h3>
<p>Using <em>cygwin</em>:</p>
<p><span style="font-family:Courier New;">$ cd &lt;path to a directory that contains initial data to be uploaded to the new module&gt;<br />
$ cvs import -m &#8220;First new module&#8221; MyFirstModule sts start</span> <span style="font-family:Courier New;"><br />
$ cd &lt;path to the directory where the new module shall be checked out&gt;<br />
$ cvs co MyFirstModule</span></p>
<p>Using <em>TortoiseCVS</em>:</p>
<ul>
<li>Create a new folder</li>
<li>In Windows Explorer right click this folder and choose the option &#8220;CVS -&gt; Make New Module&#8230;&#8221;</li>
<li>Choose the protocol &#8220;Locally mounted folder (:local:)&#8221;, enter the repository path &#8220;C:/CVSServer&#8221; and enter the name of the new module. The CVSROOT field will be automatically build as &#8220;:local:C:/CVSServer&#8221;. After clicking OK, this folder will automatically be checked out.</li>
<li>Copy some initial data into the new folder, mark the content, right click and choose the option &#8220;CVS Add&#8230;&#8221; and then &#8220;CVS Commit&#8230;.&#8221;</li>
</ul>
<h3>Migrate the CVS repository into SVN</h3>
<p>Now we can run the cvs2svn tool to migrate the previously created CVS repository to a new SVN repository. Try the following command in <em>cygwin</em>:</p>
<p><span style="font-family:Courier New;">$ /c/Program&#92; Files/cvs2svn-2.1.0/cvs2svn &#8211;svnrepos /c/SVNServer/ /c/CVSServer/MyFirstModule</span></p>
<p>After performing the command above, a new directory should have been created (C:&#92;SVNServer&#92;). Now the new SVN repository needs to be configured.</p>
<h3>Configure the new SVN repository</h3>
<p>Open the file C:&#92;SVNServer&#92;conf&#92;svnserve.conf and uncomment the following settings:</p>
<p>[general]<br />
anon-access = read<br />
auth-access = write<br />
password-db = passwd</p>
<p>Open the file C:&#92;SVNServer&#92;conf&#92;passwd and uncomment the following settings:</p>
<p>[users]<br />
harry = harryssecret<br />
sally = sallyssecret</p>
<h3>Start the SVN server</h3>
<p>You have a few different ways how to make the new SVN repository available for check outs.</p>
<p>One way is making the repository available as a SVN server &#8211; so, the repository will be available within your local network:</p>
<p><span style="font-family:Courier New;">$ svnserve &#8211;daemon &#8211;root /c/SVNServer</span></p>
<p>Alternatively you can start the SVN server as a windows service &#8211; open the MS-DOS console and enter the following command:</p>
<p>&gt; <span style="font-size:10pt;font-family:'Courier New';">sc create svnserve binpath= &#8220;&#92;&#8221;C:&#92;Program Files&#92;Subversion&#92;bin&#92;svnserve.exe&#92;&#8221; &#8211;service -r C:&#92;SVNServer&#8221; displayname= &#8220;Subversion Server&#8221; depend= Tcpip start= auto</span></p>
<h3>Checkout the migrated SVN repository</h3>
<p>If you have started the SVN server, you can use the address <em>svn://localhost/trunk </em>for the checkout. If you would rather like just to use the file system, you can use the address <a rel="nofollow"><span style="color:#000000;">file:///C:/SVNServer/trunk</span></a><span style="color:#000000;"><span style="text-decoration:underline;">.</span></span></p>
<p>Using <em>cygwin </em>or MS-DOS:</p>
<p class="MsoNormal" style="margin:0;"><span style="font-size:10pt;font-family:'Courier New';">cd &lt;path to the directory where the repository shall be checked out&gt;</span></p>
<p class="MsoNormal" style="margin:0;"><span style="font-size:10pt;font-family:'Courier New';">svn co &lt;svn address as described above&gt;</span></p>
<p>After performing the command above, a new directory should have been created with the same name as in the command argument.</p>
<p>Using <em>TortoiseSVN</em></p>
<ul>
<li>Create a directory that will contain a copy of the files in the SVN repository</li>
<li>Right-Click on the new created folder and choose option &#8220;SVN Checkout&#8230;&#8221;</li>
<li>Enter the address as described above and press the OK button.</li>
</ul>
<h3>How to create a new SVN repository and import initial data</h3>
<p>To create a new SVN repository, you can use the following command:</p>
<p><span style="font-family:Courier New;">$ svnadmin create /c/NewSVNServer</span></p>
<p>Now you can enter the folder that contains initial data that will be uploaded and then perform the import command.</p>
<p class="MsoNormal" style="margin:0;"><span style="font-size:10pt;font-family:'Courier New';">$ cd &lt;directory with initial data&gt;</span></p>
<p class="MsoNormal" style="margin:0;"><span style="font-size:10pt;font-family:'Courier New';">$ svn import -m &#8220;Import initial data&#8221; svn://localhost/trunk/</span></p>
<p class="MsoNormal" style="margin:0;">
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/ruthklempel.wordpress.com/5/"/> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/ruthklempel.wordpress.com/5/"/> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/ruthklempel.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ruthklempel.wordpress.com/5/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/ruthklempel.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ruthklempel.wordpress.com/5/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/ruthklempel.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ruthklempel.wordpress.com/5/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/ruthklempel.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ruthklempel.wordpress.com/5/"/></a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/ruthklempel.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ruthklempel.wordpress.com/5/"/></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ruthklempel.wordpress.com&blog=3517514&post=5&subd=ruthklempel&ref=&feed=1"/></div>]]></content:encoded>
         <media:content url="http://0.gravatar.com/avatar/6b92b44e0cb11a21c3a89eaf1980a160?s=96&amp;amp;d=wavatar" medium="image">
            <media:title>ruthklempel</media:title>
         </media:content>
      </item>
      <item>
         <title>IE7 Page Zoom Broken</title>
         <link>http://21ccw.blogspot.com/2008/04/ie7-page-zoom-broken.html</link>
         <description>We use &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.xplanner.org/&quot;&gt;XPlanner&lt;/a&gt; at work for some projects, and we noticed that there seems to be a problem with the hyperlinks in Internet Explorer (version 7.0.5730.11) when the pages are zoomed in (you can zoom pages in IE with Ctrl +). The horizontal areas for the links were not aligned to the actual text, which means that some links seem &lt;span style=&quot;font-style:italic;&quot;&gt;can't be clicked correctly&lt;/span&gt;, but you &lt;span style=&quot;font-style:italic;&quot;&gt;can&lt;/span&gt; click white space (look carefully at the first image, you can see the normal I-beam cursor):&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SAjcyclT7uI/AAAAAAAAAG8/uXDb8m13Ddo/s1600-h/one.png&quot;&gt;&lt;img style=&quot;margin:0px auto 10px;display:block;text-align:center;cursor:pointer;&quot; src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/SAjcyclT7uI/AAAAAAAAAG8/uXDb8m13Ddo/s400/one.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5190641329768754914&quot; border=&quot;0&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://4.bp.blogspot.com/_bXDgUoT7V7o/SAjcyslT7vI/AAAAAAAAAHE/r-iBAhrJyJU/s1600-h/two.png&quot;&gt;&lt;img style=&quot;margin:0px auto 10px;display:block;text-align:center;cursor:pointer;&quot; src=&quot;http://4.bp.blogspot.com/_bXDgUoT7V7o/SAjcyslT7vI/AAAAAAAAAHE/r-iBAhrJyJU/s400/two.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5190641334063722226&quot; border=&quot;0&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I shouldn't be surprised, since it does &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://21ccw.blogspot.com/2008/03/acid3-test-released.html&quot;&gt;so badly in the Acid3 test&lt;/a&gt;. I couldn't find any other reports of this issue, and will be happy to link to them if you post a comment.&lt;br /&gt;&lt;br /&gt;P.S. Firefox, Opera and Safari don't have this problem.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7435412383881764254-3297377195562942494?l=21ccw.blogspot.com'/&gt;&lt;/div&gt;</description>
         <author>Benjamin Nortier</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7435412383881764254.post-3297377195562942494</guid>
         <pubDate>Fri, 18 Apr 2008 03:13:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_bXDgUoT7V7o/SAjcyclT7uI/AAAAAAAAAG8/uXDb8m13Ddo/s72-c/one.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Getting started with distributed Erlang - Mnesia table relocation</title>
         <link>http://21ccw.blogspot.com/2008/04/getting-started-with-distributed-erlang.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/doc/apps/mnesia/index.html&quot;&gt;Mnesia&lt;/a&gt; is a distributed database that forms part of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/&quot;&gt;Erlang&lt;/a&gt; release. One of the features that I think is potentially powerful, is &lt;span style=&quot;font-style:italic;&quot;&gt;transparent&lt;/span&gt; table relocation across machines. With Mnesia, you can replicate tables to any nodes you wish in your network, and Mnesiatakes care of all the back end bits for you. With &quot;transparent&quot;, I mean that you don't need to do anything in your clients to make them &quot;aware&quot; of the new tables. Reads that were taking place from a table on one machine, will now be distributed across multiple nodes (where the nodes reside on single or multiple machines).&lt;br /&gt;&lt;br /&gt;I wanted to see how difficult it is to achieve this. For the setup, I installed two virtual Ubuntu 7.10 machines using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.vmware.com/products/player/&quot;&gt;VMware Player&lt;/a&gt;. You can get images for most Ubuntu distros at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://isv-image.ubuntu.com/vmware/&quot;&gt;http://isv-image.ubuntu.com/vmware/&lt;/a&gt;. FYI, the username and password for these images is ubuntu:ubuntu. I named the two nodes&lt;br /&gt;&lt;br /&gt;node1.21ccw.blogspot.com and&lt;br /&gt;node2.21ccw.blogspot.com&lt;br /&gt;&lt;br /&gt;You'll need to edit the network configurations with the IP addresses if you want to reproduce this experiment. If you need some help, post a question as comment :)&lt;br /&gt;&lt;br /&gt;I now had two machines that could ping each other using the full names, and a warm and fuzzy feeling inside:&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/R_4bNw2zkfI/AAAAAAAAAG0/by5WJ18M21A/s1600-h/vms.jpg&quot;&gt;&lt;img style=&quot;margin:0px auto 10px;display:block;text-align:center;cursor:pointer;&quot; src=&quot;http://3.bp.blogspot.com/_bXDgUoT7V7o/R_4bNw2zkfI/AAAAAAAAAG0/by5WJ18M21A/s400/vms.jpg&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5187613744044413426&quot; border=&quot;0&quot;/&gt;&lt;/a&gt;&lt;br /&gt;The next step was to start up an Erlang node on each machine. There's a catch here though. I got some problems using erl -sname, probably because of the way I set up the hostnames of the machines. So, &lt;span style=&quot;font-style:italic;&quot;&gt;I had to specify the fully qualified names manually&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;ubuntu@node1:~/node1$ erl -name 'node1@node1.21ccw.blogspot.com'&lt;br /&gt;Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]&lt;br /&gt;&lt;br /&gt;Eshell V5.5.5 (abort with ^G)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;ubuntu@node2:~/node2$ erl -name 'node2@node2.21ccw.blogspot.com'&lt;br /&gt;Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]&lt;br /&gt;&lt;br /&gt;Eshell V5.5.5 (abort with ^G)&lt;br /&gt;(node1@node1.21ccw.blogspot.com)1&amp;gt; nodes().&lt;br /&gt;[]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice the output of the &lt;span style=&quot;font-style:italic;&quot;&gt;nodes() &lt;/span&gt;command. This will return a list of &lt;span style=&quot;font-style:italic;&quot;&gt;other&lt;/span&gt; Erlang nodes that this node is aware of. Initially there's no awareness. To let a node know of another node, you can use net_adm:ping/1 to ping the other node. Both nodes will then become be aware of each other:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)4&amp;gt; net_adm:ping('node2@node2.21ccw.blogspot.com').&lt;br /&gt;pong&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)5&amp;gt; nodes().&lt;br /&gt;['node1@node1.21ccw.blogspot.com']&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;(node2@node2.21ccw.blogspot.com)1&amp;gt; nodes().&lt;br /&gt;['node1@node1.21ccw.blogspot.com']&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Cool. Now the nodes know of each other. To get Mnesia started, you have to create a schema on each node. A schema is located on the file system, in the same location where the actual disc-copies of tables will reside. [node()|nodes()] creates a list of the current node and all the other connected nodes. ls() shows the directory that Mnesia has created for the database.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)5&amp;gt; mnesia:create_schema([node()|nodes()]).&lt;br /&gt;ok&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)6&amp;gt; ls().&lt;br /&gt;Mnesia.node1@node1.21ccw.blogspot.com&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;(node2@node2.21ccw.blogspot.com)2&amp;gt; ls().&lt;br /&gt;Mnesia.node2@node2.21ccw.blogspot.com&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we have to start Mnesia on both nodes. You will notice that when we do an mnesia:info on node2 at this point, that it shows both nodes as being running database nodes.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)8&amp;gt; mnesia:start().&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;(node2@node2.21ccw.blogspot.com)3&amp;gt; mnesia:start().&lt;br /&gt;ok&lt;br /&gt;&lt;br /&gt;(node2@node2.21ccw.blogspot.com)4&amp;gt; mnesia:info().&lt;br /&gt;...&lt;br /&gt;running db nodes = ['node1@node1.21ccw.blogspot.com','node2@node2.21ccw.blogspot.com']&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next we'll create an actual database table, and populate it with some data. We define a record using rd(), then create a table on node1 (by default, this table will reside in RAM and have a disc copy), write a record to it and then read the record again. The primary key of the table is the first field of the record, i.e. the name.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)9&amp;gt; rd(person, {name, email_address}).&lt;br /&gt;person&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)10&amp;gt; mnesia:create_table(person, [{attributes, record_info(fields, person)}, {disc_copies, [node()]}]).&lt;br /&gt;{atomic,ok}&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)11&amp;gt; mnesia:transaction(fun() -&amp;gt; mnesia:write(#person{name = &quot;John&quot;, email_address = &quot;john@21ccw.blogspot.com&quot;}) end).&lt;br /&gt;{atomic,ok}&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)14&amp;gt; mnesia:transaction(fun() -&amp;gt; mnesia:read({person, &quot;John&quot;}) end).&lt;br /&gt;{atomic,[#person{name = &quot;John&quot;,email_address = &quot;john@21ccw.blogspot.com&quot;}]}&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)15&amp;gt; mnesia:info(). ...&lt;br /&gt;...&lt;br /&gt;[{'node1@node1.21ccw.blogspot.com',disc_copies}] = [person]&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What happens when we do the same read on node2? Remember that node has access to the person table &lt;span style=&quot;font-style:italic;&quot;&gt;only&lt;/span&gt; via the network, since it resides in RAM and on disc on node1.&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;node2@node2.21ccw.blogspot.com)5&amp;gt; mnesia:transaction(fun() -&amp;gt; mnesia:read({person, &quot;John&quot;}) end).&lt;br /&gt;{atomic,[{person,&quot;John&quot;,&quot;john@21ccw.blogspot.com&quot;}]}&lt;br /&gt;&lt;/pre&gt;Nice. Mnesia has transparently read the record from a table that's on another machine :)&lt;br /&gt;&lt;br /&gt;Now we decide to copy the table to node2. This requires a single command. Mnesia does the copying of the actual data for you to the other machine, and when you look at the file system on node2, there will now be &quot;person.DCD&quot; file, which is the disc copy of the table.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)15&amp;gt; mnesia:add_table_copy(person, 'node2@node2.21ccw.blogspot.com', disc_copies).&lt;br /&gt;{atomic,ok}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleB&quot;&gt;&lt;br /&gt;(node2@node2.21ccw.blogspot.com)9&amp;gt; ls(&quot;Mnesia.node2@node2.21ccw.blogspot.com&quot;).&lt;br /&gt;DECISION_TAB.LOG LATEST.LOG person.DCD&lt;br /&gt;schema.DAT&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;At this point, when you do a query on the person table, the actual data can come from either node. I'm not sure how Mnesia decides how to distribute the data, that's something to investigate further.&lt;br /&gt;&lt;br /&gt;Since the table is resident on both nodes, we can actually delete it from node1, and doing a read on node1 will now read the table over the network from node2:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;consoleA&quot;&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)23&amp;gt; mnesia:del_table_copy(person, node()).&lt;br /&gt;{atomic,ok}&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)19&amp;gt; mnesia:info().&lt;br /&gt;...&lt;br /&gt;[{'node2@node2.21ccw.blogspot.com',disc_copies}] = [person]&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;(node1@node1.21ccw.blogspot.com)18&amp;gt; mnesia:transaction(fun() -&amp;gt; mnesia:read({person, &quot;John&quot;}) end).&lt;br /&gt;{atomic,[#person{name = &quot;John&quot;,email_address = &quot;john@21ccw.blogspot.com&quot;}]}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Cool.&lt;br /&gt;&lt;br /&gt;What I've show is how to start up an Erlang/Mnesia node on two machines that are networked together, create tables on either node, and move the tables to other nodes by copy