Recently I got into cordial argument with someone while designing a simple command line interface. The point of contention was the behaviour of the validation function.
Programming design patterns suggest that the best computer programs are written in the form of modules wherein each module performs a very specific task, no more - no less. A function such as ‘validate’ or ‘isValid’ or ‘checkValidity’ is meant to return one of two values - true if the passed argument is valid, false otherwise.
Conceptually, this makes perfect sense. After all, does that not make it very clear to the developer what the function does and what to expect once it finishes executing? Of course it does. Now it does not matter that in your function you can have 10 validation rules that the user input has to go through. As long as the function spits out a true or a false, everyone is happy. Isn't it?
Well, let me tell you this. Not EVERYONE is going to be happy about it. Because you just forgot about the person for whom you are building your application. The person who has a life outside of your application. The person who has a short term memory of 7 units of information, who is human, inherently makes mistakes and receives tremendous joy when he/she gets things right. The person who fumbles and sometimes needs a helping hand to get up and get back on track, wants to use your product and maybe needs come back to it again.. and again.. and again.
With multiple ways in which someone can enter wrong input, it is CRUEL to simply return a bland ‘false’ from a validation function and torment the helpless user. Unless your product is a game, you don’t have the right to punish someone who makes a mistake while using your application.
Now, I am not saying that design patterns are wrong. from that. In fact, they are probably the reason why we are this stage in history to even have a discussion on human computer interaction. However, with people being the primary focus of our products, the way we design and develop our computing solutions has to change.
Speaking of the validation problem. How could you actually make it less hideous?
Lets see, how about first setting a goal and then trying to achieve it?
The goal of any user facing validation function is to allow the user to recover from the error.
Thats it. Thats all you need to think of while designing a solution for this problem.
One of the simplest approaches is to return an error code instead of a ‘false’ when there is an invalid input. These error codes can then be looked up in a configuration table (that is probably set up for internationalization) and the corresponding description that maps to the error code can then be returned to the user.
Although the above approach is sufficient for simple validations functions, it will however not suffice for complex validation applications. If there are 10 rules, and the user input is incorrect for many of them, would it not be much more appropriate to show all the mistakes in the input in the first attempt so that the user can recover faster instead of opening an unnecessary window of opportunity for the user to correct each mistake one at a time after several attempts?
Return an array of error codes instead of a false. As discussed in Approach 1, a configuration table can be used to look up the corresponding error description with internationalization(if applicable) and present all the messages to the user in a single interaction.One can also take a more defensive approach. And that is, by providing the user information beforehand about what comprises of a valid input.
You can specify, in a summarized format, the rules for a valid input and then check the off one by one as the user provides an input. The catch is that if you have a lot of rules, you probably wont have enough real estate to show all the rules.
Lead by example, i.e. There's nothing better than a sample valid input that the user can see and use as a guideline thereby eliminating the need to show most of the rules. In my opinion, a combination of Approach 3 and Approach 4 would mitigate a lot of frustration for your users.
Perhaps there are better ways to solve this problem that I am not aware of. The point that I am trying to make is that as developers, we have to understand that no matter what we are building, the human mind has a limited capacity to memorize things, a limited of tolerance for failure and a limited attention span. If you exhaust all of these human capacities in your users, its only a matter of time that someone smart enough figures out what you are doing wrong, builds a better and less frustrating product and sweeps away your users from right below your nose.
As Alan Cooper would have said
Stop making dancing bears.
*A dancing bear is an analogy that Alan Cooper uses in his book The inmates are running the asylum to a product that people use even though it has a faulty user experience, just like a dancing bear whom people would watch with fascination not just because it dances but because it is a bear that can also dance.