Don’t aggravate your users

In my career I’ve worked with and mentored many less experienced programmers. One thing I stress when reviewing their UI designs with them is data validation. Anybody who’s worked with me for more than a week has probably heard me say, “The best way to handle bad data is to prevent it from entering the system.”

It seems obvious, but I actually had to work on a system in which date fields were accepted as input strings, and then validated at each use. There was a whole mess of messy code involved with recovering from invalid date fields. But that’s a story for another time.

The typical way to prevent bad data from entering the system is to validate it on input and reject whatever isn’t valid. If the user enters “ham and cheese” in the Birthday field, don’t accept it. Tell the user to enter a valid date.

Some programmers take this too far and try to prevent the user from entering potentially bad data. In a date input field, for example, they’ll display a prompt showing the format “MM/DD/YYYY”.

The input control is customized so that the user can enter only numbers. The user’s input overwrites the letters, and the cursor is never placed on a slash. The control actually helps the user enter a date in the correct format, but it’s still possible to enter an invalid date. That is, nothing in the control itself prevents the user from entering a date of 99/99/9999. The format of the data is correct, but the value is not a valid date. That’s okay: the value is checked when the user exits the field or submits the form.

Every programmer, either of his own volition or because he was told to by a misguided UI designer, will eventually try to prevent the user from entering a bad date. And that’s when things get ugly.

For example, the user enters the date “10/13/2024”. Then she realizes that she made a mistake. That was supposed to be “10/31/2024”. So she hits the back arrow key and positions the cursor under the ‘1’ in “13”. She’s going to type “31” to replace “13”. But the control won’t let her do that because if she enters ‘3’ in that position it will result in “10/33/2024”. Clearly an invalid date and not to be allowed.

So now we’re in a situation where the user wants to do something completely reasonable (type “31” over the “13”), but the control won’t allow it. She has to jump through hoops to fix her error.

Control customization that actually helps the user enter valid data is A Good Thing. But if the control makes it difficult to enter valid data, it’s gone too far. Users are happy to correct fields in which they’ve entered bad data. They are not at all amused by controls that punish them for making common mistakes. That kind of thing is what I call “actively user-hostile.” It’ll make people hate your application.

I’ve heard programmers argue that it’s easier to let the control constrain the input than to validate all the fields when the form is submitted. It’s certainly not easier for the user! And I don’t think it’s any easier for the programmer, either. Forms quite often have interdependent fields that can’t easily be validated individually. The only reasonable time to validate is when the form data is submitted. Custom data input controls can’t change that.

Standard UI controls work well and modern UI frameworks support validate-on-submission. Everything’s there to make the process easy for the programmer and painless for the user. There’s nothing to be gained by attempting to prevent the user from making a mistake. It’s much easier and more user-friendly to let the user submit the form, validate all the data at once, and then prompt the user to fix the fields that have errors. Don’t waste your time on custom controls that do nothing but aggravate your users.