Odd Scales

I have electronic scales, which allow you to enter your age and sex. When I step on my scales as a 33 year old man, I weigh 72.5 kg. Anonymously, however, I only weigh 70.7 kg.

My curiosity was piqued, of course, and I did two more experiments by placing a towel over the scales (the scales measure my body fat with a small electric current - the towel blocks the current). No difference as anonymous person, but as a 33 year old man without body fat measuring I weigh 70.7 kg.

So based on the measurement of my body fat and my age and gender, my scales add another 1.8 kg to my weight. I have no idea why.

A Trick For Caching And Expiring Static Web Resources

The images, css files and javascript files in a web application, the “static resources”, are a big part of each request, both in number and in bandwidth. That’s why they they should be cached by the browser for as long as possible. By setting a HTTP-EXPIRES header in the far future (at least a year from now) the web server tells the web browser that it’s ok to cache these resources, saving us a lot of bandwidth and improving the page load time for the user.

But sometimes we want to make a change in one of our resources, and want the browser to update the resource at once, long before the cached version expires. To do this we must create a new URL for the resource. Yahoo solves this in their YUI project by giving their css resources a version number:
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css"/>
This is a fine solution, but it involves some overhead - if you just want to use the latest version, you have to update the version number in all places you include the resource.

I’ve invented another trick which works fine as long as we, unlike Yahoo, don’t care about supporting older versions of resources. To generate the URL of a resource, we call a function, e.g. versioned_css("main"). In this function we append the git hash (git-hash-object filename) to the filename, before the extension, caching the result (because we don’t want to calculate the hash more than once). The first ten digits of the git hash will be sufficiently long to be unique (a git hash consists of 40 hexadecimal digits). Also, there is no need to use git - there are other ways to create a unique hash from a file.

Whenever the file changes, its hash will also change, creating a new and uncached URL, which is exactly the effect we’re looking for.

However, we still need to map the URL-with-hash to our resource, a file named something like “main.css”. We could add the hash to the filename, by renaming the resource to “main-c0a9a0a5ec.css” during the deployment of the application, but it is easier to have Apache remove the hash using url-rewriting:
RewriteRule ^/stylesheets/(.+)-[0-9a-f]{10}\.css$ \
http://127.0.0.1:3010/stylesheets/$1.css [P,QSA,L]

The difference with renaming the resource is that with rewriting a request for “main.css” with any hash at all will return the latest version of the file, while with renaming an incorrect hash would lead to a 404 error.

The strength of this trick is that it lets you use far-future expire dates, is easy to implement and allows you to forget about it afterwards, particularly if you extend the built-in methods in Rails to generate urls for resources.

Is Your Program Perfect? The de Mare Test

Is your program as fast as it needs to be? As fast as it can be? Does it use as little memory as possible? Is it free of memory leaks? Is the response time that the users experience as low as possible? Is their a cap on the maximum response time? A low cap? Does your program consume as little bandwidth as possible? Does it consume no more energy than necessary?

Can your program report on its own functioning? Can it detect its own errors? Report them? Can you change your program while it’s running? Can your program update itself? Securely? In the background? Without restarting?

Is your program easy to understand for new programmers? Easy to change? Can parts of it be changed or configured by non-programmers? While running? Can you easily find programmers that are proficient with the languages and technologies you have chosen? If new programmers introduce errors, can these errors be easily detected? How does your program handle faulty user input? Deliberately invalid user input? Do you make a separation between parts that will probably remain unchanged and parts that will probably see a lot of change? Can your program be built in one step? Can you create and distribute patches for older versions?

Can parts of your program be used in other programs? Replaced by other modules? Can a single module be assigned to another team for improvement?

Can your program be scripted on the command line? Does it expose an API? Are there bindings or wrappers for Java and PHP? For Ruby and Python? For OCaml and Smalltalk?

Does the performance of your program increase linearly with faster hardware? With more hardware? Can you sacrifice memory usage for speed and vice versa with one setting?

Can your program survive a computer crash? Without data loss? Without downtime? Does it have a single point of failure? If it crashes, will you be notified automatically? At once?

Does your program run on IE, Firefox, Opera and Safari? All versions of IE? On windows, mac and linux? On windows 95 and Vista? Without administrative privileges? On all common linux distributions? On 64-bit hardware? On a PowerPC? On an iPhone? With a Turkish user interface? A Japanese interface? Will it work for the colorblind? The visually-impaired? The illiterate?

Does your program follow code conventions? Does it have conventions in naming variables and functions? Have you documented them? Does it have a glossary of terms? Can your program be read from beginning to end as a literate program? Understood? Understood a year from now by you? By other people? Does the documentation answer all the relevant questions in this essay?

Is your program correct? Is what it does worth doing?