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

<channel>
	<title>Calcatraz Blog &#187; Development</title>
	<atom:link href="http://www.calcatraz.com/blog/category/development/feed" rel="self" type="application/rss+xml" />
	<link>http://www.calcatraz.com/blog</link>
	<description>Towards an optimized life</description>
	<lastBuildDate>Mon, 30 Jan 2012 20:53:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Site Review: Signal vs Noise</title>
		<link>http://www.calcatraz.com/blog/site-review-signal-vs-noise-211?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=site-review-signal-vs-noise</link>
		<comments>http://www.calcatraz.com/blog/site-review-signal-vs-noise-211#comments</comments>
		<pubDate>Thu, 08 Dec 2011 23:09:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[37signals]]></category>
		<category><![CDATA[Darren Rowse]]></category>
		<category><![CDATA[Rework]]></category>
		<category><![CDATA[websites]]></category>

	<!-- AutoMeta Start -->
	<category>technical</category>
	<category>noise</category>
	<category>signal</category>
	<category>traffic</category>
	<category>complaints</category>
	<category>design</category>
	<category>topics</category>
	<category>stats</category>
	<category>technical</category>
	<category>noise</category>
	<category>signal</category>
	<category>traffic</category>
	<category>complaints</category>
	<category>design</category>
	<category>topics</category>
	<category>stats</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=211</guid>
		<description><![CDATA[In an attempt to improve this blog, I&#8217;m currently doing Darren Rowse&#8217;s 31 day better blog challenge. Today&#8217;s task is to review an existing blog (in a similar niche) and answer a few questions about it. I&#8217;ve picked Signal vs Noise, a blog on web design by the 37 signals guys. These are the same [...]]]></description>
			<content:encoded><![CDATA[<p>In an attempt to improve this blog, I&#8217;m currently doing Darren Rowse&#8217;s <a href="http://www.problogger.net/31dbbb-workbook/">31 day better blog challenge</a>. Today&#8217;s task is to review an existing blog (in a similar niche) and answer a few questions about it. I&#8217;ve picked <a href="http://37signals.com/svn">Signal vs Noise</a>, a blog on web design by the 37 signals guys. These are the same guys behind web apps such as Basecamp, and book such as Rework &#8211; which made it onto into my <a title="My Top 10 (Mainly Online) Business Books of The Year" href="http://www.calcatraz.com/blog/my-top-10-mainly-online-business-books-of-the-year-200">top 10 business books of the year</a>.</p>
<p><img class="alignleft size-medium wp-image-231" title="Signal vs Noise" src="http://www.calcatraz.com/blog/wp-content/uploads/svn-297x300.png" alt="Signal vs Noise" width="297" height="300" /></p>
<p><strong>Content:</strong></p>
<p><strong></strong><em>What topics are they covering?</em></p>
<p>According to their own tag line: design, business, experience, simplicity, the web, culture, and more.</p>
<p><em>What topics are they ignoring?</em></p>
<p>Despite being an online business, they don&#8217;t seem to write much about (or do) much in the way of traditional SEO / link building, etc.</p>
<p><em>What voice/style do they post in?</em></p>
<p>Posts are generally informal, with a cut-the-crap attitude.</p>
<p><em>How often are they posting?</em></p>
<p>Once or twice a week on average.</p>
<p><em>What level are they pitching their posts at (beginners, advanced etc)</em></p>
<p>Their posts are typically high level, avoiding nitty gritty technical details. Even the technical articles tackle whatever specific technical issue at a high level.</p>
<p><strong>Reader Engagement:</strong></p>
<p><strong></strong><em>What topics generate most conversation?</em></p>
<p>It seems to be those that are somewhat political in nature, or relate to significant new product features.</p>
<p><em>What styles of posts seem to connect with readers best?</em></p>
<p>Posts of a technical nature seem to produce the most in-depth comments.</p>
<p><em>What questions are readers asking in comments?</em></p>
<p>Asking for further details on the topics discussed.</p>
<p><em>What complaints do you see readers making in comments?</em></p>
<p>Complaints about product features / changes required. Also complaints about nonsensical topics / lines of argument.</p>
<p><em>What tools/mediums is the site using (eg: are they using Twitter, forums etc)</em></p>
<p>Twitter widget showing latest tweets. RSS feed and stats counter. Comments. Newsletter signup. Site search.</p>
<p><strong>Design:</strong></p>
<p><strong></strong><em>What first impression does their design give?</em></p>
<p>Clean, colourful.</p>
<p><em>What have they done well? What have they done poorly?</em></p>
<p>Good emphasis / de-emphasis / elimination of page elements. Somewhat confusing &#8216;mini-posts&#8217; which visually appear to belong to the major post above, but which I don&#8217;t think actually do. RSS feed blends with ad block &#8211; I wasn&#8217;t sure if it was part of the ad, or part of the site, until I hovered over it to see the URL.</p>
<p><em>What Options do they give readers to subscribe?</em></p>
<p>Newsletter, RSS, link to follow on twitter.</p>
<p><strong>Monetization:</strong></p>
<p><strong></strong><em>what advertisers are targeting this blog?</em></p>
<p>IT ads.</p>
<p><em>what type of affiliate programs are they promoting?</em></p>
<p>None that I can see, but promote their own web apps and books quite prominently.</p>
<p><strong>Traffic:</strong><br />
3,412 on Alexa for the entire 37signals domain, with 16k sites linking in. Traffic has decreased sightly (by around 10%) over the past 3 months.</p>
<p><strong>SEO:</strong></p>
<p><strong></strong><em>Who is linking to this blog? (use the link:www.blogurl.com command in Google to find out)</em></p>
<p>Lots of diverse sites, especially tech / design blogs.</p>
<p><em>What does their source code reveal about how they’ve set up their site</em></p>
<p>Very clean HTML source, with defined meta tags, etc.</p>
<p><em>If they have an open or unlocked stats package what can you learn from their stats? What pages are popular? Where does their incoming traffic come from?</em></p>
<p>Not available.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/site-review-signal-vs-noise-211/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case Study: Speeding up the Calcatraz API</title>
		<link>http://www.calcatraz.com/blog/case-study-speeding-up-the-calcatraz-api-168?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=case-study-speeding-up-the-calcatraz-api</link>
		<comments>http://www.calcatraz.com/blog/case-study-speeding-up-the-calcatraz-api-168#comments</comments>
		<pubDate>Sun, 14 Aug 2011 21:31:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category></category>
	<category></category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=168</guid>
		<description><![CDATA[I wanted the Calcatraz API to be fast enough to be usefully callable within a single page request. To this end, I performed some optimisation and was able to reduce the runtime of an API call to around 1/6 of its original time. To establish a baseline, I looked at the fastest page load time [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.calcatraz.com/calculator/api"><img class="alignleft size-medium wp-image-236" title="Calcatraz API" src="http://www.calcatraz.com/blog/wp-content/uploads/api-300x244.png" alt="Calcatraz API" width="300" height="244" /></a>I wanted the Calcatraz API to be fast enough to be usefully callable within a single page request. To this end, I performed some optimisation and was able to reduce the runtime of an API call to around 1/6 of its original time.</p>
<p>To establish a baseline, I looked at the fastest page load time possible on my local host. This was around 12ms avg for a minimal html page (containing the word &#8216;test&#8217; only) and around 15-17ms for a minimal php page. Note that I cleared the cache after each request. My aim then is to get the api working on localhost at something approaching these times. Any additional delay in the production environment would presumably be down to dns / latency / shared hosting, which I can deal with separately.</p>
<p>I then tested the api for its response time. A simple calculation such as 3*3 gave a response time of 250-320ms. Not bad, but not as good as I would like. As a start, I aimed to reduce it below 50ms. This should be done with improvements which benefit all calculations, rather than being achieved with caching of previously seen answers (which I want to have as a separate speedup).</p>
<p><strong>Output Buffering</strong></p>
<p>Using webgrind, I profiled the call. The call took 406ms this time (presumably slowed by the profiling code). It showed that the slowest individual function call (i.e. self-cost) was the single database call, taking 147ms. This call is used to simply log the calculation made &#8211; it isn&#8217;t actually used in the production of the calculation. As a result, it can be moved to the end of the code and executed after the output has been sent by the user. That way, though the time to run the php script hasn&#8217;t improved, the time until the user gets their answer has.</p>
<p>I did this, using the following PHP code to send the output buffer contents to the user and close the connection:</p>
<p>// Initialise content buffering (using compression)<br />
ob_start(&#8216;ob_gzhandler&#8217;);</p>
<p>&#8230; code to generate user output goes here &#8230;</p>
<p>// close the http connection and send the data to the user<br />
echo str_pad(&#8221;, 1024); // pad so IE and Chrome will render short answers<br />
header(&#8220;Connection: close&#8221;);<br />
header(&#8220;Content-Length: &#8220;.ob_get_length());<br />
ob_end_flush(); // send the results to the user<br />
ob_flush();<br />
flush();</p>
<p>&#8230; code to process behind the scenes goes here &#8230;</p>
<p>The result of this change was that the response time dropped from 250-320ms to around 110ms &#8211; more than halving the response time.</p>
<p><strong>File Inclusion</strong></p>
<p>Going back to the webgrind profile output, I found that the next largest bottleneck was a bunch of file inclusions I was doing at the start of the code. These include library functions which I store with one file per function. The time taken to include the files seems to vary between about 30 and 60ms.</p>
<p>Originally the files were included using the include_once() function. I changed this to the include() function to remove the (unnecessary) check for a previous inclusion. This seemed to slightly reduce the time to load to 25-30ms. While I will probably inline the functions at a later time, having them separate makes development easier. So until I sort out a solution I&#8217;ll leave it as it is.</p>
<p><strong>Function Caching</strong></p>
<p>The next target for improvement was a function which consumed around 20ms per page load. Reviewing the function revealed that while caching was in use on the function return values, not all return paths were being cached &#8211; essentially the function was traversing a tree structure and caching the nodes but not the leaves. By adding caching I was able to cut the time used by the function to around 8ms. With the changes so far, the time for the api call has now dropped from 250-320ms to around 65-90ms. As an added bonus, I was able to make use of PHP static variables to replace the previous, more clumsy, caching method (I learned how to do this while studying the Drupal codebase). And as a further bonus I was able to remove two of the library functions being included (as discussed above), very slightly addressing that problem.</p>
<p><strong>Dead Code Elimination</strong></p>
<p>While it might seem excessive, I continued to try and further reduce the time towards my 50ms goal. I took a look at one frequently called function which was using around 10ms. It was being called from two locations. The vast majority of the calls were coming from a function which, on inspection, turned out not to actually need to call it. Removing this call all but eliminated the 10ms usage.</p>
<p><strong>File Inclusion Revisited</strong></p>
<p>By this point, the file inclusion issue below has become the clear bottleneck, accounting for over a third of the total runtime of the API call. So I decided to bite the bullet and tackle it. I realised that Toyota-style lean principles suggest that I should combine the many files into fewer as the multiple calls do not add value to the user and are therefore &#8216;waste&#8217;. While it benefits me as a developer, there are other ways I can achieve the same effect. A short-term approximation is to use the &#8216;fold all&#8217; feature of notepad++ to collapse the functions into a browseable list. If I need something more closely resembling explorer&#8217;s view of the files (e.g. so I can work on two or more functions in a tabbed view, I can easily write something which will let me do it. I combined the functions into four larger library files (corresponding to the four directories the function files were stored in), and changed the code to include just these. Immediately the time cost of loading the functions dropped form around 70ms to around 7ms. I could take it further and combine these four files, but I think it would complicate development more than it would benefit runtime.</p>
<p><strong>Conclusion</strong></p>
<p>Through a series of optimisations I was able to reduce the time the server takes to feed the user a response to a simple API query from 250-320ms to only 45ms. This was done exclusively through optimisations which simplified the codebase, or just moved things around in a way that will have minimal impact on ease of development. While other potential optimisations exist to reduce the time requirement further, they will require more involved development work and so are not going to be carried out at this time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/case-study-speeding-up-the-calcatraz-api-168/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing XDebug and Webgrind for XAMPP on Windows</title>
		<link>http://www.calcatraz.com/blog/installing-xdebug-and-webgrind-for-xampp-on-windows-164?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=installing-xdebug-and-webgrind-for-xampp-on-windows</link>
		<comments>http://www.calcatraz.com/blog/installing-xdebug-and-webgrind-for-xampp-on-windows-164#comments</comments>
		<pubDate>Fri, 12 Aug 2011 22:06:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>program</category>
	<category>xampp</category>
	<category>xdebug</category>
	<category>ini</category>
	<category>instructions</category>
	<category>vc6</category>
	<category>windows</category>
	<category>windows</category>
	<category>program</category>
	<category>xampp</category>
	<category>xdebug</category>
	<category>ini</category>
	<category>instructions</category>
	<category>vc6</category>
	<category>windows</category>
	<category>windows</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=164</guid>
		<description><![CDATA[When XDebug is installed it will produce a file each time you load a PHP webpage on your localhost. This file contains detailed timing information on which functions the PHP file called and for how long. This is essential information for improving the speed of a website as it allows you to pinpoint exactly which [...]]]></description>
			<content:encoded><![CDATA[<p>When XDebug is installed it will produce a file each time you load a PHP webpage on your localhost. This file contains detailed timing information on which functions the PHP file called and for how long. This is essential information for improving the speed of a website as it allows you to pinpoint exactly which part of your code is slowing your site down the most. Webgrind provides an easy to use web view of the information produced by XDebug.</p>
<p>I&#8217;ve installed this combination on several web servers in the past and it has always proved a bit more time-consuming and painful than it really should be. To save myself, and hopefully others, from similar pain in the future, here are the steps I used this time round. Note that these instructions apply to installing XDebug and Webgrind for use with XAMPP on Windows.</p>
<p>1. Create a php file under your localhost webroot containing the command:</p>
<p>&lt;?php phpinfo() ?&gt;</p>
<p>2. Open the file in a browser &#8211; it should display a load of configuration about your php setup.</p>
<p>3. Select and copy all the content of that page</p>
<p>4. Paste it into the textbox on this page: http://www.xdebug.org/find-binary.php</p>
<p>5. Click &#8216;Analyse my phpinfo() output</p>
<p>6. This will generate some output like:</p>
<p>Summary<br />
Xdebug installed: no<br />
Server API: Apache 2.0 Handler<br />
Windows: yes &#8211; Compiler: MS VC6 &#8211; Architecture: x86<br />
Zend Server: no<br />
PHP Version: 5.3.5<br />
Zend API nr: 220090626<br />
PHP API nr: 20090626<br />
Debug Build: no<br />
Thread Safe Build: yes<br />
Configuration File Path: C:\Windows<br />
Configuration File: C:\Program Files\xampp\php\php.ini<br />
Extensions directory: C:\Program</p>
<p>Instructions</p>
<p>Download php_xdebug-2.1.2-5.3-vc6.dll<br />
Move the downloaded file to C:\Program<br />
Edit C:\Program Files\xampp\php\php.ini and add the line<br />
zend_extension = C:\Program\php_xdebug-2.1.2-5.3-vc6.dll<br />
Restart the webserver</p>
<p>7. Before following these instructions, note that they are wrong! The extension dir path has been truncated. You will need to locate your extension dir and update the instructions accordingly. For instance, my extension dir is at: C:\Program Files\xampp\php\ext</p>
<p>This gives the revised instructions:</p>
<p>Download php_xdebug-2.1.2-5.3-vc6.dll<br />
Move the downloaded file to C:\Program Files\xampp\php\ext\<br />
Edit C:\Program Files\xampp\php\php.ini and add the line<br />
zend_extension = &#8220;C:\Program Files\xampp\php\ext\php_xdebug-2.1.2-5.3-vc6.dll&#8221;<br />
Restart the webserver</p>
<p>8. Follow these instructions, but to save a bit of time you don&#8217;t yet need to restart the webserver. Also keep php.ini open.</p>
<p>9. Add the following to php.ini to run XDebug every time a page is requested:<br />
xdebug.profiler_enable = 1</p>
<p>10. Still in php.ini, Change the line:<br />
xdebug.profiler_output_name = &#8220;xdebug_profile.%R::%u&#8221;<br />
To:<br />
xdebug.profiler_output_name = &#8220;xdebug_profile.%R.%u&#8221;</p>
<p>This is because windows can&#8217;t handle the colons in the file name, and won&#8217;t write the files otherwise. This took me a while to figure out.</p>
<p>11. Now restart the Apache web server</p>
<p>12. It should be working. To test, load (in a browser) the localhost page you want to profile. If all is well, XDebug will produce a file named xdebug_profile.xxxx.xxxx or similar in the XDebug output directory. (For me the directory is &#8220;C:\Program Files\xampp\tmp&#8221;, but you find / set the output dir from the php.ini line which looks like: xdebug.profiler_output_dir = &#8220;C:\Program Files\xampp\tmp&#8221;).</p>
<p>13. Install webgrind:</p>
<p>* Download webgrind from https://github.com/jokkedk/webgrind (use the &#8216;downloads&#8217; button).<br />
* Extract webgrind to a folder accessible to the webserver.<br />
* Start using webgrind by browsing to the URL of your webgrind install, e.g. http://localhost/webgrind.</p>
<p>If all has gone well you should now be able to use webgrind to view the profile information for the page you loaded in step 12.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/installing-xdebug-and-webgrind-for-xampp-on-windows-164/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Apache mod_rewrite encoded slash problem</title>
		<link>http://www.calcatraz.com/blog/the-apache-mod_rewrite-encoded-slash-problem-152?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-apache-mod_rewrite-encoded-slash-problem</link>
		<comments>http://www.calcatraz.com/blog/the-apache-mod_rewrite-encoded-slash-problem-152#comments</comments>
		<pubDate>Sun, 31 Jul 2011 00:36:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>txt|xml</category>
	<category>encoded</category>
	<category>urls</category>
	<category>encoding</category>
	<category>url</category>
	<category>mod_rewrite</category>
	<category>api</category>
	<category>apache</category>
	<category>txt|xml</category>
	<category>encoded</category>
	<category>urls</category>
	<category>encoding</category>
	<category>url</category>
	<category>mod_rewrite</category>
	<category>api</category>
	<category>apache</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=152</guid>
		<description><![CDATA[The Aim &#160; I&#8217;ve been working on an API for the new version of Calcatraz (both API and new version coming soon). As part of this, I&#8217;ve been trying to configure the API to use nice URLs. This has caused me to bump up against a tricky problem in Apache&#8217;s mod_rewrite module. I want to [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The Aim</strong></p>
<p><img class="alignright size-medium wp-image-259" title="Apache HTTP Server" src="http://www.calcatraz.com/blog/wp-content/uploads/apache1-300x230.png" alt="Apache HTTP Server" width="300" height="230" /></p>
<p>&nbsp;</p>
<p>I&#8217;ve been working on an API for the new version of Calcatraz (both API and new version coming soon). As part of this, I&#8217;ve been trying to configure the API to use nice URLs. This has caused me to bump up against a tricky problem in Apache&#8217;s mod_rewrite module.</p>
<p>I want to be able to accept URLs containing a calculation such as:</p>
<pre>http://www.calcatraz.com/api/calc/3*3.txt</pre>
<p>&nbsp;</p>
<p>And redirect it to a script which can extract the calculation (3*3) and the required format (in this case plain text &#8216;txt&#8217;).</p>
<p><strong>The Basics</strong></p>
<p>For the case above it can be done without problem, you just use a .htaccess redirect rule such as:</p>
<pre>RewriteRule calc/ api.php [L]</pre>
<p>&nbsp;</p>
<p>which calls api.php to serve the page. Then in api.php you parse the $_SERVER['REQUEST_URI'] variable &#8211; which contains the original url &#8211; and extract the various parts. Alternatively you can get a bit more complex in mod_rewrite and do the redirect and parsing in one, with something like:</p>
<pre>RewriteRule calc/(.+)\.(txt|xml)$ api.php?calc=$1&amp;format=$2 [L]</pre>
<p>&nbsp;</p>
<p><strong>The Problem</strong></p>
<p>So far, so good. But this breaks down when the calculation contains characters with special meaning in URLs, such as &#8216;/&#8217;, &#8216;?&#8217;, etc. My initial thought was to require that the calculation is url-encoded before inclusion in the API URL. This works for the likes of &#8216;?&#8217;. Encoding a slash is a different matter. The encoded URL for 3/3 would be:</p>
<pre>http://www.calcatraz.com/api/calc/3%2F3.txt</pre>
<p>&nbsp;</p>
<p>Here the %2F is the urlencoded form of &#8216;/&#8217;.</p>
<p>This seems like it should be passed through to the api.php script, but it isn&#8217;t. Instead a 404 not found page is found. It turns out that this is <a title="Apache bug discussion on mod_rewrite slash encoding issue" href="https://issues.apache.org/bugzilla/show_bug.cgi?id=34602">a known bug</a> in Apache / mod_rewrite.</p>
<p>No matter what I tried, there seems to be no way to redirect an API url containing a %2F to a particular script.</p>
<p><strong>The Solution(s)</strong></p>
<p>1) What does work is to perform a double url-encoding of the calculation before placing it in an API URL. So the api call to get the answer for 3/3 would be:</p>
<pre>http://www.calcatraz.com/api/calc/3%252f3.txt</pre>
<pre></pre>
<p>&nbsp;</p>
<p>This works, redirecting to the script and allowing us to extract the calculation and get its original form by performing a single url-decoding (as Apache / mod_rewrite performs one level of decoding implicitly). The main problem with it is that the URLs are pretty messy, and the user has to be asked to perform a double url-encoding. It also makes the URLs less obviously hackable / readable.</p>
<p>2) We can remove the need for the user to perform a double url-encoding by replacing it with a single base-64 encoding. This slightly tidies up the client-side API calls, but it means the URLs are completely inscrutable - the user can&#8217;t easily play around with them at all.</p>
<p>3) Since the slash will actually work without any encoding (it is only other characters as &#8216;?&#8217; which must be encoded), we could create  a custom version of urlencode which encodes everything normally encoded, other than slashes. This would yield the most readable URLs, but significantly complicates things for the user.</p>
<p>4) Switch web servers. As discovered in <a title="ServerFault mod_rewrite url encoding issue discussion" href="http://serverfault.com/questions/295664/mod-rewrite-not-working-with-url-encoded-values">this ServerFault discussion</a> I&#8217;ve been having on the issue, while it affects Apache, it doesn&#8217;t affect some other servers such as <a title="NGINX web server writeup at Pingdom.com" href="http://royal.pingdom.com/2010/02/23/nginx-the-little-russian-web-server-taking-on-the-giants/">nginx</a>.</p>
<p><strong>5) Update: Okay, thanks to the guys over at ServerFault, I now have the answer. By default Apache decodes encoded slashes (the problem). This behaviour can be disabled by adding the following to Apache&#8217;s httpd.conf file (or the relevant vhost configuration):</strong></p>
<pre><strong>AllowEncodedSlashes On</strong></pre>
<p>&nbsp;</p>
<p><strong>Conclusion</strong></p>
<p>I haven&#8217;t tested it on my public web server yet (only my dev server), but all being well Solution 5 is going to be the winner. Look out for the API, coming soon along with nice URLs, and a new version of <a title="Calcatraz, online calculator" href="http://www.calcatraz.com">Calcatraz calculator</a>.</p>
<p><strong>Side Note</strong></p>
<p>Interestingly, it seems that WordPress also falls prey to this issue. I originally posted this article with the term %2F in the title. WordPress took this title and url-decoded it to produce the URL &#8220;slug&#8221; for the post &#8211; which now contained a slash. When the slug is used in the permalink of the page title it is URL encoded back up, and clicking on the link then requests a URL containing a %2F. Because wordpress makes use of redirects, then as seen before, the redirect fails and a 404 error is returned. So it was not possible to actually view the post!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/the-apache-mod_rewrite-encoded-slash-problem-152/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to add dots and shorten a string</title>
		<link>http://www.calcatraz.com/blog/how-to-add-dots-and-shorten-a-string-129?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-add-dots-and-shorten-a-string</link>
		<comments>http://www.calcatraz.com/blog/how-to-add-dots-and-shorten-a-string-129#comments</comments>
		<pubDate>Sat, 06 Mar 2010 15:42:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>str</category>
	<category>preg_replace</category>
	<category>dots</category>
	<category>spot</category>
	<category>strlen</category>
	<category>variable</category>
	<category>function</category>
	<category>shorter</category>
	<category>str</category>
	<category>preg_replace</category>
	<category>dots</category>
	<category>spot</category>
	<category>strlen</category>
	<category>variable</category>
	<category>function</category>
	<category>shorter</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=129</guid>
		<description><![CDATA[While working on the back-end Calcatraz management system, I came across a situation where I wanted to display strings, but if they were too long I wanted to truncate them and add three dots (ellipsis) to the end to show that this had occurred. I first got on Google and looked for a solution. The [...]]]></description>
			<content:encoded><![CDATA[<p>While working on the back-end Calcatraz management system, I came across a situation where I wanted to display strings, but if they were too long I wanted to truncate them and add three dots (ellipsis) to the end to show that this had occurred.</p>
<p>I first got on Google and looked for a solution. The best (as in most brief) solution I found could be distilled down to this:</p>
<pre>(strlen($str)&gt;10)?substr_replace($str,'...',10):$str;</pre>
<pre></pre>
<div>It&#8217;s a bit clumsy, and contains the variable name three times, so would become quite long if the variable name was itself long. It would probably be best wrapped in a function to keep things clean, even if only used once or twice. I decided to try and do better. My first attempt was:</div>
<pre></pre>
<pre>(strlen($str)&gt;10)?substr($str,0,10).'...':'';</pre>
<div></div>
<div>It&#8217;s shorter and only contains the variable name two times. However, it&#8217;s still not great. If it was inlined in code it is difficult to spot where it starts and finishes, so again wrapping it in a function call would probably be the best way to go.</div>
<div>I then realised I could achieve the same thing  with a single call to preg_replace(), like so:</div>
<pre></pre>
<pre>preg_replace('/(.{10}).*/', '\\1...', $str);</pre>
<p>This is shorter still, only uses the variable name once and is a single function call making it easier to spot the start and end. It&#8217;s not perfectly descriptive, but the second argument in particular does hint at it&#8217;s function. I&#8217;d be happy using this inline if it was only to be used a couple of times (and the surrounding code was otherwise quite straightforward).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/how-to-add-dots-and-shorten-a-string-129/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Another Quick Tip: inline divs in IE</title>
		<link>http://www.calcatraz.com/blog/another-quick-tip-inline-divs-in-ie-121?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=another-quick-tip-inline-divs-in-ie</link>
		<comments>http://www.calcatraz.com/blog/another-quick-tip-inline-divs-in-ie-121#comments</comments>
		<pubDate>Sun, 07 Feb 2010 16:27:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>inline</category>
	<category>elemid</category>
	<category>display</category>
	<category>block</category>
	<category>firefox</category>
	<category>versions</category>
	<category>tested</category>
	<category>possibly</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=121</guid>
		<description><![CDATA[In Firefox, it is easy to create an inline div (i.e. a div which adjusts its width to fit its contents). You just do this: div#elemid { display: inline-block; } However, it doesn&#8217;t work in IE. It took me a while to figure out how to get it working, so here&#8217;s the solution: div#elemid { [...]]]></description>
			<content:encoded><![CDATA[<p>In Firefox, it is easy to create an inline div (i.e. a div which adjusts its width to fit its contents). You just do this:</p>
<pre>div#elemid { display: inline-block; }</pre>
<p>However, it doesn&#8217;t work in IE. It took me a while to figure out how to get it working, so here&#8217;s the solution:</p>
<pre>div#elemid { display: inline-block; *display: inline; zoom: 1; }</pre>
<p>It works for the latest versions of IE, Firefox and Chrome (and possibly others &#8211; I haven&#8217;t tested yet).</p>
<p>Hopefully that&#8217;ll save someone some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/another-quick-tip-inline-divs-in-ie-121/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Quick Tip: Webpage Simplification</title>
		<link>http://www.calcatraz.com/blog/a-quick-tip-webpage-simplification-112?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-quick-tip-webpage-simplification</link>
		<comments>http://www.calcatraz.com/blog/a-quick-tip-webpage-simplification-112#comments</comments>
		<pubDate>Sun, 07 Feb 2010 13:07:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[simplify]]></category>

	<!-- AutoMeta Start -->
	<category>table</category>
	<category>border</category>
	<category>shot</category>
	<category>homepage</category>
	<category>solid</category>
	<category>image</category>
	<category>excess</category>
	<category>screenshots</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=112</guid>
		<description><![CDATA[If your web pages have a large number of nested div and table tags you may end up wondering whether they are all really necessary, and whether you might not be able to get by with less. While you could run through your code and assess each one individually and decide if it can be [...]]]></description>
			<content:encoded><![CDATA[<p>If your web pages have a large number of nested div and table tags you may end up wondering whether they are all really necessary, and whether you might not be able to get by with less. While you could run through your code and assess each one individually and decide if it can be removed, there is a quicker, easier way to approach the problem. Simply add the following right at the end of your CSS definitions:</p>
<pre>table { border: 1px solid red; }</pre>
<pre>div { border: 1px solid green; }</pre>
<p>This will draw a border round each div and table on your page and let you visually see which are really necessary. It also works better than looking at each table / div in turn as often each seems necessary; it is only when you look at the big picture that you see that two or more can be combined.</p>
<p>As an illustration, here are the before and after screenshots when I applied this to the Calcatraz homepage. The excess tables / divs can be seen in the before shot (click on the image to see it full size). Notice how I&#8217;ve been able to two of them in the after shot, leading to shorter, cleaner html, with more of the presentation being handled in CSS where it should be.</p>
<p>Before:</p>
<p style="text-align: center;"><a href="http://www.calcatraz.com/calcatraz/blog/wp-content/uploads/2010/02/before1.jpg"><img class="aligncenter size-medium wp-image-116" style="border: 1px solid black;" title="The Calcatraz Homepage - Before" src="http://www.calcatraz.com/calcatraz/blog/wp-content/uploads/2010/02/before1-300x162.jpg" alt="The Calcatraz Homepage - Before" width="300" height="162" /></a></p>
<p>After:</p>
<p style="text-align: center;"><a href="http://www.calcatraz.com/calcatraz/blog/wp-content/uploads/2010/02/after.jpg"><img class="aligncenter size-medium wp-image-117" style="border: 1px solid black;" title="The Calcatraz Homepage - After" src="http://www.calcatraz.com/calcatraz/blog/wp-content/uploads/2010/02/after-300x162.jpg" alt="The Calcatraz Homepage - After" width="300" height="162" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/a-quick-tip-webpage-simplification-112/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Defining Website Value</title>
		<link>http://www.calcatraz.com/blog/defining-website-value-100?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=defining-website-value</link>
		<comments>http://www.calcatraz.com/blog/defining-website-value-100#comments</comments>
		<pubDate>Sat, 30 Jan 2010 09:53:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>bound</category>
	<category>lower</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://www.calcatraz.com/blog/?p=100</guid>
		<description><![CDATA[Recently I attempted to define in as objective a way as possible how much value my online calculator is providing to its users. The idea is to come up with an equation which gives me a &#8216;score&#8217; of how much value has been provided to users. With this, it will then be possible to optimise [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I attempted to define in as objective a way as possible how much value my <a href="http://www.calcatraz.com">online calculator</a> is providing to its users. The idea is to come up with an equation which gives me a &#8216;score&#8217; of how much value has been provided to users. With this, it will then be possible to optimise the site to provide as much value as possible. For instance, when considering two possible improvements I can use the equation to estimate the likely increase in value. That then lets me know which one to go ahead with (the one likely to be of most value to the users).</p>
<p>At the end of this post are the notes I made while trying to figure it out. They&#8217;re probably not of any use to anyone, but I though I&#8217;d share them. Before that, though, I want to outline the process I went though as hopefully this will be a bit more useful.</p>
<h3><strong>Step 1: Identify the main source of value you provide</strong></h3>
<div>The first thing I did was to figure out what user actions provide the main source of value. For me, since my site is a calculator, this was clear. Value is provided when a user enters a calculation and receives an answer. There are other potential sources of value (e.g. someone may find some value in one of my blog posts). But I want to focus on the calculations as my main value proposition. I may include other sources of value later, but now I&#8217;ll focus on just the one.</div>
<div><strong>Step 2: Identify possible outcomes for the value action</strong></div>
<div><strong><br />
</strong></div>
<div><strong><span style="font-weight: normal;">When a user takes the value giving action (e.g. performing a calculation), one of several things can happen. Specifically, value can be delivered or not. In my case I found there were four possible outcomes when a visitor was on the main calculation page:</span></strong></div>
<div>
<ul>
<li>No calculation performed</li>
<li>Calculation answered correctly</li>
<li>Calculation answered incorrectly</li>
<li>Calculation not answered</li>
</ul>
</div>
<div>I initially didn&#8217;t include the &#8216;No calculation performed&#8217; outcome, but then added it in as I realised that a user incurs a time cost in visiting the calculation page and thus if they don&#8217;t perform a calculation then the value provided is actually negative (i.e. it cost them and they gained nothing).</div>
<h3><strong>Step 3: Identify time costs</strong></h3>
<div>Each of these actions incurs a time cost to the user. Like the &#8216;No calculation performed&#8217; case, all four outcomes incur the cost of the user first visiting the site (though this cost is actually shared among all calculations the user performs in that visit).</div>
<p>The  other three also incur the time cost involved in typing in the calculation. This is then followed by the time cost in waiting for a response. Hopefully all these costs should be minimal, but it would be wrong to ignore them.</p>
<p>By analysing web logs, etc, it should be possible to get exact values for this time cost in most cases. The only thing that can&#8217;t be exactly pinpointed is the time it takes for the user to find the site as this may include, e.g. searching on a different site such as Google.</p>
<h3><strong>Step 4: Identify the user-derived benefit and costs</strong></h3>
<p>Assuming the user takes the action required to produce the value, three things can happen. Either the user gets the value they were after, they don&#8217;t get the value, or they get a wrong answer which may actually cost them (in that they may act on incorrect information).</p>
<p>In the case that the right answer is provided, we know that the user has received some value. While we don&#8217;t know how much there is one assumption we can make &#8211; it should be greater than the cost the time cost the user expected to incur. Otherwise the user wouldn&#8217;t have take the action (assuming rationality). We can figure out the expected time cost in a way similar to the actual time cost calculated in step 3. This just involves estimated averages across all sites (such as average site response time) rather than using data specific to my site. I also made an assumption that a user would expect a return of at least 10% greater than the time invested to make it worthwhile.</p>
<p>In the case that the calculator returns no answer (where I haven&#8217;t yet implemented the calculation asked), then the user gets no benefit, but also no real cost other than the time invested.</p>
<p>The final case is that the user gets given the wrong answer. This could potentially be have a large cost to the user if they act on the incorrect information. While hard to quantify, one assumption I felt confident making is that a rational user would cap their potential losses in relation to their potential gain. For this I assumed that the user would cap losses at, at most, 1o times their potential gain.</p>
<h3><strong>Step 5: Write out value expressions for each outcome</strong></h3>
<div>We now have enough information to write out expressions for each outcome, in terms of the total actual time cost (which I called &#8216;alpha&#8217; for no good reason), and the user&#8217;s gain if the answer is correct, which I called G. These came out to be:</div>
<div>
<ul>
<li>No calculation performed: -alpha/2</li>
<li>Calculation answered correctly: G &#8211; alpha</li>
<li>Calculation answered incorrectly: -10*G &#8211; alpha</li>
<li>Calculation not answered: -alpha</li>
</ul>
</div>
<h3><strong>Step 6: Derive a lower-bound on each expression solely in terms of the gain</strong></h3>
<p>We know alpha is the actual time cost the user incurs. This is related to a lower-bound on the gain, G, by the user&#8217;s expected time cost (call it alpha_e). With a bit of work (see the notes below for details), we can rewrite the value expressions so that they are expressed in terms of the lower-bound on G. So essentially, we have value expressions written solely in terms of (a lower-bound on) G.</p>
<p>Without getting into to much detail, we can basically total up the value provided to a user when they perform a set of calculations. This will give us a value score for that set in terms of G. While we don&#8217;t know what G actually is, it doesn&#8217;t matter &#8211; as we will be using the value calculation simply to compare one set of calculations to another (separated in time, by user, by calculator version, etc.) we can just drop G entirely.</p>
<h3>Conclusion</h3>
<p>Now we have an expression for the lower-bound on the value provided by any set of calculations and resulting outcomes. While not perfect (an exact score would be better than a lower-bound), I think it might be the best that can be done without figuring out what user&#8217;s are actually doing with their calculation results (and I think that&#8217;s their own business). It will still be very useful to be able to compare the lower-bounds as these are likely to be reasonably well correlated with the actual values. Also as the aim is to increase value over time we can be fairly confident that this is occurring if we can see that the lower-bound on the value is increasing over time.</p>
<h3><strong>My Rambling Notes (or Stop Here and Don&#8217;t Read On)</strong></h3>
<div>The main aim is to provide value to users. In order to do so with the greatest impact / least effort, it is necessary to optimise the value provided. In particular, potential projects should be prioritised based on the value they are expected to deliver. However, value is one of those difficult to define things, which makes an objective assessment of the value delivered by projects difficult. Nonetheless, I think it is worth trying to get as good an approximation as possible.</div>
<p>For the time being I&#8217;m restricting the value calculation to the core calculation service. There are four basic outcomes which can occur when someone interacts with main calculator page:</p>
<div>
<ul>
<li>No calculation performed</li>
<li>Calculation answered correctly</li>
<li>Calculation answered incorrectly</li>
<li>Calculation not answered</li>
</ul>
</div>
<p>If it is possible to assign a reasonable measure of user value to each item, then it will be possible to combine them into a reasonable total measure of the value provided by the calculator in a given time period, per user, etc.</p>
<p>In general, there will be a fixed time cost involved in performing any calculation (regardless of the result). For the time being, call this alpha. The cost when no calculation is performed will be somewhat less than this. At a rough estimate it will be alpha / 2.</p>
<p>Should a calculation be performed correctly there will be some gain G for the user.</p>
<p>If a calculation is not answered, then this gain G will not be realised. However, should the calculation be incorrectly answered, not only will the gain not be realised, but the user may be significantly affected (e.g. by entering into a bad financial transaction based on the incorrect result). While we can&#8217;t say exactly what magnitude of loss this might be, it seems reasonable to expect that any rational user would cap their potential losses at 10 times the possible gain. At the very least, at that risks beyond that level, they could be expected to verify the calculation results with other sources. So the maximum loss can, I think, be taken to be -10*G.</p>
<p>Combining these we can get value expressions for each of the possible outcomes:</p>
<div>
<ul>
<li>No calculation performed: -alpha/2</li>
<li>Calculation answered correctly: G &#8211; alpha</li>
<li>Calculation answered incorrectly: -10*G &#8211; alpha</li>
<li>Calculation not answered: -alpha</li>
</ul>
</div>
<p>This will be more useful if we can express it in a single quantity. To do so we need to look at the relationship between alpha and G.</p>
<p>There is a quantity related to alpha which will be useful to us. This is the time cost the user expects to pay, assuming a reasonably responsive system. Depending on the performance of our system, alpha may be greater or smaller than this. We&#8217;ll call this quantity alpha_e.</p>
<p>A rational user would not carry out actions which did not at least repay the expected initial investment plus a bit of &#8216;profit&#8217; to make it worthwhile and absorb associated risks. Thus we can expect G to have a lower-bound of perhaps 1.1 * alpha_e.</p>
<p>That&#8217;s a bit better, but still not quite there. We can get the rest of the way by looking at what exactly alpha and alpha_e are. These, as noted above, are the time cost of performing a calculation and the expected time cost of performing one on an averagely responsive system respectively. They have the same formula:</p>
<p>time_to_input_calc + time_to_perform_calc + time_to_reach_calculator / num_calcs_per_user</p>
<p>The only difference is that alpha_e represents the user&#8217;s expectation of these values while alpha represents the actual values.</p>
<p>We can assign approximate values to these for alpha_e. Something like this, perhaps:</p>
<p>alpha_e = time_to_input_calc_e + time_to_perform_calc_e + time_to_reach_calculator_e / num_calcs_per_user_e</p>
<p>= 10 + 3 + 10 / 5</p>
<p>= 15 seconds</p>
<p>This gives a lower-bound on G of 16.5 seconds.</p>
<p>Now, we can perform a similar calculation for alpha. I don&#8217;t know exactly, but the result will probably be something similar. Assuming for the time being that it is, we can then say that G &gt;= 1.1 * alpha. We could easily adjust the multiplicative factor should analysis of the data show that alpha and alpha_e show that they differ.</p>
<p>But is relating alpha to a lower-bound on G any use? It&#8217;s not precise, but it gives a possible approach.</p>
<p>Totalling up the value for a set of calculations (based on the expressions above) we will get something in terms of G and alpha, e.g.</p>
<p>value = a * G &#8211; b * alpha</p>
<p>If we can get an upper-bound on b * alpha in terms of G, then we&#8217;ll get a lower-bound on the value in terms of G:</p>
<p>Setting G = 1.1 * alpha, we get our upper-bound on b * alpha:</p>
<p>b * alpha &lt; (b / 1.1) * G</p>
<p>This gives us a lower-bound on the value provided as:</p>
<p>value &gt;= (a &#8211; (b / 1.1)) * G</p>
<p>So that is our lower-bound on the value provided to the user by a set of calculations. The a and b variables can easily be calculated by totalling the values of G and alpha for each calculation in the set. The 1.1 factor can be assumed constant (or calculated from the actual data observed). And G is essentially irrelevant to us. As all value calculations will contain a multiple of G, we can simply drop it &#8211; it contains no useful information.</p>
<p>So we have, pulling everything together, finally:</p>
<p>value &gt;= (a &#8211; (b / c))</p>
<p>where</p>
<p>a = answered_correctly &#8211; 10 * answered_incorrectly</p>
<p>b = 0.5 * no_calculation + answered_correctly + answered_incorrectly + not_answered</p>
<p>c = 1.1 * 15 / (time_to_input_calc + time_to_perform_calc + time_to_reach_calculator / num_calcs_per_user)</p>
<p>While not an exact measure, (which wouldn&#8217;t really be feasible), it does give us a lower-bound on the value provided (given the assumptions made above). This is almost as useful as we can now operate with this as our measure in value and strive for a constantly increasing lower-bound on the value provided. While the actual value may be somewhere higher than this, improvements in the lower-bound will almost certainly result in the actual value provided being increased (if not perfectly correlated, this should at least happen on average over time).</p>
<div id="_mcePaste">Note that there are no units &#8211; this doesn&#8217;t matter as the primary use of this value is to compare two sets of calculations, or options, to determine the relative value provided to the user.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/defining-website-value-100/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The qualities of a great web application</title>
		<link>http://www.calcatraz.com/blog/the-qualities-of-a-great-web-application-78?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-qualities-of-a-great-web-application</link>
		<comments>http://www.calcatraz.com/blog/the-qualities-of-a-great-web-application-78#comments</comments>
		<pubDate>Sun, 08 Nov 2009 08:48:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>

	<!-- AutoMeta Start -->
	<category>application</category>
	<category>sense</category>
	<category>important</category>
	<category>unlimited</category>
	<category>requirements</category>
	<category>understanding</category>
	<category>punctual</category>
	<category>punctual</category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">https://www.calcatraz.com/blog/?p=78</guid>
		<description><![CDATA[The qualities of a great web application I aim to make Calcatraz into a great web application. To do so effectively it is important to understand the qualities a great web application exhibits. So what are they? Here are a few things I have thought of: 1. Punctual A web application should be quick: quick [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">The qualities of a great web application</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">I aim to make Calcatraz into a great web application. To do so effectively it is important to understand the qualities a great web application exhibits. So what are they? Here are a few things I have thought of:</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">1. Punctual</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">A web application should be quick: quick to load, quick to respond to user input, etc. However, I don&#8217;t think that calling the required quality &#8216;speed&#8217; would be entirely accurate. There are instances when things can be too fast &#8211; an error message not displayed for long enough, for example. In general, events should happen at the appropriate time. If the user does not need a time lag, then there should not be one. I think the correct word is &#8216;punctual&#8217; &#8211; the app should do things at, rather than before or after, the right time.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">2. Minimal</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">A web application should be minimal. Not in the sense of leaving out important features, but more in the sense of containing no unnecessary parts. Anything which does not perform a necessary function should usually be removed. Where several parts perform similar functions they should be generated by the same code.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">3. Magical</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">There is a quote &#8216;any sufficiently advanced technology will be indistinguishable from magic&#8217;. I think this applies to great web apps. Components of the application should be worked on and crafted to such an extent that it is no longer possible for the user to readily comprehend the underlying process.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">4. Intuitive</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">Use of the application should be easy. Even complex parts of the application should be straight-forward to use without prior knowledge. This requires not just simplicity, but an understanding of human psychology. By understanding the mind and it&#8217;s quirks, an experience can be tailored to it.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">5. Unlimited</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">A great web app will be unlimited in the sense that users do not hit upon limits while making use of it. That doesn&#8217;t mean the app can do anything in the world, but it does mean that it can do anything in its domain. This requires general mechanisms for extending the application upon its lines of functionality. An example is Google Analytics, while it doesn&#8217;t capture everything you need to know about your app, it can be readily extended to do so.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">6. Responsive</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">An application should be the product of user feedback. While it should not necessarily address every bit of feedback (as good for one user may be bad for another), it should be shaped and moulded into the form and function which delivers the most value to the most users. It should continue to evolve over time with changing needs.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">7. Predictive</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">As well as just responding to user requirements, a great application will predicted future requirements. New functionality will appear before a user realises they need it. Only genuinely useful improvements will be made &#8211; those that enhance and improve the user&#8217;s experience.</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">8. Avaliable</div>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">The application will be on-hand wherever the user requires it. It should be unobtrusive, but always available and easily invoked.</div>
<p>I aim to make <a href="http://www.calcatraz.com">Calcatraz</a> into a great web application. To do so effectively it is important to understand the qualities a great web application exhibits. So what are they? Here are a few things I have thought of:</p>
<p><strong>Punctual</strong></p>
<p>A web application should be quick: quick to load, quick to respond to user input, etc. However, I don&#8217;t think that calling the required quality &#8216;speed&#8217; would be entirely accurate. There are instances when things can be too fast &#8211; an error message not displayed for long enough, for example. In general, events should happen at the appropriate time. If the user does not need a time lag, then there should not be one. I think the correct word is &#8216;punctual&#8217; &#8211; the app should do things at, rather than before or after, the right time.</p>
<p>Example: Not an web app as such, but <a href="http://www.google.co.uk/chrome">Google Chrome</a> is exemplary in this area &#8211; <a href="http://www2.webkit.org/perf/sunspider-0.9/sunspider.html">compare</a> it to Firefox or IE to see the difference.</p>
<p><strong>Minimal</strong></p>
<p>A web application should be minimal. Not in the sense of leaving out important features, but more in the sense of containing no unnecessary parts. Anything which does not perform a necessary function should usually be removed. Where several parts perform similar functions they should be generated by the same code.</p>
<p>Example: The 37 Signals guys do this really well. See <a href="http://basecamphq.com/">BaseCamp</a> for instance.</p>
<p><strong>Magical</strong></p>
<p>There is a quote &#8216;any sufficiently advanced technology will be indistinguishable from magic&#8217;. I think this applies to great web apps. Components of the application should be worked on and crafted to such an extent that it is no longer possible for the user to readily comprehend the underlying process. Alternatively it should be surprising &#8211; as in it offers something obvious but that no one even conceived as being possible.</p>
<p>Example: <a href="http://phpanywhere.net/">PHPAnywhere</a> &#8211; coding is suddenly mobile.</p>
<p><strong>Intuitive</strong></p>
<p>Use of the application should be easy. Even complex parts of the application should be straight-forward to use without prior knowledge. This requires not just simplicity, but an understanding of human psychology. By understanding the mind and it&#8217;s quirks, an experience can be tailored to it.</p>
<p><strong>Unlimited</strong></p>
<p>A great web app will be unlimited in the sense that users do not hit upon limits while making use of it. That doesn&#8217;t mean the app can do anything in the world, but it does mean that it can do anything in its domain. This requires general mechanisms for extending the application upon its lines of functionality. An example is Google Analytics, while it doesn&#8217;t capture everything you need to know about your app, it can be readily extended to do so.</p>
<p>Example: <a href="http://twitter.com/">Twitter</a> &#8211; while the app is incredibly simple in itself, it is being put to an incredibly wide range of uses.</p>
<p><strong>Responsive</strong></p>
<p>An application should be the product of user feedback. While it should not necessarily address every bit of feedback (as good for one user may be bad for another), it should be shaped and moulded into the form and function which delivers the most value to the most users. It should continue to evolve over time with changing needs.</p>
<p><strong>Predictive</strong></p>
<p>As well as just responding to user requirements, a great application will predicted future requirements. New functionality will appear before a user realises they need it. Only genuinely useful improvements will be made &#8211; those that enhance and improve the user&#8217;s experience.</p>
<p><strong>Available</strong></p>
<p>The application will be on-hand wherever the user requires it. It should be unobtrusive, but always available and easily invoked.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.calcatraz.com/blog/the-qualities-of-a-great-web-application-78/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

