9 Answers
9

A lack of proper input validation is one of those things which tends to lead quite quickly to users doing "bad" things with your application, when it should really be handled by the programmer.

I've seen legacy apps where users have been trained to:

not enter apostrophes in names

not enter any symbol other than a-z0-9,

ensure there are no spaces before or after the text they've entered

check that a correctly formatted email address is being entered in to the email field, otherwise subsequent mailings to that user will use whatever's in the field and will fail

make sure "http://" is put before web addresses

etc etc

All of the above issues are ones which should be handled by an application developer. When your input validation is essentially "make sure the user knows what format this field should be in and trust what they've entered is right", then unexpected things are bound to find their way in to the app. Aside from the obvious security implications, users make mistakes. As programmers we often produce our best products by bending over backwards to make sure that the user can't get it wrong, no matter how hard they try!

This is so often overlooked... I can't believe we still run into these problems today!@
–
mpetersonSep 11 '10 at 15:06

1

+1 because I've seen it. BUT: A "correctly formatted email address" is notoriously difficult to validate fightingforalostcause.net/misc/2006/compare-email-regex.php make sure you know what you're doing. If you're just dealing with the subset of emails your company uses internally, that should be fine, otherwise there's more complexity than most expect. Same story for the http:// validation point. As an example, ASDF does this in a naive way, and the result is that you can't host packages on domains that use https://.
–
InaimathiNov 23 '10 at 14:55

That doesn't work... it doesn't accept emails with bang paths (yes I know who cares, but still, validating emails to the RFC IS hard.)
–
Spudd86Nov 25 '10 at 19:19

I once got a customer support call because my app just disappeared. Turned out they opened another app on top of it.

... I decided not to ensure that didn't happen again, since it was the users computer illiteracy that caused the problem, not the app. Anything I could have done to fix it would have lead to a poor user experience for others.

Almost every program that I write is invoked strictly from the command line. I've also written some fancier things that started out as CLI interfaces and rapidly grew into something more shell like than anything.

So, I can speak only for what I know. Here's some common issues with command line programs:

Way too many options

Unless you are writing a compiler or a line editor, try to keep options limited to one screen full on an 80x25 frame buffer when --help or /? is passed. It is perfectly fine to have more options than that, but break them into sub categories. For instance

foo --help

foo --help option_name

No long options

It is much easier to remember foo --attach_to [argument] --volatile --verbose than it is to remember foo -a [arg] -v +V. This isn't always possible, but in most cases, it is.

No input validation

Almost every platform has multiple libraries that are tried, tested and true when it comes to parsing and validating arguments. Almost every platform has a tried, tested and true lexer that validates input from a CLI. Use one, the other or both. If your program segfaults or divides by zero due to something a user provided, that's just embarrassing.

You might not need something as complex as a lexer, perhaps you can just tokenize the string if you are expecting stuff in a certain order with certain things in certain places.

I actually got a bug report once where an integer was expected and someone typed f*** my life in quotes. I didn't write that program, I had the misfortune of inheriting it.

No 'verbocity' knob

Allow experienced users to easily discover how to get way more noise out of your program than most people would tolerate, but default to printing serious and critical stuff only. I can't tell you how many times I had to fire up strace just to realize that something segfaulted because it operated on a NULL file stream.

You can also wrap assertions so that turning them off via NDEBUG or other means still results in something printed or logged for the user to find.

Speaking of log files, try to make sure anything you place in them makes (at least a little) sense to someone other than you. If the start of every entry is a UNIX epoch date, you're going to compound frustration in someone who really wants to help you reproduce the bug.

No 'bug buddy' in debug mode

A lot of programs offer some sort of 'debug' switch that offers extra chatter regarding what is going on with the program, but very few offer the following:

A way to automatically send a report via HTTP/HTTPS and get some kind of service reference number

A way to dump useful information to a file that could be sent as an attachment to a support request

Or, perhaps you like hearing people read the following over the phone:

It says unexpected condition at zero
eff oh four zero oh .... OK lemme read that back to you ...

Overly complex configuration files

Don't justify the need to parse a config as an excuse to get a buzz on lots of syntactic sugar. Try to use a format that people actually know, even if it means extra work when parsing. I try to use the INI style format whenever possible. You'd be amazed what you can pull off with a simple key->value dictionary.

No configuration files

Don't make people write shell scripts or batch files just to use your program, unless it was intended to be a tool for either task. Give me a means to point at a file containing my usual options and provide just a few additional arguments.

No 'wet floor' signs

If some feature could get the user into trouble (perhaps it is there for advanced users), clearly mark it as such. Additionally, if someone fat fingers input or forgets something, have you program print a very friendly link to on-line documentation. You might be dealing with someone who is using your program via KVM and can't cut and paste.

