Small Things Matter

Usability is a big topic but sometimes it can be very small things. Say, one line of JavaScript (well, jQuery in this case):

$('my_important_input_field').focus()

This is a small big thing that is ridiculously easy to implement and yet so underused.

I’m currently slowing down the feature development on the MixifyRequests-site and concentrating on little finishing touches like this in preparation of an official 1.0 launch. I already did one release concentrating on reducing technical debt (by improving the codebase in general, adding more tests, etc.) and now I’m kind of doing the same with UI and copy.

This is usually the part of software projects that gets neglected the most due to tight deadlines and budgets, so it’s fun to be able to do it with no hurry.

(This post was originally posted to my other blog called Spinning Code.)

Enhancing registering experience with django.contrib.localflavor

Usability is very much about little stuff. That kind of things that you normally don’t even think about. Here is a small snippet of code that I used in a project where I wanted to pre-select a users location (city) on a registering form.

Hostip.info has the necessary data and a very straightforward API. The newly-added django.contrib.localflavor package in Django helps with the other part of the data.

This is the small method for geolocating the IP address:

def _get_city_for_ip(ip):     """     Uses hostip.info to get a city name from IP     """     import urllib     import mimetools      url = 'http://api.hostip.info/get_html.php?ip=%s' % ip     fp = urllib.urlopen(url)     headers = mimetools.Message(fp, 0)     fp.close()     return headers.dict['city'].lower()

and a stripped-down view code for generating and displaying the form:

class ProfileForm(forms.Form):     from django.contrib.localflavor.fi.fi_municipalities import MUNICIPALITY_CHOICES     ...     cities = [('none_selected', 'Please Select a city')] + list(MUNICIPALITY_CHOICES)     location = forms.ChoiceField(required=False, choices=cities)  def profile(request):     """ Presents and validates the profile form """     u = request.user      # Only do geolocating if the profile has no location info     location = u.get_profile().location     if len(location) < 2:         location = _get_city_for_ip(request.META['REMOTE_ADDR'])      form = ProfileForm(initial={'location': location})     return render_to_response('users/profile_form.html', locals())

I’m sure this code can be tweaked quite a bit from this. Currently it uses Finnish localflavor code to get a list of Finnish municipalities, add a ‘Please Select a city’ choice to the beginning of it, and then tries to match a geolocated city against it. If no match is found, it defaults to ‘Please Select a city’. But if a match is found, user is presented a select field with the City matching his current IP-address pre-selected.

Design Your URLs

URLs are the most important, and yet often least designed, part of your website. No matter if it’s a cool 2.0 application or plain vanilla homepage, it’s the URLs that lead the visitors to it. Why is it that almost nobody seem to know (or care about) how to design them?

Any web developer should know that URIs are a part of the sites user interface. Usability guru Jakob Nielsen reminded us about this back in 1999, but very few of us seem to remember.

Learning from bad examples

Here’s a typical example of a very bad URL:

http://www.turunsanomat.fi/viimeuutiset/ts/?ts=0,3:2025:0:0,4:26:0:0:0;4:27:0:0:0;4:28:0:0:0;4:29:0:0:0;4:30:0:0:0;4:31:0:1:2007-01-06;4:35:0:0:0,0,1:0:0:0:0:0:#429985

This is so ugly that it’s impossible to say anything good about it. It makes me want to cry.

Apple usually gets things like these right. Apple.com is generally very good regarding to URLs, but then there is the Apple Store. I’ll buy you a beer if you can read this to your grandma over the phone:

http://store.apple.com/Apple/WebObjects/fistore.woa/6994044/wa/PSLID?mco=E2DBC1A0&nclm=iPod&wosid=ci7FXn07nrcd2jXw2kj1tYj6QqG

Do you know where it points to? Of course not. But guess what’s the best part of it? It doesn’t work. Try it yourself.

As an example of a half-way designed URL, lets look at

http://shop.digitalworldtokyo.com/index.php/shop/product/full_set_of_three_usb_humping_dogs/

