Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing useful error messages

Writing useful error messages

English version of slides from a talk presented at local Python user group in Florianopolis.

Dfd7b9492f5c5e49dca373bfdd7a3b1a?s=128

Elias Dorneles

November 04, 2015
Tweet

More Decks by Elias Dorneles

Other Decks in Programming

Transcript

  1. Writing useful error messages Elias Dorneles @eliasdorneles

  2. EMPATHY Core value in software engineering

  3. Why do I need to put myself in the shoes

    of the user?
  4. It’s nice to have an UX professional designing end user

    interactions, including the error messages
  5. The best error message is no error message If you

    know what to do, don’t try “educating” users: just do it! $ python Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> exit Use exit() or Ctrl-D (i.e. EOF) to exit >>> UGH! Don’t use people attention unnecessarily.
  6. Sometimes it’s just a matter of trying again https://pypi.python.org/pypi/retrying

  7. Provide feedback as early as possible

  8. Example: checking required arguments def check_arguments(args, required): """Check if required

    arguments are present in args dict """
  9. Example: checking required arguments def check_arguments(args, required): """Check if required

    arguments are present in args dict """ for arg_name in required: if arg_name not in args: raise ValueError("Required argument: %s" % arg_name)
  10. Example: checking required arguments >>> required = ('name', age', 'phone')

    >>> check_arguments({'name': 'Elias'}, required) ... ValueError: Required argument: age >>> check_arguments({'name': 'Elias', 'age': 99}, required) ... ValueError: Required argument: age UGH!
  11. Provide feedback as early and as informative as possible

  12. Example: checking required arguments def check_arguments(args, required): """Check if required

    arguments are present in args dict """ missing = set(required) - set(args) if missing: msg = "Missing arguments: %s" % ', '.join(missing) raise ValueError(msg)
  13. Example: checking required arguments >>> required = ('name', age', 'phone')

    >>> check_arguments({'name': 'Elias'}, required) ... ValueError: Missing arguments: age, phone
  14. Example: checking required arguments >>> required = ('name', age', 'phone')

    >>> check_arguments({'name': 'Elias'}, required) ... ValueError: Missing arguments: age, phone >>> check_arguments({'name': 'Elias', 'age’: 99, 'phone':'007'}, required) >>>
  15. Same principle in other situations • Check available space before

    copying/uncompressing files • Validate fields in a form as they are being filled • In unit tests, use an assertion that covers everything (ex: assertItemsEqual() , or roll your own)
  16. “If you hit this sign, you will hit that bridge”

  17. People generally don’t read error messages It’s not stupidity: it’s

    limited attention. People have better things to do than hand-holding your program. ;-)
  18. Keep it short.

  19. Keep it short. But not cryptic.

  20. Example: sending notification def notify_product_is_available(product): try: NotificationService.send(type='product_is_available', id=product.id) except: print("Something

    bad happened sending product_is_available") WAT?
  21. Avoid using names of internal things from your code

  22. Provide context, inform for real

  23. Example: sending notification def notify_product_is_available(product): try: NotificationService.send(type='product_is_available', id=product.id) except: print("Error

    notifying product %s is available: %s" % (produto, e))
  24. Example: sending notification import logging def notify_product_is_available(product): try: NotificationService.send(type='product_is_available', id=product.id)

    except: msg = ("Error notifying product %s is available: %s" % (produto, e)) logging.error(msg)
  25. Tell what to do to solve the problem

  26. Example: def publish_app(app_id): try: deploy_application(app_id) return {'status': 'ok'} except ServiceUnavailable:

    message = ("The service is unavailable at the moment." " Try again in a few minutes.") return {'status': 'error', 'message': message}
  27. Another example: def send_email(email): try: EmailService.send(email) return {'status': 'ok'} except

    UserQuotaExceededError: message = ("You reached the limit for your current plan." " Upgrade plan at: http://example.com/upgrade") return {'status': 'error', 'message': message}
  28. Be serious Confused or frustrated users are not having fun.

    Don’t joke around.
  29. In short: 1. Solve the problem automatically, if possible 2.

    Point out problems as early as possible 3. Be short, but provide full context 4. Indicate how to solve the problem 5. Be serious -- frustrated users aren’t having fun
  30. Thanks! Elias Dorneles http://twitter.com/eliasdorneles References: • http://www.ihearttechnicalwriting. com/write-error-messages/ • http://uiwriting.tumblr.

    com/post/128339130079/4-things-to- improve-ui-writing • http://www.nngroup.com/articles/error- message-guidelines/ • https://developer.gnome.org/hig- book/unstable/language-errors.html.en • http://bugroll.com/how-to-write-good- error-messages.html