Archive for June, 2006

Die, Caps Lock, Die!

Wednesday, June 28th, 2006

The caps lock key is the dumbest key on the keyboard. I mean, there are other vestigial keys, like Scroll Lock. Scroll Lock crouches off to the side, doing nothing in particular, not getting in your way. It’s a waste of space, but this is a minor transgression compared to the accursed Caps Lock.

Caps Lock is one of the largest keys on the keyboard, and sits right to the left of the home row. Thus it’s very easy to hit, and that would be ok if it did nothing, like our pal Scroll Lock. And maybe it would even be ok if it inserted a character into your typing stream, because you’d spot it immediately and backspace. (Backspace is about 1/3rd the size of the caps lock on my keyboard, and much further from the home row. From this we can glean that backspace is used perhaps 25% as often as caps lock? Ha!)

No, it’s even worse than an extraneous character, because this is a modal key. That’s right, you don’t get any immediate feedback after striking it. Instead, whenever the next alpha keystroke comes - it could be seconds later, or hours, or even days - you are amazed to find yourself typing in all caps.

And even THIS could be forgiven. Maybe, very maybe. But if you’re currently in a program that uses the alpha keys for commands, like Photoshop or - and this one is truly nasty - vim, your next set of keystrokes (which, remember, could be many minutes after the original caps lock change) start having strange and unpredictable effects on your work. Only after a few confused and disorienting seconds do you realize what happened, try to back out what went wrong, and finally turn off the caps lock.

Yes, this horrible, horrible key should be drug out back and shot between the eyes. Thankfully this isn’t hard to do, even without physically mangling your keyboard. Directions follow for switching caps lock to an alternate control (thus making it actually useful) or off (just making it inert, a scroll lock with better real estate).

GNOME (i.e., Ubuntu Linux)

System -> Preferences -> Keyboard
“Layout Options” tab, expand “Control key position”
Select “Make CapsLock an additional Control”

Mac OS X

System Preferences -> Keyboard
Click “Modifier Keys” button
Change “Caps Lock Key” dropdown


Update: Looks like I’m not the only one that thinks this. Check out the CAPSoff campaign.

Continuations, Ajax, and REST

Wednesday, June 21st, 2006

There’s a debate that seems to be emerging among web app developers between three competing types of interfaces. I’ve been pondering this question for years - almost since I first began working in the web realm - but, lacking good terms to describe my vague thoughts on the matter, I was unable to vocalize them. Luckily I stalled long enough that someone else did the hard work of coming up with terms. Here they are:

  • REST - Aka “the usual”. This is where all the information for the page’s state is stored in the URL, or in the payload of an HTTP POST. (The latter implies that every piece of data you want to carry onto the next page will appear as a hidden input field in the previous page’s form.)

    REST is easy to use, works perfectly with all browser functionality (back, forward, bookmarks, etc), and requires no server-side storage. It is the default and should be used unless there is a compelling argument to use one of the other two types.

  • Continuations - This is where you stuff user state data into a session stored on the server. Aside: the name comes from the continuation feature offered by advanced languages, but the language or framework doesn’t need to support low-level continuations to implement the interface feature. Sessions are a cinch to use with modern languages, in some cases even easier than REST since you can store complete objects and not just easily urlencodable fields like text and numbers. Use of sessions makes a lot of sense for multi-page forms (which closely resemble the “wizard” style of interface in the olden days of local GUI applications). The checkout process on a shopping cart, filing out a long and complex profile on a dating site, or browsing the result set from a complex query on a travel booking site are some good examples of where continuations / sessions are often used.

    The downside to continuations is that they break some browser functionality. This is painfully apparent with tabbed browsing. Want to browse two result sets side-by-side in two tabs or browser windows? Too bad - you can only have one session at a time. I’ve often worked around this by viewing the site with two different browsers at once. The fact that this terrible hack is worth using indicates there is some serious flaws in the continuation model.

  • Ajax - Always a crowd-pleaser. Ajax breaks browser functions completely in most cases, so it should be used only when breaking standard navigation can be considered a benefit. One of my favorites is deleting an item out of a list. Back/forward and bookmarks make absolutely no sense for this. Dragging the map around in Google Maps is another good example. (Importantly, you can still get bookmark / email a link to your friend / etc capability via the “Link to this page” link.) And sometimes Ajax can be justified just for speed reasons. GMail breaks some browser functionality in places where it might be preferable to keep it, but the benefit to performance makes this a worthwhile tradeoff.

Personally I really like continuations. They are just so dang intuitive. The user clicks a link or button to start a new session, taking them into a multi-page form where they can move at will between the steps, tinkering with all the data until everything is just right. Then when they are satisfied that everything is perfect, they click “Commit” or “Place Order” or other button at the end of the process, and the session data is finalized and saved into the server’s database.

Continuations can actually get even cooler if they can be used as a work-in-progress which can be returned to at a later time, or even send the link to another person for collaboration. One of our clients has a system which uses this to submit change requests. Certain types of users can start the request, entering in all the relevant data, but they cannot commit it. The change request is saved as a work-in-progress and users from another role are notified. One of those users then loads up the request - effectively taking it over - and can verify and approve all the data they see entered, then run the finalize step at the end to commit the change.

