Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
Good practice demands that we show the user an error message when exceptions occur so they know what went wrong. I want to make the case that good design makes exceptions the exceptionâââsomething so wrong that the user can not do anything about it. In most cases, the best approach will be to show the user a single, generic message when exceptions occur.
An Unexplainable Exception
As always, the context is a modern mainstream web application. So we will start out of the blocks with a simple registration form. We require a userâs email and a password that is exactly 4 characters long. We can assume that the form has working validation on both the client side and the server side.
To our surprise, we receive an email from a customer. He complains that the registration isnât working and attaches the following screenshot:
Obviously, the userâs password is exactly 4 characters long. Just as obviously, the form validation agreed with that and set the border colour to green. For some reason, however, the backend reached another opinion and displayed the error message.
Our user does not know what he did wrong. Even worse, he does not know how to proceed with the registration.
How did it come that far? How could we have avoided that? Before we go into detail, letâs clarify some basic things.
Exception === Uncontrolled State
We should not mistreat exceptions as alternatives to if conditions.
For example:
public boolean validateRegistration(String email, String password) { /* some validation code */ try { this.checkPassword(password); } catch (PwLengthException ple) { return false; } return true; }
public void checkPassword(String password) throws PwLengthException { if (password.size != 4) { throw new PwLengthException(âThe password requires a lenght of 4â); } }}
If the password is invalid, then the function checkPassword will throw an exception. The exception is used as a conditional expression in the caller.
However, we should consider each exception as an unexpected, and therefore uncontrolled state, of our application.
Rocket science takes that to the maximum. If an exception bubbles up to the main routine, then it usually triggers the systemâs self-destruction commands. The developers understood the true nature of exceptions: the system is beyond their control. That state requires extreme measures to prevent even more catastrophic events.
Ariane 5 triggering self-destroy after an unhandled buffer overflow exception in 1996. Source:Â ESA
We are web developers, not rocket scientists. Exceptions in our systems will never require similarly drastic measures like destroying the userâs laptop because the password complexity is wrong :).
Like rocket scientists, however, we design our systems in a way that exceptions never occur. If they do, then we are in unknown territory.
The example can be corrected to:
public boolean validateRegistration(String email, String password) { /* some validation code */ if (!this.isValidPassword(password)) { return false; } return true; }
public boolean isValidPassword(String password) { return password.size == 4; }
UI as Gatekeeper against Invalid Data
How can we achieve an application design that makes exception throws theoretically impossible?
It is the task of the user interface to keep the user on the right track. Each possible action should be part of a defined process. There should be no way for the user to step out of that designed path.
Invalid input from the user is part of this process. Since it is a planned state of our application, there is no reason to throw an exception. It only becomes a problem, when that invalid input passes unfiltered to our backend. Therefore, the UI needs to handle it via validation.
So our frontend acts as the gatekeeper. It makes sure that only valid data finds its way into our system. That implies that our system, theoretically, cannot enter an uncontrolled state.
Our password input example is just one type of input that requires frontend validation. A userâs access may require a security clearance. Or a userâs country may define regional restrictions. Even more commonly, a user must manually enter a valid URL.
Of course, this does not free us from proper validations in our backend. One cannot blame the frontend, for example, if users are bypassing it on purpose. They could change URL parameters. Or they may be sniffing endpoints and sending manipulated data.
In these cases, we are in an uncontrolled situation. Throwing an exception is justified. But please catch it with a standard error screen.
From Theory to Practice
Letâs recap. Weâve made sure that exceptions are only thrown when the application enters an uncontrolled state. Weâve made sure that only valid data can enter our system. Therefore, no frontend-lead action can fail the system, right? Wrong!
Letâs come back to our initial example. It turns out that our server-side validation code somehow used an array of bytes instead of a simple StringâŠ
public void finishRegistration(String email, String password) { /* some validation code */ if (!this.isValidPassword(password.getBytes())) { /** * only for safety reasons. Canât happen due * to proper client validation */ throw new PwLengthException( âThe password requires a length of 4â); } return true;}
public boolean isValidPassword(byte[] password) { return password.length == 4;}
In UTF-8 an âĂŒâ takes two bytes. Source: imgflip.com
You think this doesnât happen in practice? Well, my friend ⊠these things happen ⊠all the time.
Unknown Root Cause
As we have seen, the user input itself was not the root cause. It is our application which has a bug.
Worse, we display an error message to our users that is incorrect. That simply confuses them. After all, they did everything right.
If we are honest our message should read something like âDear user, your password seems to be fine. For some as-yet unexplainable reason, it hasnât been accepted by the backend. Weâve messed up. Sorry.â
How to fix this bug?
It should be clear by now that, with sound validation mechanisms in place, exceptions still occur. But we can be quite sure that, if an exception is thrown, it is not the fault of the user.
Therefore, it does not make sense to put our efforts into a module capable of showing different error messages, each one internationalised and supporting substitution of contextual information like âPassword requires a length of 4 instead of %sâ.
Just apologize. Then make sure we log the incident along with all contextual information we can gather. Letâs use a sophisticated log collector and optimise our internal processes to fix these errors as quickly as possible. Thatâs all we can do.
Summary
An Exception is no alternative to an if condition.
The user interface should make sure that an exception from the userâs side canât occur.
Donât confuse your users by showing them misleading information.
Originally published at www.rainerhahnekamp.com on January 14, 2018.
Useless Error Messages was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.