Ala works at NVidia Corp. as a physical ASIC designer. He can be reached at [email protected].
Let's face itdesigning a product is hard. Regardless of what the product is, it is not a trivial problem to make people like it. It is even harder to get people to use it regularly. That problem becomes exponentially more complicated if people have to pay for it. That is the dilemma facing the CEO of every company, and obviously, it is not an easy problem. In this article, I will discuss different issues that I faced while designing various things. I will limit myself to Human-Computer Interaction (HCI) in general, and User-Interface (UI) design in particular. Finally, I will bring everything together from a Perl perspective.
I have been writing GUIs for around 10 years now, mostly as a hobby. My main platform for the past five or six years has been Perl/Tk, although I have also used Qt and Delphi. One thing that bothered me about Perl/Tkand something that generates discussion on comp.lang.perl.tkis the absence of a GUI builder. So I set out to write one, thinking that it's just another GUI that I have to build, albeit a nontrivial one. After all, I have created many GUIs. I just have to slap a few buttons together, create some dialogs, stuff all possible options in menus, and voilà! A GUI builder. In fact, the first version of the program literally took me only a handful of hours to build, from start to end.
But my assumptions turned out to be very wrong. The GUI was more a hindrance than help. So I started to think about what makes one interface better than another; hence, one product better than another. The big difference, I concluded, between this GUI and most of the others I have developed is that this will have a much wider audience, whereas most of the others had been written for myself. This complicates the problem exponentially because different people expect different things to happen, and although I will never satisfy everyone, I will have to cater to everyone's needswhich might be different from mine. So, I threw everything I did out the window, and started again from scratch.
Lessons Learned
I will now outline some of the lessons I learned and design decisions that I had to make, and revise several times, in my quest to create an intuitive GUI builder. The main goal behind every decision was to minimize the effort required by users to get their jobs done, and to let them enjoy themselves in the process. In his book About Face 2.0 (John Wiley & Sons, 2003), Alan Cooper summarizes the three things that users look for in a product:
- Users want to have at least a minimal amount of work done, so they please their superiors.
- Users want to have fun using the product.
- Users don't want to feel stupid while using the product.
It is interesting to note that these three rules loosely correspond to what Larry Wall considers the three great virtues of a programmer: Hubris, Laziness, and Impatiencegetting the job done will give you a feeling of hubris, while having fun is surely just as good as laziness, and tackling a condescending interface will very quickly drive away your patience.
I will now give examples of some products and discuss their usability in light of the three rules above, and show how they mirror different aspects of Perl's design.
Expectation and Predictability
Different people have different experiences; hence, different expectations. It is essential that the user be able to predict the outcome of an action they might take. Otherwise, frustration starts to build. For example, I find it perfectly natural that double-clicking something invokes some action related to the object being double-clicked. I also assumed that this assumption was shared by everyone, so I made double-clicking on a widget open up a properties window for the widget where the user can change its properties. But I was wrong. A person reviewing a beta release of the GUI builder complained that right-clicking did not invoke a menu where he could choose the option to access the properties menu, and he couldn't find another way to do it. So I created a menu short cut to achieve the same behavior, and he was happy. Another example is Adobe's Acrobat Reader. In older versions of the software, pressing the up or down arrows would scroll a complete page up or down, respectively, while pressing the page up or page down keys would scroll the page by a small amount. This mix-up caused lots of confusion, and users resorted to using the mouse to drag the scrollbars for more predictable scrolling.
Luckily, Perl tries very hard to be predictable. For example, when testing numbers for equality using eq, Perl automatically converts them to strings. Alternatively, testing two strings that start with numbers using numerical comparison operators transforms them to numbers. Autovivification is another example where Perl does the right thing and creates any intermediate hash keys if necessary:
my %hash; $hash{key1}{key2}{key3} = 'value';
Experience
Past experience plays a big role in GUI design. You want users to feel at home when using your application. A good interface caters to those experiences, thus easing up the user's learning curve. Users will appreciate it if they can sit in front of a new interface and figure it out quickly. This lets them be more productive. For example, although the letter "V" appears nowhere in the word "Paste," binding a "Paste" function to anything other than Ctrl-V is wrong. Similarly, "Copy" has to be bound to Ctrl-C, "Undo" to Ctrl-Z, and "Cut" to Ctrl-X. The last thing you want is for people to have to learn a new technique for doing a common thing. Some other good examples are word processor programs that display a "letter" view of the document, leveraging people's familiarity with paper, and VoIP programs that display the numbers in a pad layout similar to those found on physical phones.
Perl's way of leveraging users' experiences is through its syntax. Perl borrowed heavily from a large number of very different languages, and many of Perl's constructs are very similar, in many cases identical, to those found in other languages. For example, its general syntax is very similar to C, which is the most widely used programming language. Anybody with past experience in C, C++, C#, or Java (among other languages) will be at ease with Perl's syntax, and will need to spend less time getting used to it and have more time to get useful things done.
Simplicity
People like simple things. As Einstein said, "Make things as simple as possible, but not simpler." A simple interface is an interface that people can fully understand quickly. It removes the element of uncertainty of whether the user missed an essential piece of the interface. Simple does not necessarily mean an empty interface, but rather an interface that gets out of your way and allows you to do your job. This usually translates to keeping the most widely used functions easy to access.
Perhaps the most famous example of a nonsimple interface is a VCR's clock. Something this simple should be trivial to set, yet it is anything but trivial. You have to go through a maze of menus, and sometimes press multiple remote buttons simultaneously, in order to change the clock settings. Worse still, most VCR clocks do not retain their setting and quickly diverge from the real time. I have heard countless jokes and even read some serious research papers on how to set VCR clocks. There is even a web site, http://www.vcrclock.com/, devoted to this frustrating interface. Yet, the fix is so simple. We just need to have two dials, one labeled "Hours" and the other labeled "Minutes," next to the LED display. Lifting a dial up increments the respective setting, while pushing it down decrements it. Simple and effective.
In the specific case of my GUI builder, I chose to give widgets sensible default configurations, and to hide less frequently used options. Also, I placed any option that the users will most likely modifylike a button's text and callback bindingin a toolbar, which makes it very easy for users to modify. If users need to modify more exotic configuration options, then those are still accessible, but the user has to dig a little deeper.
Some of the more famous products thrived as a direct result of their simple interfaces. Google shot to Internet fame because of its clean, empty, simple homepage. You are presented with a single text entry where you type your search query and hit "Search." That's what a search engine is supposed to do, and Google did it well. It presented the results in a simple, clean way with no intrusive text, allowing it to overtake Yahoo in the blink of an eye. Conversely, Yahoo is the epitome of clutter. I have to use my browser's "Find" function to find anything on their main web page. That's too much work. Another good example is Apple's iPod. It simply does its job through a simple, aesthetically pleasing interface, allowing it to take the portable music player market by storm, even though it didn't support some popular formats from Microsoft and Real.
Perl's simplicity is largely based in its forgiveness and its special variables. Larry Wall said that Perl makes easy things easy and hard things possible. This means that the most widely used constructs should be simple and easy to use. Less common constructs should still be possible. For example, Perl is great at string manipulation, so you'd expect that many people would use it for reading files. The usual idiom for reading from a file is:
while (<FH>)
which is equivalent to:
while (defined($_ = <FH>))
but is much simpler to write. Conversely, if you find yourself wanting to read from a binary file, then a little bit more work is needed. You have to tell Perl that this is a binary file, and use the read function to get the binary data in chunks:
binmode FH; while (read FH, $buff, $chunk_size)
Choice
This might seem contradictory to the "Simplicity" rule, but in fact it is not. A good interface can, and should, give its users the option to do anything they wish, within the limits of the product, taking care not to overburden with too much detail at once. After all, choice is a good thing. The hard part is how to give users the choice, while still keeping the interface simple and easy to use. The two most prominent Linux-based desktop managers, Gnome and KDE, serve as the best example of two extremes. Gnome's approach is to hide as much information as possible from the user, and to hide everything behind menus. For example, the latest version of Gnome has an icon on the desktop labeled simply "Web Browser." Their philosophy is that users don't need to know which web browser they are using, as long as it allows them to browse the Web as they please. KDE, on the other hand, comes with at least three different web browsers, all of them hidden under the same menu. I believe that Gnome's approach is the better one as long as it gives users the ability to change what browser to use, which it does.
Back to Perl. Perl's most famous motto is all about choice: "There's More Than One Way To Do It." Larry Wall realized that different people think differently and, therefore, might try different routes to achieve the same goal, so he gave Perl users different tools and the choice to use the ones they liked. For example, there are two versions of the binary logical operators&& and and, || and or, ! and notthat have slightly different precedence strengths. Although just one set of those operators together with proper use of parentheses is enough, Perl gives you the choice. This allows code of the form:
$flag && open FH, $file or die $!
which attempts to open the file $file only if $flag evaluates to True, and will only die if the open() fails. Simply changing the or to || will change the meaning of the code, and will require parentheses in order to produce the correct behavior. Another example is the introduction of unless and until, which are equivalent to if not and while not, respectively. Although they are not necessary, having those two extra control operators can tremendously increase code readability.
Feedback
Designers often forget that they are developing things for others to work with. Thus, it is very important that they listen to their end users and take their comments and concerns very seriously. I often find that when working on a long project that takes more than a few days to finish, I start to get impatient and want to release something quickly. So I start to cut corners and relegate many features to the "ToDo" status and end up releasing what is really a half product. A few months ago, I read very similar comments on different newsgroups by other people who develop open-source software. That is why most open-source programs have this feeling of still being in production, that there is something unfinished about them. This is probably the most important lesson of them all.
Feedback is valuable. There are a lot of smart people who could give you interesting ideas that you might not be able to come up with by yourself. For example, one of the testers of my GUI builder suggested that the dumped Perl code be wrapped up as a Perl/Tk mega widget, which could be instantiated via user-specific code. He went so far as to give me a specific example of how to do it, and I thought it was a great idea. Now the GUI builder can dump either standalone code, or a mega widget in the form of a Perl module. That is one use I didn't plan for that came almost for free.
Perl is fortunate enough to have a large community around it, which generates a tremendous amount of feedback. I wouldn't imagine such a large community would have been possible if Larry hadn't listened to their needs in the first place, and the Perl pumpkings still treat each concern with care. As an example, when the Perl6 project was announced, over 350 RFCs were submitted to Larry for consideration, and he took (and indeed is still taking) account of each one of them in his Perl6 design. That is a sure recipe for success.
TPJ