One could actually do this same sort of thing even with a single-page form, but prior to needing this interface feature I never stopped to think about storing data in an incomplete / work-in-progress state. The old web app model was just form post -> store to database, and that was it. Multi-page forms forced me to come up with a good implementation for saving the state of an incomplete data record; but once that capability was available, I discovered there were a lot of other uses for it.

Multiple Continuation Sessions

So what about running two separate continuation sessions in different tabs? There’s a pretty simple technique for dealing with this, although it doesn’t seem like many places use it. The trick is to create a unique key each time a new session is started. For example, a travel booking site might generate a random key whenever you click “Find my flights” or whatever was the initial button or link to launch the search process. This key should go in the URL, so your address bar looks something like:

http://example.com/multipageform.php?sesid=12345

The object storing your continuation data can then be accessed via something like $_SESSION[’multipageform’][$_REQUEST[’sesid’]]. Users can view the same session in multiple tabs by cutting and pasting the URL from their results or by a duplicate tab/window function. Or they can view different sessions by opening a separate tab and starting a new search - or any combination thereof.

One thing to watch out for here is that your session data can get pretty large if you don’t do a little bit of manual garbage collection. I usually just limit the number of sessions which can be open at once, throwing out the oldest one when the limit is reached. For example:

if (count($_SESSION['multipage']) >= 5)
   unset(key($_SESSION['multipage']));
$sesid = sha1(rand());
$_SESSION['multipage'][$sesid] = new MultiPageFormController;

Spend Less Time Working, Get More Done

Saturday, June 10th, 2006

This piece makes a strong argument for keeping hours worked per week low in order to enhance productivity. Low, as in less than 40.

“The sociologist Arlie Hochschild in one of her books mentions an IT copany that were in big financial trouble. Rather than lay some people off they switched to a 30-hour work week and a corresponding pay cut, and experienced no reduction in production. They did the exact same amount of work in 30 hours a week as in 40.”

My own anecdotal evidence confirms this: often I find that I get more work done when my time is limited. I know I’ve got to leave at 7pm on a particular day, so I get straight to it, no messing around. Without such a time constraint I may spend the morning tinkering with a new technoloy tool or writing a post for my blog. (er…)

In reality I think that 6 hours per day is the maximum real productivity that can be achieved, at least on a sustainable basis. Nicely enough, this period fits neatly into an 8 hour day (counting some time for lunch, breaks, socializing at the water cooler, etc). Most people probably get only about 2 solid hours of productivity spread out across the per day, even when they spend 8, 9, 10, or more hours at the office. What the heck is the point of that?

The attitude that more hours = more productivity is almost dogmatic in the IT industry. A related attitude, but possibly even worse, is that employees prove their loyalty to the company by spending more than 40 hours a week parked behind their desk. In the past I’ve been accused of not being a “team player” for refusing to come in to work on the weekends on a regular basis. (This even after I specified at the time of my hire that I wouldn’t do the weekend thing.)

I do developer interviews from time to time, and when I do one thing I always mention is “we don’t believe in working more than 40 hours a week here.” Confusion inevitably spreads over the applicant’s face, as they think: What is this strange concept? Is it a trick of some sort? This is a software company, surely I will be expected to participate in coding death marches as any given release date approaches…

Nope, it’s for real. We actually want to be productive and make high-quality software. It’s hard to do the first and nearly impossible to do the last by constantly straining your development team to the limit with excessive overtime.

I think the more subtle reason that this approach works better is that most people work better at a steady pace, rather than spending half the time fooling around and the other half in a desparate burst to deliver the product on time. Slow and steady wins the race and so forth.
The nature of the traditional long-cycle approach to software development is to creates a sort of peak-and-trough pattern. At the start of the project you think “I’ve got plenty of time, I can spend three weeks tinkering with this particularly interesting bit of code that isn’t that important to the project overall.” More likely you don’t think any such thing conciously, but it is what it happening. Then this is much enhanced your residual burnout from the last product’s release death march, so you want to take it easy for a while.

Then as the release date gets close enough to be a reality - say, three to six months away - you start to really buckle down and think about what it’s going to take to get it finished. You realize just how much is left to do and the entire team goes into code-like-hell overdrive. The quality of the code produced and the social lives of the team all go straight into the wastebasket. All you can think about is hitting that finish line.

Using evolutionary design with short iteration cycles breaks out of this pattern. Release cycles that are 2 - 6 weeks long don’t give enough time to relax at the beginning - the deadline is always right around the corner. At the same time your goals for the iteration are simple and within reach, with realistic time estimates as well. (I think it’s pretty much impossible to do accurate time estimates for projects that will take more than a few months.) So this approach tends to cause people to work at a steady rate, consistently producing week after week. There are never any coding marathons and subquent burnout - which in turn reduces the quantity of maintenance work on the next iteration, since the code produced is of a higher quality.

Spend less time at the office, but then that time more productive. It works - really.