When possible, (this coincides with input validation) use the Google apporach:

Did you mean foo --bar FILENME, you
typed only foo --bar

Offer a way out of destructive instructions

The goal is to tell the user why it didn't work and have them try a few more times, while ensuring that you do nothing potentially destructive unless it appears that the user really wants you to do that. Allow a switch that turns off 'nagging' , for instance -Y or /Y but otherwise allow a way out for someone who simply has 'fat fingers'.

I'm probably forgetting a few pointers. I deal with this frequently as it is very, very difficult to make the 'low level' interface for something intuitive enough for most people to avoid making mistakes.

I don't feel like getting specific break/fix examples is as important as realizing this:

Users do not read your manual, or watch your tutorials. They learn your software through exploration.

If through that exploration they break something, as a programmer it is your job to either warn them of the danger or prevent it from happening in the first place. I can't remember where I saw it now, but in the back of my mind I always try to "make doing the right thing easy" for the user of my software.

If you insist on examples:

User was able to enter a lowercase name that broke the integration code / fixed by performing input validation

User was able to click the wrong button after performing an action / fixed by only showing the correct buttons.

User was able to do X accidentally / fixed by warning them they are about to do X.

Warnings should be reserved only for the most destructive operations, and you should avoid having any of those, undo is MUCH MUCH MUCH better, people have now been trained to click on 'OK' without even reading the box, it's muscle memory now, avoid them for any operation the user might conceivably do on any sort of regular basis to avoid this effect.
–
Spudd86Nov 25 '10 at 19:22

Why the "quotes". Are you suggesting they deliberately clicked yes, just so they could phone you up?
–
Peter BoughtonSep 9 '10 at 13:32

1

Easily solved by using "soft deletes" which can be undone.
–
Robert HarveySep 11 '10 at 17:33

yes they can be undone, but why delete it in the first place? Thats why i put that warning there, asking them to confirm twice that they want to delete it:)
–
QuamisSep 14 '10 at 13:03

2

@Quamis: Dialog boxes have become so annoying to many users that they just click OK, Yes, whatever, just to get through the dialog box. That's why many new systems use a soft delete without confirmation, and give the user a way to undo. Most mail systems now work this way, for example.
–
Robert HarveyNov 23 '10 at 16:03

1

@Robert Harvey - I understand, and yes that's the specific reason a hard delete had to be implemented. This specific example could be solved by tracking retention policies, but there are probably cases where people press "Delete" rightly expecting the consequence of that operation to be a true deletion. I favor the soft delete route myself, but my point was that it's sometimes not an option.
–
InaimathiNov 23 '10 at 17:29

Here is one I heard this week. A user asks for a feature "send me a notification when an event occurs". Simple enough and the developer goes ahead and implements it. Sure, the first question should have been "what are trying to address by this notification?". I won't go into that. Few days later the user stops by the developer and asks "I got this notification. What am I supposed to do with it?".

I remembered this Dilbert comic and suggested to the developer "write an app to figure out what the user should do with that notification".

Like mpeterson said, the user is very competitive in their area of expertise. They just don't think like a software developer or designer.

Having a good user interface and providing an adequate learning experience goes a long way towards preventing users from doing bad things.

Good user interfaces should be
frictionless.

Instead of throwing up a dialog box (an expensive operation, and one that users ignore after awhile) to confirm a delete, perform the delete, and offer a way to undo.

Good user interfaces should be
discoverable.

Although the ribbon in Microsoft Office gets a lot of flak because it forces old users of Word to change their ways, the ribbon is a shining example of how you can make an interface discoverable (i.e. easy to discover).

Good user interfaces, like good code,
should be self-explanatory.

Nobody reads the manual. The only manual I ever got my users to read was a PowerPoint presentation containing step-by-step walkthroughs of the software. I have seen these done with video tools like Camtasia, but PowerPoints are better because you can easily flip backwards and forwards through the steps.

Back when I lived with my parents, my dad asked me why he was disconnected from the internet every time he checked his email (yes, this was back in the Stone Age when we had dial up - I'm just that old). I asked him to show me - guess what I saw? When Outlook Express' Send & Receive dialog came up, the option to disconnect after sending and receiving was ticked. I think that one's all on the user...
–
JohnLNov 23 '10 at 15:32

3

Not really John.. If the outlook programmers had thought this through they would not have placed that CheckBox over there or gave it a more meaningful label. Your dad is not an idiot: this feature was not thought over or been through usuability tests. Software is not here to make us feel stupid! :)
–
ArcturusNov 23 '10 at 15:37

-1: Users do make mistakes, even if they could be avoided with things like better labeling. The point is, this question is asking for specific issues that have specific solutions. Just saying "test it" is simply a bad answer.
–
MaxpmNov 6 '11 at 4:44