<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: rants</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/rants.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2007-02-04T13:57:24+00:00</updated><author><name>Simon Willison</name></author><entry><title>Why you should be using disambiguated URLs</title><link href="https://simonwillison.net/2007/Feb/4/urls/#atom-tag" rel="alternate"/><published>2007-02-04T13:57:24+00:00</published><updated>2007-02-04T13:57:24+00:00</updated><id>https://simonwillison.net/2007/Feb/4/urls/#atom-tag</id><summary type="html">
    &lt;p&gt;Good URLs are important. The best URLs are &lt;a href="http://www.flickr.com/photos/drewm/280526490/"&gt;readable, reliable and hackable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the nice things about Rails, Django and other modern Web frameworks is that most of them encourage smart URL design. Rails has relatively smart defaults and a powerful routing system for custom URLs; Django forces you to think about URL design up front by defining them as regular expressions. Many of the definitive "Web 2.0" sites such as Flickr and del.icio.us also use well designed URLs. This is a positive trend, and long may it continue.&lt;/p&gt;

&lt;p&gt;There's one aspect of URL design that is often ignored. Good URLs should be &lt;em&gt;unambiguous&lt;/em&gt;. By that, I mean that any logical piece of content should have one and only one definitive URL, with any alternatives acting as a permanent redirect.&lt;/p&gt;

&lt;p&gt;This rule is frequently broken. Here are some examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;My Flickr photo stream lives at &lt;samp&gt;www.flickr.com/photos/simon/&lt;/samp&gt; and &lt;samp&gt;flickr.com/photos/simon/&lt;/samp&gt;&lt;/li&gt;
  &lt;li&gt;My del.icio.us account is at &lt;samp&gt;del.icio.us/simonw&lt;/samp&gt; and &lt;samp&gt;del.icio.us/simonw/&lt;/samp&gt;&lt;/li&gt;
  &lt;li&gt;The YDN Python Developer center lives at both &lt;samp&gt;http://developer.yahoo.com/python/&lt;/samp&gt; and &lt;samp&gt;http://developer.yahoo.com/python/index.html&lt;/samp&gt;&lt;/li&gt;
  &lt;li&gt;The Google AdSense sign-in page is at &lt;samp&gt;https://www.google.com/adsense/&lt;/samp&gt; and &lt;samp&gt;https://google.com/adsense/&lt;/samp&gt;. If you visit the latter you get a scary certificate warning (they really need to fix that).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each of the above cases, it's obvious to regular people that the URLs are the same. Unfortunately, from a technical point of view they are different and could quite feasibly serve up different content. This causes all kinds of problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Caches (both browser and intermediate proxies) can't improve performance if you request the same content from a different URL.&lt;/li&gt;
  &lt;li&gt;Browser can't show users their visited links.&lt;/li&gt;
  &lt;li&gt;Social link sharing sites such as del.icio.us can't accurately aggregate links to the same resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one in particular should catch your attention if you care about effectively promoting your site. Here's a random example, plucked from today's &lt;a href="http://del.icio.us/popular"&gt;del.icio.us popular&lt;/a&gt;. &lt;a href="http://www.convinceme.net/"&gt;convinceme.net&lt;/a&gt; is a new online debating site (tag clouds, gradient fills, rounded corners). It's listed in del.icio.us a total of &lt;strong&gt;four times&lt;/strong&gt;!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;samp&gt;http://www.convinceme.net/&lt;/samp&gt; has &lt;a href="http://del.icio.us/url/7baaee8f40da9c648c67d1b1bd0f7f1f"&gt;36 saves&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;samp&gt;http://www.convinceme.net/index.php&lt;/samp&gt; has &lt;a href="http://del.icio.us/url/26ee29f184ae25f089638efb33e28878"&gt;148 saves&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;samp&gt;http://convinceme.net/&lt;/samp&gt; has &lt;a href="http://del.icio.us/url/b1cd9926b9f30c89bdbce63882404495"&gt;211 saves&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;samp&gt;http://convinceme.net/index.php&lt;/samp&gt; has &lt;a href="http://del.icio.us/url/77ddf81a6c4906a53c7b993f5b86d1ed"&gt;38 saves&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined that's 433 saves; much more impressive, and more likely to end up at the top of a social sharing sites.&lt;/p&gt;

&lt;p&gt;Here's a useful rule of thumb:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links to (and within) your site should never, ever end with index.php / index.html / default.aspx / any default directory index filename.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The whole point those defaults is that you can link to the containing directory to see their content, resulting in a shorter and prettier URL. If you're linking to them directly you're missing out on a golden opportunity to disambiguate your URLs.&lt;/p&gt;

