<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Ben Godfrey</title><link>http://aftnn.org/</link><description /><language>en-GB</language><lastBuildDate>Thu, 29 Jul 2010 21:26:45 +0300</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/afternoon" /><feedburner:info uri="afternoon" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>51.4779</geo:lat><geo:long>-0.2136</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nd/2.0/</creativeCommons:license><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item><title>Moving to HTML5
</title><link>http://feedproxy.google.com/~r/afternoon/~3/bdQWH_AoOpE/</link><description>&lt;p&gt;&lt;img src="http://aftnn.org/stuff/journal_src/abookapart_html5.jpg" alt="HTML5 book" /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve converted this site to &lt;span class="caps"&gt;HTML5&lt;/span&gt;. It took about 5&amp;nbsp;minutes.&lt;/p&gt;

&lt;p&gt;The first step was to switch the doctype. The &lt;span class="caps"&gt;HTML5&lt;/span&gt;&amp;nbsp;doctype:&lt;/p&gt;

&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s it. No more secret&amp;nbsp;incantation.&lt;/p&gt;

&lt;p&gt;The 2nd step was to remove the trailing slashes from void tags (&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;, etc). These are optional in &lt;span class="caps"&gt;HTML5&lt;/span&gt;. I&amp;#8217;m not using the &lt;span class="caps"&gt;XML&lt;/span&gt; serialisation, so they&amp;#8217;re&amp;nbsp;unnecessary.&lt;/p&gt;

&lt;h2&gt;Next&amp;nbsp;steps&lt;/h2&gt;

&lt;p&gt;When I get another 5 minutes, I&amp;#8217;d like to use the new document structure tags &amp;mdash; &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;. These expose the semantics of the document more clearly (useful for authors). They can also be styled with &lt;code&gt;display:block&lt;/code&gt; to keep older browsers happy. Their introduction was based on a &lt;a href="http://code.google.com/webstats/index.html"&gt;large-scale analysis of &lt;span class="caps"&gt;HTML&lt;/span&gt; document structure performed by Google&lt;/a&gt;.&lt;/p&gt;

</description><pubDate>Thu, 29 Jul 2010 21:26:45 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2010/jul/29/moving-html5/</guid><category>html5</category><feedburner:origLink>http://aftnn.org/2010/jul/29/moving-html5/</feedburner:origLink></item><item><title>Towards testing OpenRasta views (OR 2.0.3, .NET 4, VS 2010)
</title><link>http://feedproxy.google.com/~r/afternoon/~3/nhzqG_mPkUA/</link><description>&lt;p&gt;&lt;a href="http://www.wonga.com/"&gt;My employer&lt;/a&gt; is a .&lt;span class="caps"&gt;NET&lt;/span&gt; shop. Despite my open source upbringing, I&amp;#8217;ve been getting to grips with some of the newer .&lt;span class="caps"&gt;NET&lt;/span&gt; technologies, &lt;a href="http://www.openrasta.com/"&gt;OpenRasta&lt;/a&gt; for exposing objects RESTfully, &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt; for simple object-&lt;span class="caps"&gt;RDBMS&lt;/span&gt; mapping. Some pretty cool stuff coming from the &lt;a href="http://altdotnet.org/"&gt;&lt;span class="caps"&gt;ALT&lt;/span&gt;.&lt;span class="caps"&gt;NET&lt;/span&gt;&lt;/a&gt;&amp;nbsp;scene.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m building a RESTful &lt;span class="caps"&gt;XML&lt;/span&gt; service with OpenRasta. I encountered a couple of problems that weren&amp;#8217;t covered by the &lt;a href="http://trac.caffeine-it.com/openrasta/wiki/Doc"&gt;community documentation&lt;/a&gt; so I&amp;#8217;ve written them up here. As such this is not a complete introduction. See this &lt;a href="http://stackoverflow.com/questions/2264839/getting-started-with-openrasta"&gt;question on StackOverflow about getting started with OpenRasta&lt;/a&gt; for help on that&amp;nbsp;front.&lt;/p&gt;

&lt;h2&gt;A quick note about&amp;nbsp;Web.config&lt;/h2&gt;

&lt;p&gt;The minimal changes to Web.config suggested by the &lt;a href="http://trac.caffeine-it.com/openrasta/wiki/Doc/Tutorials/FirstSite"&gt;first site tutorial&lt;/a&gt; wasn&amp;#8217;t enough for me in &lt;span class="caps"&gt;VS&lt;/span&gt; 2010. However, borrowing the &lt;a href="http://trac.caffeine-it.com/openrasta/browser/branches/2.0.3000/src/demo/OpenRasta.Demo/Web.config"&gt;Web.config from OpenRasta.Demo&lt;/a&gt; (included in the &lt;span class="caps"&gt;OR&lt;/span&gt; repo) and hacking it a little bit worked a treat. Here is the &lt;a href="http://gist.github.com/429870"&gt;complete Web.config for an &lt;span class="caps"&gt;OR&lt;/span&gt; 2.0.3 project hosted on &lt;span class="caps"&gt;ASP&lt;/span&gt;.&lt;span class="caps"&gt;NET&lt;/span&gt; in &lt;span class="caps"&gt;VS2010&lt;/span&gt;&lt;/a&gt; that&amp;#8217;s working for me right&amp;nbsp;now.&lt;/p&gt;

&lt;h2&gt;A note about NUnit&amp;nbsp;versions&lt;/h2&gt;

&lt;p&gt;OpenRasta.&lt;span class="caps"&gt;DI&lt;/span&gt;.Unity.Tests.Unit introduces a dependency on nunit.framework.dll version 2.5.1.9189. If you&amp;#8217;re using a different version, you can redirect the binding in App.config. See &lt;a href="http://blueonionsoftware.com/blog.aspx?p=03fe209c-db64-4a04-9adc-cec25b36f68b"&gt;Resolving Dependent .&lt;span class="caps"&gt;NET&lt;/span&gt; Assembly Version Conflicts&lt;/a&gt; for more&amp;nbsp;info.&lt;/p&gt;