This is a good example of an URL as UI. You may not want to visit that page after seeing the URL. But this is not a good URL. First, why on earth is there an /index.php/ in the middle, even though it most definitely could have been omitted?

Also, the word ‘shop’ occurs twice in the URL. And ‘product’ is not useful here in any way, so why display it? Instead there could be some category reference in the URL so that products in different categories would be distinguishable.

With these tweaks a good URL for this product could be something like:

http://shop.digitalworldtokyo.com/usb/full_set_of_three_usb_humping_dogs/

How to design good URLs

There are many preferences of how to build a good URL structure. The most important thing is to be consistent. The small details are not as important as that they are consistent as a whole.

Often the URL structure of a companys web site is similar to the inner structure of the company. This is a very basic mistake that you should avoid. While it may be quite easy for you to understand the inners of your company, it’s not something that your customer knows, or even should know. Try to be as descriptive and simple as you can when designing the URLs.

A good URL:

  • is short
  • gives user a hint about the content (ie. use /products/product_name/ instead of /c/1/)
  • tells user where he/she is (ie. /support/product_name/faq/)
  • is hackable (ie. if faq is at /support/product_name/faq/, then /support/product_name/ shows the support main page for this product and /support/ is the main support page. Also, if you search faq for product2, you should find it at /support/product2_name/faq/)
  • does not have any session data or other cruft in it
  • does not expose the underlying technology (like foo.php and bar.aspx does)

How to redesign URLs

While Cool URIs don’t change, it’s inevitable that sometimes you have to change something. As a matter a fact, in my opinion, you should change the URLs as your organization changes. But when you do, you should do it very wisely.

Here are some tips:

  • Avoid linkrot with any means necessary. With every changed URL, redirect the old URL permanently (using HTTP status code 301) to the new one. Automate the process if you can.
  • Just in case, use a good 404 page that informs users about recent site redesigns, so that in case of a missed redirect, they can locate the moved page easily.
  • Design to future. Try to avoid situations where you have to change URL designs more often than yearly.
  • Use temporary redirects. For example, when designing a campaign site for spring 2007, you can use /spring_campaign/ or similar as the URL for marketing, and redirect the page temporarily (with HTTP status code 302) to /spring_campaign/2007/. Next year, just change the redirect to /spring_campaign/2008/. This way, when someone links to the campaign page, they’ll probably link to the right permanent URL and you can still use short and easy to remember URLs in marketing.
  • If, for whatever reason, you absolutely must delete a page, inform users about it on the 404 page. If possible, offer them a way to go to some other relevant page.

Require good URLs

Good URLs don’t just happen — you have to design them. Next time when listening to someone pitch about website design, publishing platform or developing framework, ask the person “what about the URLs”. Remember that the question is very much like “is she pregnant”, because it’s not possible to have a little bit customized URLs (well, it is, but it’s pointless) no more than it’s possible to be a little bit pregnant.

In web design, you can cut the corners in many places, but don’t do it with URLs.

I Want My Preferences Online

Yet another interesting video from Google: this time it’s Guido talking about a code reviewing app that he’s been developing for Googles internal use. What’s interesting about this, is the fact that he used Djangos templates for building the UI.

During his presentation Guido mentioned a very common usability problem in modern software: it’s often very hard to use an easily configurable program on other persons computer (because it behaves very diffrently than what you are used to). In his example, Guido mentioned Emacs, I was thinking about TextMate.

I absolutely love TextMate, but I hate the fact that when I’m using it on somebody elses computer, it feels like using a totally different program. And it’s not just text editors. Nowadays, I find it very hard to use Mac OS X withouth QuickSilver. And what can you do with QuickSilver that is not trained to do exactly the things that you want? Not very much. This problem of adaptive software is quite universal.

This is hardly news to anobody. Usability people haven been talking about this for years, but why is it that nobody haven’t come up with any decent solution for it yet? Come on, it’s not like we’re living in eighties anymore. We have this web 2.0 thingy with the tubes and all.

Give me a way to use my TextMate with my own settings and preferences from any computer. Well, at least on any computer running on Mac OS X 🙂