&lt;p&gt;Disambiguating your URLs isn't particularly difficult. The &lt;a href="http://no-www.org/"&gt;no-www site&lt;/a&gt; offers tips on having one domain name redirect to the other, and there are &lt;a href="http://rewrite.drbacchus.com/" title="mod_rewrite cookbook"&gt;various mod_rewrite techniques&lt;/a&gt; for achieving the desired effect as well. If mod_rewrite makes your hair stand on end, remember that if you are using a server-side scripting language such as PHP you can implement rewriting logic in your application code by examining the &lt;code&gt;$_ENV['PATH_INFO']&lt;/code&gt; variable or your platform's equivalent.&lt;/p&gt;

&lt;p&gt;Django sites get this behaviour for free, thanks to some default settings and Django's &lt;a href="http://www.djangoproject.com/documentation/middleware/#django-middleware-common-commonmiddleware"&gt;CommonMiddleware&lt;/a&gt;. You can that in action on this weblog: try &lt;a href="http://simonwillison.net/2007/Feb/4/"&gt;here&lt;/a&gt;, &lt;a href="http://www.simonwillison.net/2007/Feb/4"&gt;here&lt;/a&gt; and &lt;a href="http://simonwillison.net/2007/Feb/4"&gt;here&lt;/a&gt;.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/delicious"&gt;delicious&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/flickr"&gt;flickr&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rants"&gt;rants&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/urls"&gt;urls&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="delicious"/><category term="django"/><category term="flickr"/><category term="rants"/><category term="urls"/></entry><entry><title>Fjax: Just say no</title><link href="https://simonwillison.net/2006/Jun/25/fjax/#atom-tag" rel="alternate"/><published>2006-06-25T15:03:53+00:00</published><updated>2006-06-25T15:03:53+00:00</updated><id>https://simonwillison.net/2006/Jun/25/fjax/#atom-tag</id><summary type="html">
    &lt;p id="p-0"&gt;To my utter amazement, a decent amount of buzz appears to be building around a new "technology" called &lt;a href="http://www.fjax.net/"&gt;Fjax&lt;/a&gt; - much of it centred around &lt;a href="http://www.webmonkey.com/06/25/index4a.html" title="Webmonkey Q&amp;amp;A: Fjax"&gt;this interview on Webmonkey&lt;/a&gt;, but also benefiting from &lt;a href="http://radar.oreilly.com/archives/2006/06/fjax_ajax_with_flash.html" title="FJAX: Ajax with Flash"&gt;a mention&lt;/a&gt; on the O'Reilly Radar and of course the &lt;a href="http://digg.com/programming/FJAX_(Flash_AJAX)" title="FJAX (Flash + AJAX)"&gt;obligatory Digg story&lt;/a&gt;.&lt;/p&gt;

&lt;p id="p-1"&gt;Here's the catch: Fjax solves a non-existent problem. Here's the description from &lt;a href="http://www.fjax.net/?x=lnkExecutiveSummary.xml"&gt;the site&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote cite="http://www.fjax.net/?x=lnkExecutiveSummary.xml"&gt;&lt;p id="p-2"&gt;
Fjax is the lightweight, cross-browser, rapid-development methodology for Ajax-style web 2.0 development that puts a Flash engine under the hood (not in the presentation layer - read on) to handle realtime XML/HTML content updating.&lt;/p&gt;

&lt;p id="p-3"&gt;Fjax enables web 2.0 development, with true, asynchronous (x)HTML content updating without page refreshes. The trick is, it does it with less than 65 lines of code and works in most browsers. It can process multiple streams of data simultaneously, and has an incredibly small footprint (4K!).
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p id="p-4"&gt;So what does it actually do? It offers a replacement for the native browser XMLHttpRequest object that is slower, less fully-featured and does a bunch of crazy extra work behind the scenes. Ajax requests are instead made through an invisible Flash file that uses Flash to load the data, parse the XML, extract some CDATA and pass it back to JavaScript to replace a div.&lt;/p&gt;

&lt;p id="p-5"&gt;Kind of like Prototype's &lt;a href="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Updater"&gt;Ajax.Updater&lt;/a&gt; then.&lt;/p&gt;