&lt;h2&gt;Testing&amp;nbsp;views&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://docs.djangoproject.com/en/1.2/topics/testing/#module-django.test.client"&gt;Django&amp;#8217;s test client&lt;/a&gt; makes it easy to test a&amp;nbsp;view.&lt;/p&gt;

&lt;pre&gt;&lt;code class="python"&gt;&amp;gt;&amp;gt;&amp;gt; from django.test.client import Client
&amp;gt;&amp;gt;&amp;gt; c = Client()
&amp;gt;&amp;gt;&amp;gt; response = c.get("/retailer/1")
&amp;gt;&amp;gt;&amp;gt; response.content
'&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;...'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I want to do the same thing to my OpenRasta&amp;nbsp;views.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a lightweight environment with 1 or 2 lines of&amp;nbsp;code.&lt;/li&gt;
&lt;li&gt;Pass an &lt;span class="caps"&gt;URL&lt;/span&gt; to a method which returns the view&amp;nbsp;output.&lt;/li&gt;
&lt;li&gt;Parse response content and inspect data contained&amp;nbsp;therein.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would prefer not to have to set up a dev web server or use Selenium or Twill or some other tool to test my view code. Although those are valid integration tests, they&amp;#8217;re complicated and slow. My purpose is just to demonstrate that I&amp;#8217;ve wired my domain model and OpenRasta together correctly, so I want to test the shortest code&amp;nbsp;path.&lt;/p&gt;

&lt;p&gt;OpenRasta provides &lt;code&gt;InMemoryHost&lt;/code&gt; which looks like it should solve the problem nicely. OpenBastard, OpenRasta&amp;#8217;s suite of regression tests, also provides some tools for solving this problem. Sadly, both are undocumented and work in progress at the time of&amp;nbsp;writing.&lt;/p&gt;

&lt;p&gt;After spending some time looking through the source and asking questions on the mailing list, I wasn&amp;#8217;t able to create a test environment using either &lt;code&gt;InMemoryHost&lt;/code&gt; or OpenBastard. I&amp;#8217;ll update this post as and when I make any&amp;nbsp;progress.&lt;/p&gt;

&lt;p&gt;However, in the meantime, here is an integration test that passes a request to &lt;span class="caps"&gt;OR&lt;/span&gt; through &lt;span class="caps"&gt;IIS&lt;/span&gt; running on&amp;nbsp;localhost.&lt;/p&gt;

