Friday, September 9, 2016

Helpful Errors


"Errors. The grate unknown. No single discipline may cover this weird and mysterious creature for all technologies...
...because what is error-handling after all? It is a curious man looking through a keyhole, the keyhole of mishap, trying to know what's going on." (Jacques Yves Cousteau)

I'm working on a new code base, and see this "errors.*" code file, And some of the errors (although, I'm happy to say, not most), reminds me an old joke:

A pilot needs to land a plane in Heathrow. It is about 4:00 AM, the fog is like a thick blanket, and his navigational equipment is a bit off. To put it in the simplest terms: the pilot is lost.
He flies around for some time, lower and lower, looking for some kind of landmark to help him find his bearings. Suddenly he notice a man looking at him out of a window. He slows down, roll down his own window, and call to the man:
"Excuse me, sir. Can you please tell me where I am?"
"Of course" - answer the man - "you are in a plane".
The pilot feels relief, turn 23.6 degrees left, continue for 13.51 miles, and land on runway 24B, just south of Heathrows' Terminal 5.
The control tower, that was aware of the pilots' predicament, asks him:
"How did you find your way?"
The man tells his story, and adds: "As soon as the man in the window answered, I knew I was over the Microsoft building. It is exactly their kind of help..."

So lets' imagine this scenario:
1. I sign-in into my e-commerce service.
2. I add some items to my basket.
3. I proceed to the checkout, and try to pay with my credit card.
4. The service return an error, saying: "CloseOrderValidationFailed".

What should I do? Should I pay again? Should I remove an Item? Should I join the navy?

CloseOrderValidationFailed is one of the errors in the "errors.*" file I looked at. It have a message, and status and code. The only thing it lacks, is meaning.

So what is a meaningful error? Here are some pointers:
  • It should help the user. If the user see's it, and say "oh, right. my bad..." - it is excellent.
  • It should never say "F**k you!". An error like "Payment Failed" is the same as saying "We do not serve people like you". Not only that it is not helpful, it is an insult.
  • It should fit it's audience. You are in a bad place when your application display something like: "Error #26748. Please contact someone that know what this error mean!". Even if you know that the users that see this error cannot do anything about it, you must help him remain positive. And I do not mean "Please do not panic", but more like: "It appear we have encountered a problem (...appearance may be deceiving...). Please try to restart your application. If it do not help, try to restart your iPad. If you do not have an iPad, please contact us in the following address, and we will be happy to sell you one." - although it looks like a joke, most people will restart the app after the second sentence, and with some luck it will give you time to fix the problem on your end.
 Finally, some guidelines I constructed, mostly to help me when I need to design an error:
  1. Talk about the "Why" rather then the "What": "Money withdrawal failed" is what happened. "Withdrawal amount exceeded the daily limit of 99$" is why it happened. Although it is helpful to know the former, I would rather be informed of the later.
  2. Suggest a solution, even if it is an obvious one: "Cannot access the internet. Please make sure your LAN cable is connected properly" helped me personally more then once.
  3. Be secured, but not frustrating: "Id check digit do not match RFC 3044" is definitely too much information, but "Make sure you omit leading zeros in the Id input" might actually save repeated head injury.
  4. Be multi-dimensional: Error should be concise when displayed to the end user, and extensive when logged to the system audit. So "LoyaltyMembershipExpired" error will include an informative message saying "Your 'Pockimon-Go' membership expired. Please go to your town center to renew it", and also some other properties like "source", "account-id" and "stack-trace" that will be visible to the technician on the back-end.
  5. Things get lost in translation: Any useful information that may be given by the error should be kept as close to the error source as possible. Do not fret to have your code, message, all your message translations and your formatting variables in the same error class (or near it).It is better not to relay on a client to convert your code into something readable if you can help it.
  6. Be unique, but do not quench other information sources: Allow your errors to be unique in the system you manage, but always allow to include errors from external sources. There are cases when a third party system will articulate why it failed much better. Make it part of your error design.
And the most impotent thing: Never underestimate the need for good error design. From the error-class to the error-auditing - all this is an important foundation to a system that can last beyond the proof-of-concept phase.






No comments:

Post a Comment