&lt;p id="p-6"&gt;Why would you do this? According to the authors, doing this with JavaScript requires painful code forking. It certainly does if you write JavaScript like they do:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;
if (document.all) {
  //isIE
  document.all[ThisOutputDivID].innerHTML = objFjax;
} else {
  //isNotIE
  document.getElementById(ThisOutputDivID).innerHTML = objFjax;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p id="p-7"&gt;(The &lt;code&gt;document.all&lt;/code&gt; workaround is only needed by IE 4 - every subsequent IE version has supported &lt;code&gt;document.getElementById&lt;/code&gt;, part of the DOM specification.)&lt;/p&gt;

&lt;p id="p-8"&gt;They also claim that using Flash to load and parse XML is substantially faster than the native alternative:&lt;/p&gt;

&lt;blockquote&gt;&lt;p id="p-9"&gt;And of course, this stuff is SPEEDY. Vastly reduced code, crazy fast parsing &amp;amp; delivery, quick load/unload, and multiple simultaneous data streams means your final applications have some serious pep.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p id="p-10"&gt;They haven't done any benchmarks and I haven't either - but I would be amazed if this claim held up. Simply sending data between Flash and JavaScript is notoriously slow (see Brad &lt;a href="http://codinginparadise.org/weblog/2006/04/now-in-browser-near-you-offline-access.html"&gt;Neuberg's writeup&lt;/a&gt;) and I've heard bad thing's about Flash's XML parsing speed too. Not that they are really using any of the capabilities of XML - the actual data used to update the page is handed back in &lt;a href="http://www.fjax.net/content/Fjax_Content1.xml"&gt;one big CDATA block&lt;/a&gt;.&lt;/p&gt;

&lt;p id="p-11"&gt;The &lt;a href="http://www.fjax.net/?x=lnkExecutiveSummary.xml"&gt;executive summary&lt;/a&gt; builds its case on the idea that JavaScript is inconsistent, buggy and slow to develop. Bizarrely, making simple XMLHttpRequest calls (of the kind that Fjax is meant to replace) is one of the few parts of modern JavaScript for which that isn't true. The following is all the browser-forking code you need to cover every available major browser.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function createXMLHttpRequest() {
  if (typeof XMLHttpRequest != 'undefined') {
    return new XMLHttpRequest();
  }
  try {
    return new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      return new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) { }
  }
  return false;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p id="p-12"&gt;They boast that Fjax uses only 65 lines of JavaScript (plus 4KB of Flash). The equivalent functionality in pure JavaScript, including the above browser workaround, runs to less than half of that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function ajaxUpdate(url, id) {
  var xmlhttp = createXMLHttpRequest();
  if (xmlhttp) {
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4 &amp;amp;&amp;amp; xmlhttp.status == 200) {
        document.getElementById(id).innerHTML = xmlhttp.responseText;
      }
    }
    xmlhttp.open("GET", url, true);
    xmlhttp.send(null);
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p id="p-13"&gt;Another quote:&lt;/p&gt;

&lt;blockquote&gt;&lt;p id="p-14"&gt;
Using a Flash engine for XML parsing and (x)HTML content delivery reduces approximately 90% of the redundant cross-browser-supporting XML-related code usually associated with standard Ajax development. That in itself is HUGE.
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p id="p-15"&gt;That 90% looks like a rectal approximation to me.&lt;/p&gt;

&lt;p id="p-16"&gt;In its present form, Fjax offers absolutely nothing of value to front end developers. Even the idea of using invisible Flash components to make new functionality available to JavaScript isn't a new one - &lt;a href="http://codinginparadise.org/weblog/2006/04/now-in-browser-near-you-offline-access.html"&gt;dojo.storage&lt;/a&gt; takes advantage of Flash's ability to store large amounts of data in an offline cache, while &lt;a href="http://blog.monstuff.com/FlashXMLHttpRequest"&gt;FlashXMLHttpRequest&lt;/a&gt; makes cross-domain HTTP requests possible. There's a lot to be said for using Flash in this way (I'd love to see someone make the Flash accessibility APIs available to JavaScript), but Fjax is not a useful demonstration.&lt;/p&gt;

&lt;p id="p-17"&gt;I'm not normally given to debunking crazy technology ideas - mainly because there are so many out there that it would be a full-time job - but this thing is so obviously broken I thought it best to try and nip it in the bud.&lt;/p&gt;

&lt;p id="p-18"&gt;One last thing: their technique doesn't work in either Opera 9/Mac or Konqueror, both of which support vanilla Ajax just fine.&lt;/p&gt;

&lt;p id="p-19"&gt;&lt;strong&gt;Update:&lt;/strong&gt; Steve McDonald, one of the Fjax authors, has posted &lt;a href="http://radar.oreilly.com/archives/2006/06/fjax_ajax_with_flash.html#c115463"&gt;a follow-up comment&lt;/a&gt; on the O'Reilly Radar entry. He argues that the getVariable API they are using avoids the performance issues communicating between Flash and JavaScript (I have not verified this) and points out that code-forking for XML parsing is more likely with complex documents (that's why I like &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt;). They have removed the 90% claim from the site.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/fjax"&gt;fjax&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/flash"&gt;flash&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rants"&gt;rants&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="fjax"/><category term="flash"/><category term="javascript"/><category term="rants"/></entry></feed>