&lt;pre&gt;&lt;code class="csharp"&gt;[TestFixture]
public class RetailerTests
{
    [Test]
    public void GetRetailer_RetailerExists_RetailerRepresentationReturned()
    {
        var uri = new Uri("http://localhost/retailers/1");
        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        webRequest.Method = "GET";
        webRequest.ContentType = "application/x-www-form-urlencoded";
        webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";

        Retailer retailer;
        DataContractSerializer dcs = new DataContractSerializer(typeof(Retailer));
        using (var response = webRequest.GetResponse())
        {
            retailer = (Retailer)dcs.ReadObject(response.GetResponseStream());
        }

        Assert.AreEqual(retailer.Id, 1);
        Assert.AreEqual(retailer.Name, "Retailer");
        Assert.AreEqual(retailer.Products.Count, 1);
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Based on code &lt;a href="http://groups.google.com/group/openrasta/msg/b93992b038a2c42b"&gt;posted to the OpenRasta mailing list by David Lawton&lt;/a&gt;.&lt;/p&gt;

</description><pubDate>Fri, 18 Jun 2010 18:38:26 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2010/jun/18/towards-testing-openrasta-views/</guid><category>.net</category><category>csharp</category><category>openrasta</category><feedburner:origLink>http://aftnn.org/2010/jun/18/towards-testing-openrasta-views/</feedburner:origLink></item><item><title>Hack your life with Remember The Milk
</title><link>http://feedproxy.google.com/~r/afternoon/~3/JQawe8dUVnQ/</link><description>&lt;p&gt;&lt;img src="http://aftnn.org/stuff/journal_src/rtmtasks.png" alt="Alt text" /&gt;&lt;/p&gt;

&lt;p&gt;At first glance, &lt;a href="http://www.rememberthemilk.com/"&gt;Remember The Milk&lt;/a&gt; (henceforth &lt;span class="caps"&gt;RTM&lt;/span&gt;), is a simple todo list web app. Dig deeper and you&amp;#8217;ll find a very flexible, customisable and programmable&amp;nbsp;platform.&lt;/p&gt;

&lt;h2&gt;Getting Things&amp;nbsp;Done&lt;/h2&gt;

&lt;p&gt;Like many todo list apps, &lt;span class="caps"&gt;RTM&lt;/span&gt; roughly follows the &lt;a href="http://en.wikipedia.org/wiki/Getting_Things_Done"&gt;Getting Things Done&lt;/a&gt; (&lt;span class="caps"&gt;GTD&lt;/span&gt;)&amp;nbsp;methodology.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The overview allows you to focus on tasks for today, tomorrow or this&amp;nbsp;week.&lt;/li&gt;
&lt;li&gt;The tasks view allows you to manage tasks, categorise them into lists (inbox, errands, work, etc), tag them, set due dates, set repeating behaviour and add urls, notes and time&amp;nbsp;estimates.&lt;/li&gt;
&lt;li&gt;The locations view lets you assign tags to locations (useful when you use a mobile&amp;nbsp;app).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Hacks&lt;/h2&gt;

&lt;h3&gt;Quick task&amp;nbsp;add&lt;/h3&gt;

&lt;p&gt;Adding tasks to &lt;span class="caps"&gt;RTM&lt;/span&gt; is a hack in itself. They have a nice terse syntax for specifying the attributes of a task. Days, times and urls are parsed automatically, e.g. &amp;#8220;Buy tea 1pm,&amp;#8221; but you can save a lot of time using their &lt;a href="http://www.rememberthemilk.com/services/smartadd/"&gt;Smart Add&lt;/a&gt; operators.&amp;nbsp;E.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Prioritise issues Monday #Work !2 *weekly
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Means:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Add a task called &amp;#8216;Prioritise issues&amp;#8217; for Monday, add it to my &amp;#8216;Work&amp;#8217; list, set the priority to 2 and repeat it every&amp;nbsp;Monday.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See the &lt;a href="http://www.rememberthemilk.com/services/smartadd/"&gt;Smart Add documentation&lt;/a&gt; for details and lots of&amp;nbsp;examples.&lt;/p&gt;

&lt;h3&gt;Keyboard&amp;nbsp;shortcuts&lt;/h3&gt;

&lt;p&gt;&lt;span class="caps"&gt;RTM&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.rememberthemilk.com/help/answers/basics/keyboard.rtm"&gt;keyboard shortcuts&lt;/a&gt; save a lot of time when navigating around the application. There are lots of them, they cover the app pretty comprehensively, making it feel more like a desktop&amp;nbsp;app.&lt;/p&gt;

&lt;h3&gt;iPhone&amp;nbsp;app&lt;/h3&gt;

&lt;p&gt;Before switching to &lt;span class="caps"&gt;RTM&lt;/span&gt;, I used &lt;a href="http://www.omnigroup.com/products/omnifocus/"&gt;OmniFocus&lt;/a&gt; on 2 Macs and my iPhone. The iPhone app was always very slow to load and sync. I hardly used it. &lt;span class="caps"&gt;RTM&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.rememberthemilk.com/services/iphone/"&gt;iPhone app&lt;/a&gt; is simple, fast and useful. It starts fairly quickly (although I wouldn&amp;#8217;t complain if they shaved off another second or 2). Critically, once it has started, it&amp;#8217;s very quick to add tasks (thanks to Smart Add) and to sync. &lt;span class="caps"&gt;RTM&lt;/span&gt; pushes reminders as app notifications (which are like richer text messages). The number of incomplete tasks (either for today or in total) is shown as an icon badge. The app does just the things you need and does them&amp;nbsp;well.&lt;/p&gt;

&lt;p&gt;There is also an &lt;a href="http://www.rememberthemilk.com/services/android/"&gt;Android app&lt;/a&gt; and sync tools for &lt;a href="http://www.rememberthemilk.com/services/milksync/blackberry/"&gt;Blackberry&lt;/a&gt; and &lt;a href="http://www.rememberthemilk.com/services/milksync/windowsmobile/"&gt;Windows Mobile&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Reminders for events with due&amp;nbsp;times&lt;/h3&gt;

&lt;p&gt;&lt;span class="caps"&gt;RTM&lt;/span&gt; can send you task reminders via email, &lt;span class="caps"&gt;SMS&lt;/span&gt;, Twitter or iPhone app notifications. You can configure &lt;span class="caps"&gt;RTM&lt;/span&gt; to send reminders for all events or just  events with due&amp;nbsp;times.&lt;/p&gt;

&lt;p&gt;I forget to do things, so I set due times for things and &lt;span class="caps"&gt;RTM&lt;/span&gt; sends me an iPhone notification. I guess when I&amp;#8217;m going to be in the shop and get &lt;span class="caps"&gt;RTM&lt;/span&gt; to remind me when I&amp;#8217;m there. An alternative way to do this would be to set locations for tasks and then check the location list when I&amp;nbsp;arrive.&lt;/p&gt;

&lt;h3&gt;Repeating&amp;nbsp;tasks&lt;/h3&gt;

&lt;p&gt;Tasks can be set to repeat and &lt;span class="caps"&gt;RTM&lt;/span&gt; can express quite specific schedules, e.g. &amp;#8220;every month on the 4th&amp;#8221; or &amp;#8220;after 6 months.&amp;#8221; See the &lt;a href="http://www.rememberthemilk.com/help/answers/basics/repeatformat.rtm"&gt;repeat interval documentation&lt;/a&gt; for details. I use it to remind me to do my weekly online grocery&amp;nbsp;shop.&lt;/p&gt;

&lt;h3&gt;Add to &lt;span class="caps"&gt;RTM&lt;/span&gt;&amp;nbsp;bookmarklet&lt;/h3&gt;

&lt;p&gt;&lt;span class="caps"&gt;RTM&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.rememberthemilk.com/help/answers/quickadd/"&gt;Quick Add Bookmarklet&lt;/a&gt; makes setting reminders from your browser extra quick and easy. Unfortunately, it doesn&amp;#8217;t save address of the current page with the new&amp;nbsp;task.&lt;/p&gt;

&lt;h3&gt;rtm command using&amp;nbsp;mail&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;m never far from a bash shell, so it&amp;#8217;s useful to have a command to add things to &lt;span class="caps"&gt;RTM&lt;/span&gt;. This command uses &lt;span class="caps"&gt;RTM&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.rememberthemilk.com/help/answers/sending/emailinbox.rtm"&gt;email to task list&lt;/a&gt;&amp;nbsp;feature.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rtm() { echo '' | mail -s "$*" username+12345x@rmilk.com; }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Smart Add operators mean I can easily set all the attributes I need on the task from a single command. I haven&amp;#8217;t gotten into scripting it yet, but it would be simple to add &lt;span class="caps"&gt;RTM&lt;/span&gt; tasks in that way. There are loads of ways this could be helpful. For example, I could create a cron job to check disk space on my servers and add a high-priority &lt;span class="caps"&gt;RTM&lt;/span&gt; task if a disk becomes more than 80%&amp;nbsp;full.&lt;/p&gt;

&lt;p&gt;You could also write a version of this command that uses Twitter to upload tasks or goes direct to the &lt;span class="caps"&gt;API&lt;/span&gt;, e.g. using the &lt;a href="http://code.google.com/p/rtmapi/"&gt;Python &lt;span class="caps"&gt;API&lt;/span&gt; wrapper&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Searching and smart&amp;nbsp;lists&lt;/h3&gt;

&lt;p&gt;You can search &lt;span class="caps"&gt;RTM&lt;/span&gt; with a bewildering array of Google-like search operators. Search for tasks tagged blah with &lt;code&gt;tag:blah&lt;/code&gt; or see work tasks completed yesterday with &lt;code&gt;completedWithin:"1 day of today" and list:Work&lt;/code&gt;. You can save any search as a &lt;a href="http://www.rememberthemilk.com/help/answers/smartlists/"&gt;Smart List&lt;/a&gt;, which adds a tab to your tasks view. Tasks added when viewing a smart lists inherit the attributes of that&amp;nbsp;list.&lt;/p&gt;

&lt;p&gt;Smart lists have a million applications. Here are some ways I&amp;#8217;ve used&amp;nbsp;them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a master &amp;#8220;Work&amp;#8221; list and then smart lists that filter by tag to show items for individual projects. View the big picture or focus on a&amp;nbsp;project.&lt;/li&gt;
&lt;li&gt;Create a list of tasks recently completed. Check it before going along to review&amp;nbsp;meetings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Even more&amp;nbsp;hacks&lt;/h3&gt;

&lt;p&gt;There are loads more &lt;span class="caps"&gt;RTM&lt;/span&gt; hacks I haven&amp;#8217;t tried&amp;nbsp;yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/services/api/"&gt;A full-featured &lt;span class="caps"&gt;API&lt;/span&gt; (the uber-hack)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/services/gmail/"&gt;A nice Gmail widget&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/help/answers/sharing/"&gt;Publish (read-only) and share (read/write) lists&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/help/answers/icalendar/"&gt;Export to your calendar&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/help/answers/tasks/printlist.rtm"&gt;Nice printing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rememberthemilk.com/help/answers/atom/"&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt;/Atom feeds&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Your life,&amp;nbsp;hacked&lt;/h2&gt;

&lt;p&gt;&lt;span class="caps"&gt;RTM&lt;/span&gt; supports a myriad of ways to organise your life and work. It&amp;#8217;s easy to get started and flexible enough to support many different styles of organisation. Some really powerful features help you work smart. The app is always responsive, it gets out of your way and lets you focus on getting things&amp;nbsp;done.&lt;/p&gt;

</description><pubDate>Tue, 18 May 2010 21:35:38 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2010/may/18/hack-your-life-remember-milk/</guid><category>lifehacks</category><category>rememberthemilk</category><category>webapps</category><feedburner:origLink>http://aftnn.org/2010/may/18/hack-your-life-remember-milk/</feedburner:origLink></item><item><title>Mixcloud is a great site for sharing mixes
</title><link>http://feedproxy.google.com/~r/afternoon/~3/PdBXR-8TTpc/</link><description>&lt;p&gt;&lt;span class="caps"&gt;UK&lt;/span&gt; startup Mixcloud has built a great site for sharing &lt;span class="caps"&gt;DJ&lt;/span&gt; mixes. It was fun enough that I typed out the full track-listing for my now-venerable &lt;a href="http://aftnn.org/stuff/music/afternoon_-_make_it_minimal.mp3"&gt;Make It Minimal&lt;/a&gt; mix, all 43&amp;nbsp;tracks!&lt;/p&gt;

&lt;div&gt;
&lt;object width="300" height="300" type="application/x-shockwave-flash" data="http://www.mixcloud.com/media/swf/player/mixcloudLoader.swf?v=13"&gt;
&lt;param name="movie" value="http://www.mixcloud.com/media/swf/player/mixcloudLoader.swf?v=13"&gt;
&lt;param name="allowFullScreen" value="true"&gt;
&lt;param name="allowscriptaccess" value="always"&gt;
&lt;param name="flashVars" value="feed=http://www.mixcloud.com/api/1/cloudcast/afternoon/make-it-minimal.json"&gt;
&lt;embed src="http://www.mixcloud.com/media/swf/player/mixcloudLoader.swf?v=13" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" flashvars="feed=http://www.mixcloud.com/api/1/cloudcast/afternoon/make-it-minimal.json" width="300" height="300"&gt;
&lt;/object&gt;
&lt;div style="clear:both; height:3px;"&gt;&lt;/div&gt;&lt;p style="display:block; font-size:12px; font-family:Helvetica, Arial, sans-serif; margin:0; padding: 3px 4px 3px 4px; color:#999;"&gt;&lt;a href="http://www.mixcloud.com/afternoon/make-it-minimal/" style="color:#02a0c7; font-weight:bold;"&gt;Make It Minimal&lt;/a&gt; by &lt;a href="http://www.mixcloud.com/afternoon/" style="color:#02a0c7; font-weight:bold;"&gt;Afternoon&lt;/a&gt; on &lt;a href="http://www.mixcloud.com/" style="color:#02a0c7; font-weight:bold;"&gt;&amp;nbsp;Mixcloud&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both; height:3px;"&gt;&lt;/div&gt;&lt;/div&gt;
</description><pubDate>Tue, 13 Oct 2009 18:39:09 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/oct/13/mixcloud-great-site-sharing-mixes/</guid><category>minimal</category><category>mixcloud</category><feedburner:origLink>http://aftnn.org/2009/oct/13/mixcloud-great-site-sharing-mixes/</feedburner:origLink></item><item><title>How I work
</title><link>http://feedproxy.google.com/~r/afternoon/~3/XaawEFT_lUU/</link><description>&lt;p&gt;I&amp;#8217;m an independent software engineer working on a contract basis. I have a process for projects. It&amp;#8217;s a relatively lightweight, loosely &lt;a href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;agile&lt;/a&gt; methodology. It attempts to ensure projects run smoothly by building software in a series of short&amp;nbsp;iterations.&lt;/p&gt;

&lt;h2&gt;Face-to-face or Skype&amp;nbsp;meeting&lt;/h2&gt;

&lt;p&gt;After an introduction is made, I organise a face-to-face or Skype meeting. I get an overview of the requirements and the context in which the application will sit, the business goals. Clients often have preconceptions about what I&amp;#8217;ll do, how long it will take, etc. I like to learn about the project so I can challenge those preconceptions if necessary. For example, if a client asks me to create a blogging tool, I&amp;#8217;ll make sure that none of the off-the-shelf tools will do before proceeding. I&amp;#8217;m actually pretty vigorous in recommending alternate approaches. &lt;a href="http://aftnn.org/2009/may/19/software-development-advice-startups/"&gt;My experience is that a lot of stress and heartache can be avoided&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because I practise agile software development, I encourage clients to find a minimum set of features which can be implemented an iteration lasting up to 2 weeks. This is a useful process. It encourages both me and my clients to think about the business goals first. If those goals can be met without software or with off-the-shelf tools, we can make that decision&amp;nbsp;now.&lt;/p&gt;

&lt;h2&gt;Specification&amp;nbsp;document&lt;/h2&gt;

&lt;p&gt;After the initial meeting and a follow-up email or 2, I will produce an iteration specification document. I usually get this to the client within a few days to a week depending on how busy I am. I can rush it through if&amp;nbsp;necessary.&lt;/p&gt;

&lt;p&gt;The specification will list the set of user stories (how the app will be used, tasks it will support) and the features required (the actual stuff I&amp;#8217;ll build). The feature set will take no more than 2 weeks to develop, test and deploy. Additional features are left for subsequent&amp;nbsp;iterations.&lt;/p&gt;

&lt;p&gt;If the client is happy, work begins. Otherwise the spec is revised. The spec is my statement of intention, this is my understanding of what the client wants me to build. I ask my clients to check this carefully. If I&amp;#8217;ve got something wrong, it&amp;#8217;s time-consuming to fix later. It&amp;#8217;s often hard to make spec docs exhaustive and unambiguous and this can lead to disagreements, I try hard to avoid&amp;nbsp;that.&lt;/p&gt;

&lt;h2&gt;Developing&amp;nbsp;iteratively&lt;/h2&gt;

&lt;p&gt;The work begins on the first iteration. I will develop the required features and test and deploy the software within the stated time period. During this period communication slows down a bit. Coding requires a really quite extreme level of concentration so I tend to close my email, Skype, etc and put my headphones&amp;nbsp;on.&lt;/p&gt;

&lt;p&gt;Only quite minor changes to the spec can be accommodated once an iteration has begun. If changes are frequent, it&amp;#8217;s very hard to get up to speed. A car can go much faster on a straight road. The client&amp;#8217;s desire to provide new feedback and ideas and the developer&amp;#8217;s desire to get the job done are often in competition. The beauty of developing in short iterations is that this competition can be resolved. Ideas can wait a week or 2, in fact they benefit from more consideration, meanwhile the develop can code away&amp;nbsp;undisturbed.&lt;/p&gt;

&lt;p&gt;Towards the end of the iteration, the new code is deployed to somewhere where it can be tested by myself, the client and other stakeholders, often a staging site. Bugs are found and fixed. Loose ends are tied up. Finally, the software is put into production. Bug testing and fixing takes from 25-50% of the iteration time. Deployment is generally straightforward, but can still take a few hours, for that reason it&amp;#8217;s only done once per&amp;nbsp;iteration.&lt;/p&gt;

&lt;p&gt;When an iteration is complete, the process begins again. A face-to-face or Skype meeting allows the client and I to assess what&amp;#8217;s been achieved so far. Learning from one iteration goes into the next. A new spec is produced and I get back to&amp;nbsp;work.&lt;/p&gt;

</description><pubDate>Tue, 29 Sep 2009 15:12:34 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/sep/29/how-i-work/</guid><category>process</category><category>software</category><feedburner:origLink>http://aftnn.org/2009/sep/29/how-i-work/</feedburner:origLink></item><item><title>Clojure: a stateless dynamically-typed Lisp on the JVM
</title><link>http://feedproxy.google.com/~r/afternoon/~3/zAHtoFE7tlc/</link><description>&lt;p&gt;I&amp;#8217;m a big fan of programming without state in languages like Haskell and Erlang. &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; is a modern Lisp, but follows the stateless style very closely, taking ideas from Haskell and &lt;span class="caps"&gt;ML&lt;/span&gt;. Clojure is implemented in Java and runs on the &lt;span class="caps"&gt;JVM&lt;/span&gt;, providing full access to all of Java&amp;#8217;s&amp;nbsp;libraries.&lt;/p&gt;

&lt;h2&gt;Modern&lt;/h2&gt;

&lt;p&gt;Clojure is a lot less crufty than other Lisp implementations, some of which are now pretty long in the tooth. Maps and vectors and a few other things are given syntax. Macros still work though, so I guess it&amp;#8217;s still all s-expressions (&lt;code&gt;[1 2 3]&lt;/code&gt; could trivially map to &lt;code&gt;(vector 1 2 3)&lt;/code&gt;). Clojure has a terse syntax with lots of good code smells (e.g. &lt;code&gt;*constant*&lt;/code&gt; and &lt;code&gt;predicate?&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;Structural&amp;nbsp;sharing&lt;/h2&gt;

&lt;p&gt;Clojure benefits from state of the art data structure research. Clojure&amp;#8217;s key data structures (lists, vectors, maps) are implemented using a technique called structural sharing. If you add an element to the front of an existing list, the new list is simply the new item plus the existing list. The existing list can be stored once. The new item simply points to the head of the existing list. This technique preserves complexity characteristics of operations on data structures (insert, remove, access, etc), minimises memory footprint and provides immutable state! Very cool&amp;nbsp;stuff.&lt;/p&gt;

&lt;h2&gt;Dynamic&amp;nbsp;typing&lt;/h2&gt;

&lt;p&gt;Clojure is dynamically-typed like Python or Ruby. This makes it a good entry point from these languages. For programmers looking to program without state other options are Haskell or Erlang. Erlang is awesome for building highly available, concurrent applications. It&amp;#8217;s syntax is kind of fun, but not for everyone. Haskell is strongly typed, pure and lazy. This unique mix of features can be very powerful, but can also trip you up. Both languages have a sweet spot, Clojure feels more general purpose. For me, that means great for scripting and writing web apps&amp;nbsp;:-).&lt;/p&gt;

&lt;p&gt;I like Django&amp;#8217;s minimal template language. There is an implementation in Erlang, but Erlang&amp;#8217;s string processing is somewhat weak. Templating and other string processing, like parsing &lt;span class="caps"&gt;JSON&lt;/span&gt;, is a bit long-winded. Haskell doesn&amp;#8217;t have any good template languages, the best option is &lt;a href="http://www.haskell.org/ghc/docs/latest/html/libraries/xhtml/Text-XHtml.html"&gt;Text.Xhtml&lt;/a&gt;, a combinator library. Not very designer-friendly. Haskell&amp;#8217;s powerful type system isn&amp;#8217;t very useful for implementing a text template language. It gets in the way more than it helps. It feels like an impedance mismatch. It would be an interesting project to build a template processor compatible with Django in&amp;nbsp;Clojure.&lt;/p&gt;

&lt;h2&gt;Recommended&amp;nbsp;viewing&lt;/h2&gt;

&lt;p&gt;For a more complete description &lt;a href="http://blip.tv/file/812787"&gt;watch Clojure creator Rich Hickey describing Clojure and walking through a concurrent application&lt;/a&gt;.&lt;/p&gt;

</description><pubDate>Tue, 21 Jul 2009 13:15:38 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/jul/21/clojure-stateless-dynamicly-typed-lisp-jvm/</guid><category>clojure</category><category>erlang</category><category>functionalprogramming</category><category>haskell</category><category>lisp</category><feedburner:origLink>http://aftnn.org/2009/jul/21/clojure-stateless-dynamicly-typed-lisp-jvm/</feedburner:origLink></item><item><title>Software development advice for startups
</title><link>http://feedproxy.google.com/~r/afternoon/~3/DYutT8fXzUY/</link><description>&lt;p&gt;You&amp;#8217;ve got a great idea! You want to build a web site that saves people time and money and helps them make friends! You&amp;#8217;ve written a rough business plan, now you want to find someone to build your&amp;nbsp;site.&lt;/p&gt;

&lt;p&gt;Software development is complicated, expensive, error-prone, regularly boring and complicated. As a programmer, here&amp;#8217;s what I think you should know before we meet for&amp;nbsp;coffee.&lt;/p&gt;

&lt;h2&gt;1. Avoid developing&amp;nbsp;software&lt;/h2&gt;

&lt;p&gt;As a general rule, you should avoid doing anything you don&amp;#8217;t need to do in a startup or new project. You have plenty of things to worry about. If you can possibly avoid writing software, do so. Need a website? Use WordPress. &lt;a href="http://intruders.tv/"&gt;Intruders.tv&lt;/a&gt; and &lt;a href="http://icanhascheezburger.com/"&gt;I Can Has Cheezburger&lt;/a&gt; are 2 great businesses built on WordPress. Need something like a social network? Use Ning. Prove that you can build the community, then transition to a bespoke platform to build features. Since 2004, an amazing number of high quality, free or low-cost tools have come on to the market. Tools don&amp;#8217;t have to be perfect. Maybe half your product is already implemented by someone else&amp;#8217;s &lt;span class="caps"&gt;API&lt;/span&gt;. Use that, build the other half. Worry about strategic risks later. You&amp;#8217;re prototyping&amp;nbsp;remember.&lt;/p&gt;

&lt;h2&gt;2. Software is&amp;nbsp;complex&lt;/h2&gt;

&lt;p&gt;Software is complex and fragile. Even a simple piece of software is many times more complex than a car engine for example. Even simple web apps built with standard tools don&amp;#8217;t tend to share that many common parts. Understanding an application later and modifying it is really a very complex task&amp;nbsp;indeed.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s many times easier to change an idea or a document or a diagram than to change software. Try to make changes early and avoid making them late if possible. The agile methodology, building software bit by bit in short sprints, makes it more likely that you&amp;#8217;ll change something before it&amp;#8217;s been coded, tested and&amp;nbsp;deployed.&lt;/p&gt;

&lt;h2&gt;3. Don&amp;#8217;t make a big long list of features stretching until the end of time and&amp;nbsp;space&lt;/h2&gt;

&lt;p&gt;Decide what the very core of your offering is, find out if your customers are interested and build the minimum that can solve their&amp;nbsp;problem.&lt;/p&gt;

&lt;p&gt;This approach costs less and is less risky than building your perfect dream. When you have the minimum viable product built, solicit feedback from your customers. By making the big list, you&amp;#8217;re second guessing what they want. You&amp;#8217;re probably&amp;nbsp;wrong.&lt;/p&gt;

&lt;p&gt;Ideas happen much more quickly than the code. An idea might take a day to think through and a week or a month to implement. If you make a list of features, those features will be irrelevant by the time the programmers get around to building them. Stay in the moment. Keep the list to what your customers are asking for&amp;nbsp;today.&lt;/p&gt;

&lt;h2&gt;4. Let your developers (and designers) do their&amp;nbsp;job&lt;/h2&gt;

&lt;p&gt;Cheaper development teams are great when you have a known problem and a known solution. When you&amp;#8217;re launching a new product, you have only one or neither. Communication is critical, but it&amp;#8217;s also important to respect the software development process. Remember that writing software is complex, boring and error-prone. This means most of the time, developers have to get their heads down and work, work, work. I find 2 weeks a good length for a block of work because it gives a good mix of regular points for communication, keeping the product connected to reality, and time to get things&amp;nbsp;done.&lt;/p&gt;

&lt;p&gt;Be flexible enough to create an environment where your team can get on with delivering a great product, and you can get on with everything&amp;nbsp;else.&lt;/p&gt;

&lt;p&gt;Bonus point: If you engage a designer, let them design. You have to be proud of the way your application or site looks, but you are not the customer, the customer is. Experienced designers are good at making things that work well and look good for the larger audience. Try not to make personal judgement, like &amp;#8220;I don&amp;#8217;t like that grey.&amp;#8221; Your customers probably won&amp;#8217;t care as long as the site or service looks professional and is easy to use. If you have &lt;a href="http://en.wikipedia.org/wiki/A/B_testing"&gt;A/B test&lt;/a&gt; data to show that the grey has lower conversion rates, that&amp;#8217;s different (Google actually tests different shades of&amp;nbsp;blue).&lt;/p&gt;

&lt;h2&gt;5. Don&amp;#8217;t&amp;nbsp;micromanage&lt;/h2&gt;

&lt;p&gt;This is kind of the same as the previous point, but it&amp;#8217;s vitally important for software. If you&amp;#8217;re launching a product and you start involving yourself in the minutiae of development, you will slow the process down hugely. Development takes focus, handling a micromanaging client takes time and destroys that focus, leading to mistakes and&amp;nbsp;delays.&lt;/p&gt;

&lt;p&gt;Let small decisions go. Revisit them if they really are wrong.  You don&amp;#8217;t know if your product will be a hit yet. You need to get something out there as quickly and as cheaply as possible. If it later turns out you need to change the core product (which you almost certainly will), all the time spent fine tuning before launch is time&amp;nbsp;wasted.&lt;/p&gt;

&lt;h2&gt;6. Software is only part of the&amp;nbsp;puzzle&lt;/h2&gt;

&lt;p&gt;Finding money, figuring out a product and having it built is not easy, but it is well understood and, given a sensible spec, can be acheived in a finite amount of&amp;nbsp;time.&lt;/p&gt;

&lt;p&gt;Most new products don&amp;#8217;t fail because the implementation was bad, they fail because the customers never came. Make sure the customer is there before you start. Make sure you know where they will come from, why they will use your product. Make sure you know this inside out. It&amp;#8217;s very possible that your idea, though neat, isn&amp;#8217;t a workable business. You really want to learn that before investing time and effort in building a product. &lt;a href="http://www.amazon.co.uk/New-Business-Road-Test-Entrepreneurs/dp/0273708058/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1254230145&amp;amp;sr=8-1"&gt;The New Business Road Test&lt;/a&gt; is an excellent book on evaluating&amp;nbsp;opportunities.&lt;/p&gt;

&lt;h2&gt;7. Rewriting is&amp;nbsp;common&lt;/h2&gt;

&lt;p&gt;Once a piece of software has been around the block once or twice, the task it&amp;#8217;s being used for ends up pretty far from the one is was intended for. Maintaining it becomes increasingly difficult. At this point, it&amp;#8217;s time to consider a rewrite. This is a good thing. New tools and practices will have emerged that you can take advantage of. You know more about the business you&amp;#8217;re in and you can cut out the features you don&amp;#8217;t need and concentrate on making the ones you do much better. Rewriting is good. Plan to rewrite. Get stuff done simply and quickly at first, revisit it later when you know&amp;nbsp;more.&lt;/p&gt;

&lt;p&gt;This is a controversial point. Trying to change software is like trying to change a car into a boat, it can be done with time and effort, but building a boat from scratch will be easier and the final boat will keep water out better, go faster, look nicer and generally be more fit for purpose. Data from &lt;span class="caps"&gt;NASA&lt;/span&gt; cited in &lt;a href="http://www.amazon.com/Facts-Fallacies-Software-Engineering-Development/dp/0321117425"&gt;Facts and Fallacies of Software Engineering&lt;/a&gt; suggest that if as little as 30% of an application needs to be changed, it is less time-consuming and expensive to start&amp;nbsp;over.&lt;/p&gt;

&lt;h2&gt;And&amp;nbsp;finally&amp;#8230;&lt;/h2&gt;

&lt;p&gt;There are many great books about software engineering, but I can personally recommend none more than Robert L Glass&amp;#8217;s &lt;a href="http://www.amazon.com/Facts-Fallacies-Software-Engineering-Development/dp/0321117425"&gt;Facts and Fallacies of Software Engineering&lt;/a&gt;.  It is a mine of empirical data about what makes software projects succeed and fail. If your company&amp;#8217;s business is making software (which it is if you&amp;#8217;re a web business), you need to read this&amp;nbsp;book.&lt;/p&gt;

&lt;p&gt;There are also a number of great websites about startups, few are finer than Eric Ries&amp;#8217; &lt;a href="http://startuplessonslearned.blogspot.com/"&gt;Startup Lessons Learned&lt;/a&gt;. Read it all. Twice.&amp;nbsp;Carefully.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.amazon.co.uk/New-Business-Road-Test-Entrepreneurs/dp/0273708058/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1254230145&amp;amp;sr=8-1"&gt;The New Business Road Test&lt;/a&gt; is a great tool for stopping yourself from diving in to an ill-advised venture. Reading it may save you a lot of time and money and prevent&amp;nbsp;hair-loss.&lt;/p&gt;

</description><pubDate>Tue, 19 May 2009 20:59:59 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/may/19/software-development-advice-startups/</guid><category>development</category><category>startups</category><feedburner:origLink>http://aftnn.org/2009/may/19/software-development-advice-startups/</feedburner:origLink></item><item><title>Django, Drupal, Webmachine: Different frameworks for different projects
</title><link>http://feedproxy.google.com/~r/afternoon/~3/Ff82POZPsJI/</link><description>&lt;p&gt;&lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; is an awesome framework but different projects have different needs. The last 2 projects I&amp;#8217;ve been involved with have been using &lt;a href="http://drupal.org/"&gt;Drupal&lt;/a&gt;. Other projects I&amp;#8217;m planning call for very RESTful designs. &lt;a href="http://bitbucket.org/justin/webmachine/wiki/Home"&gt;Webmachine&lt;/a&gt;, an Erlang framework, is a great fit for&amp;nbsp;these.&lt;/p&gt;

&lt;p&gt;I do still very much love Python and Django, perhaps even more that I&amp;#8217;m using &lt;span class="caps"&gt;PHP&lt;/span&gt; day to day. I miss the &lt;span class="caps"&gt;REPL&lt;/span&gt;. I miss first class functions. I miss Django&amp;#8217;s very tidy organisation of&amp;nbsp;code.&lt;/p&gt;

&lt;p&gt;Drupal is something I&amp;#8217;ve studiously avoided for a long time, thinking it to be a Zope-like mire. That&amp;#8217;s true to an extent: there are many versions and a lot of code. Drupal apps do have good separation of concerns. The internal organisation of modules and themes is useful, although there&amp;#8217;s a little bit too much function name magic going on (&amp;#8220;Why isn&amp;#8217;t my validator firing? Who knows!&amp;#8221;). I&amp;#8217;m interested in hooks, although I haven&amp;#8217;t needed them yet. The same concept has served Django hackers&amp;nbsp;well.&lt;/p&gt;

&lt;h2&gt;Leaky&amp;nbsp;abstractions&lt;/h2&gt;

&lt;p&gt;Django and Drupal are both leaky abstractions. It&amp;#8217;s easy to create great big joins with Django&amp;#8217;s &lt;span class="caps"&gt;ORM&lt;/span&gt;. Drupal generates a mammoth set of &lt;span class="caps"&gt;CSS&lt;/span&gt; and &lt;span class="caps"&gt;JS&lt;/span&gt; imports per page. Both of these can be addressed with programmer discipline, but sometimes it&amp;#8217;s nice to have a thinner level of abstraction to make you think carefully about each requirement and how best to implement it. Webmachine is such an abstraction. What it does provide, however, is system management built on top of Erlang and &lt;span class="caps"&gt;OTP&lt;/span&gt;. People doing scale (a group I&amp;#8217;m not a member of) find that writing the initial app is easy, scaling it is&amp;nbsp;hard.&lt;/p&gt;

&lt;h2&gt;Easy hacking, easy&amp;nbsp;scaling&lt;/h2&gt;

&lt;p&gt;Newer frameworks seek to make initial implementation easy and scaling easy too. Webmachine is undoubtedly somewhat harder to code for than Django, there are less batteries included, but, in theory at least, scaling is easier. Only a little of that is due to implementation, most is due to architectural style. Webmachine does get in your way a bit less when hacking RESTfully. Django does things like setting cookies on every hit, making caching harder, increasing load on your&amp;nbsp;app.&lt;/p&gt;

&lt;p&gt;I think the current leader for easy hacking, easy scaling is Google App Engine. The core of Django runs happily, the system scales to Google&amp;#8217;s infrastructure, deployment is very simple. &lt;span class="caps"&gt;GAE&lt;/span&gt; has one flaw though, porting to another platform involves work modifying code and extracting data. While the code scales effortlessly, scaling a business around that code seems harder. If your goals don&amp;#8217;t chime with Google&amp;#8217;s, you&amp;#8217;re stuck. Frameworks running on open source software stacks are more trustable and it&amp;#8217;s for this reason that &lt;span class="caps"&gt;EC2&lt;/span&gt; is so much more popular than &lt;span class="caps"&gt;GAE&lt;/span&gt; to&amp;nbsp;date.&lt;/p&gt;

</description><pubDate>Wed, 13 May 2009 13:26:02 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/may/13/django-drupal-webmachine-different-frameworks-different-projects/</guid><category>django</category><category>drupal</category><category>webmachine</category><feedburner:origLink>http://aftnn.org/2009/may/13/django-drupal-webmachine-different-frameworks-different-projects/</feedburner:origLink></item><item><title>Python syntax highlighting with Chili
</title><link>http://feedproxy.google.com/~r/afternoon/~3/G0JVsAvLUK8/</link><description>&lt;p&gt;I&amp;#8217;ve enabled syntax highlighting on this site using the very tidy &lt;a href="http://noteslog.com/chili/"&gt;Chili&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The standard distribution of Chili doesn&amp;#8217;t include a Python language definition (or Erlang, or Haskell&amp;#8230;), so I wrote&amp;nbsp;one.&lt;/p&gt;

&lt;p&gt;&lt;a href="/stuff/code/python.js"&gt;Download Python recipe for&amp;nbsp;Python&lt;/a&gt;&lt;/p&gt;

</description><pubDate>Fri, 24 Apr 2009 15:54:11 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/apr/24/python-syntax-highlighting-chili/</guid><category>chili</category><category>jquery</category><category>python</category><feedburner:origLink>http://aftnn.org/2009/apr/24/python-syntax-highlighting-chili/</feedburner:origLink></item><item><title>Use SSH public key authentication with Fabric
</title><link>http://feedproxy.google.com/~r/afternoon/~3/X7O-9pYGmeE/</link><description>&lt;p&gt;&lt;a href="http://www.nongnu.org/fab/"&gt;Fabric&lt;/a&gt; is a very useful Python tool for scripting administration of remote servers. Like &lt;a href="http://www.capify.org/"&gt;Capistrano&lt;/a&gt; it allows you to define tasks as a mixture of local and remote operations and then run them for lots of hosts, different groups of hosts,&amp;nbsp;etc.&lt;/p&gt;

&lt;p&gt;Increasingly I&amp;#8217;m using configuring &lt;code&gt;sshd&lt;/code&gt; to allow public key authentication only. Using this method makes your server more secure against increasingly common &lt;span class="caps"&gt;SSH&lt;/span&gt; brute force attacks. You can also configure an &lt;code&gt;ssh-agent&lt;/code&gt; app to allow password-less&amp;nbsp;logins.&lt;/p&gt;

&lt;p&gt;If you want your Fabric tasks to access machines using public key authentication, add something like to your&amp;nbsp;Fabfile:&lt;/p&gt;

&lt;pre&gt;&lt;code class="python"&gt;from paramiko import RSAKey

config.fab_user = "jhacker"
config.fab_pkey = RSAKey.from_private_key_file("/path/to/keyfile")&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple, and very&amp;nbsp;useful.&lt;/p&gt;

</description><pubDate>Fri, 24 Apr 2009 14:13:12 +0300</pubDate><guid isPermaLink="false">http://aftnn.org/2009/apr/24/use-ssh-public-key-authentication-fabric/</guid><category>fabric</category><category>ssh</category><feedburner:origLink>http://aftnn.org/2009/apr/24/use-ssh-public-key-authentication-fabric/</feedburner:origLink></item></channel></rss>

