Friday, July 8, 2011

How to have a fanatical user base.

This is (at least) as much a rant as anything really informative. It's not really about writing code either, but about designing and packaging code so it stands a chance of being liked and used instead of frustrating and angering people who want to use it. Since I happen to be frustrated with it at the moment, I'm going to use TortoiseHg as an example.

The idea of TortoiseHg is great: a GUI front-end for the Mercurial version control system. That seems great. In reality, however, it has a few design flaws and a lot of problems with packaging that render it an absolute nightmare.

Let's consider my current situation (largely because I think it's probably fairly typical for a lot of people). I've programmed for a long time. I've used various version control systems over the years. After reading about the coolness of distributed version control, I've decided it's time to switch. I've done some research and after reading a lot about the pros and cons of each, finally decided to install Mercurial.

I've also set up an account on Bitbucket, and want to be able to synchronize (at least some of) my repositories to/from there, so 1) I have an offsite backup of that code, 2) I can share it with other people, and 3) I can easily get to it when I'm no the road.

Since I do most of my programming on Windows, and quite a bit of it in Visual Studio, I decide to download the TortoiseHg package. This includes Mercurial itself and a graphical front end (for those who don't know, TortoiseXxx are all version control front-ends -- TortoiseSVN, TortoiseGit, TortoiseHg, etc.)

Anyway, running the installer goes pretty smoothly. After it's done, I can start up with TortoiseHg Workbench without any problems either. On the positive side, I guess I should note that this shows real progress over the situation a few decades ago, when it probably would have taken most of a day to accomplish even that much.

I've read the (seemingly) excellent HgInit web site. It tells me my first step is to create a repository, which seems reasonable enough. It tells me: "And getting a repository is super-easy: you just go into the top-level directory where all your code lives, [...] and you type 'hg init'." Since I'm using TortoiseHg, I get to pick my directory with a normal selection dialog and such, but otherwise that step goes smoothly enough too.

From there, thing go downhill pretty quickly though. After reading a bit more, I realize that the next step is going to be to commit all the files in that directory to the version control. Maybe I'm just a wimp, but after re-checking and noting that the directory I've selected contains over 13 gigabytes, 10,000 directories and about 85,000 files, I think about things for a moment and decide that maybe it would be better to start out with something a bit smaller.

Unfortunately, it appears I've made a mistake that's relatively difficult to fix. It's easy to "remove that repository from the registry", but that still leaves a ".Hg" directory that I don't want, and its permissions have been locked down to the point that attempting to delete it fails, even though I'm logged in as an administrator. I eventually do manage to delete it, but I have to change the permissions to give myself full control and remove the read-only bit on it before I can.

This leads to my first point: especially when a new user is trying to get started with your software, ignore the possibility that they might make mistakes. Furthermore, ensure that recovering from such mistakes is as difficult as possible. This gets you started toward a fanatical user base by filtering out all but the most dedicated almost immediately.

Anyway, after a bit more thought, I decide to start out with something smaller -- somebody has asked me to share a particular program with them, and I've set up a repository on Bitbucket (which also uses Mercurial) for it. I'll just set up a repository for that particular code for now, and once I've got things figured out a bit better, I'll deal with the rest of the code.

Of course, when I'm trying to do this, I mis-type the name of the directory where my code lives, so it creates a new directory and puts a repository in it, so I get to do the same thing all over again -- five more minutes wasted to recover from a simple one-letter typo (largely because for some insane reason, it decides to always start browsing for the right directory from my Windows system directory, which hardly seems like a likely place for a version control repository).

Okay, after that I finally manage to create a repository for the correct directory. I even manage to add the files without too much incident. My next step is to get this code on to Bitbucket. When I created the repository on Bitbucket, it gave me a path, so this should be easy, right?

Wrong! First, I seem to have a couple of options: I can push the changes from my local repository, or I can clone my local repository. Or, more accurately, both of those *seem* to be available, but neither one actually works. It appears that TortoiseHg will only let me clone my repository to a local path. When I paste in the path Bitbucket gave me and click the clone button, it tells me: "Error Creating destination folder. Please specify a different path."

This leads to my second major point: abominable error messages. About all this tells me is that it didn't work and I should try something else. Instead of providing any help about how to do things right, it's recommending that I use trial and error until I find something that at least seems to work. Again, I'll add a historical note: a few decades ago, it would have been pretty common for this to be overtly abusive (words like "stupid" or "idiot" in error message used to be pretty common), whereas now the abuse is tacit, covert, and even politely phrased. I believe this is real progress -- users were sometimes amused by over-the-top abusive error messages, where the politely unhelpful one can only be frustrating. Again, this helps a great deal in filtering out any users who might not be absolute fanatics.

Fortunately, the recommended trial and error doesn't seem to accomplish much. At least as far as I can tell so far, the only path that will work is to a local directory. "Distributed" version control that only works on a local machine is definitely a good step toward fanaticism.

Okay, maybe it'll be better to push the changes from this repository to the remote one instead. There's even a nice button that says it will "push outgoing changes to selected URL". That seems reasonable -- but clicking it simply tells me: "No URL Selected. An URL must be selected for this operation." While that seems like a reasonable idea, it tells me nothing about where or how to actually select the URL to use for this operation. Doing a bit of looking at the Settings dialog doesn't turn up anything either.

Doing a bit more clicking around, I find when I right click on the line for the current revision of the code, I get a popup menu with an "Export" sub-menu, but only one of the entries there ("copy patch") is enabled. That doesn't seem terribly promising, but what the heck -- nothing else has worked. Unfortunately, selecting it doesn't seem to do anything useful either (in fact it's not at all apparent what, if anything, it has done at all).

This leads to another obvious major point: when there's a problem, you definitely do not want to provide any information that might help fix it. It's definitely better to leave the user wondering around, helplessly flailing until they run across something that seems like it might work. If you can manage to at least implicitly blame the user, that's definitely a step in the right direction as well.

Well, maybe it's easiest to just ignore the GUI front end for the moment, and use the command line tools instead. Right clicking on the name of the repository pops up a menu that shows (among other things) a terminal entry with the icon for a normal command prompt. I'll just use that, type in the command -- that's not such a big problem, right?

Wrong again! Clicking on that menu entry does open a command prompt (good) and the current directory is even the directory for that code (better). Unfortunately, when I try to give any Mercurial command (they all start with 'hg') I get the standard error message from the command processor saying that:

'hg' is not recognized as an internal or external command,
operable program or batch file.

That's right: I'm at the Mercurial command prompt, but they haven't bothered to put Mercurial itself on my path! To execute a mercurial command at all, I have to figure out/remember where Mercurial is installed, and add that directory to my path manually (and I apparently have to re-do that every time I'm going to use it, too).

That leads to another major point: stupid roadblocks. Adding the right directory to the path epitomizes what people hate about software. You definitely want to keep the user occupied with some tedious, nitpicky details rather than ever get a chance to actually accomplish anything. Knowing the right directory name to add to the path becomes like the secret decoder ring that separates those "in the know" from the unwashed masses of outsiders.

To reiterate a few of the major points: first, ensure that only the absolute most dedicated potential user is going to work his way past all this nonsense to ever actually become a user of the product at all. If an "average" user survives even half the hurdles you've placed in their way, you've failed.

The few people who work their way past all the obstacles and get the thing to work are going to be proud of it. It's basically similar to a college initiation. Even though they won't directly admit it to outsiders, knowing that most (if not all) your fellow users have survived an ordeal similar to your own builds camaraderie.

Finally, knowing all the tricks necessary to use a package effectively tends to separate people into "us" and "them". Experienced users of the package undoubtedly recognize immediately at least a half dozen "stupid" errors in what I did above, and can probably describe exactly how it's easy to do what I wanted.

Being a bit more serious for a moment, while these lead to a fanatical user base, they also lead to a small one. I will posit that I'm not a particularly stupid person. I don't know how to use this package, but the software seems to provide little help for even an intelligent person to progress from ignorant to informed. Quite the contrary, it seems (at least to the ignorant outsider) almost as if it's designed specifically to be as frustrating and difficult as possible.

I should add one last point: although I've picked on TortoiseHg for this particular post, it's far from unique. Many packages have problems similar to those above -- others have problems that are even more severe and more numerous.

Anyway, having gotten that off my chest, I return you to your normally scheduled flaming.