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

Human Errors

871fc089cd3cbbc18b9f868c8dd85cce?s=47 Olivier Lacan
November 15, 2017

Human Errors

Runtime errors can sometimes turn into dark and unpleasant journeys which lead you to question the nature of reality. Thankfully, Ruby often provides friendly feedback for understanding the cause and remedy for exceptions. Yet, there are situations in which programmers don't receive clear enough context for what really caused an exception and how to address it. We'll look at Ruby's error feedback mechanisms and search for constructive ways in which they can be made more helpful to humans.

This talk was presented at RubyConf 2017.

871fc089cd3cbbc18b9f868c8dd85cce?s=128

Olivier Lacan

November 15, 2017
Tweet

Transcript

  1. Human Errors

  2. Humans?

  3. None
  4. None
  5. None
  6. Olivier |oh-lee-vee-yay|

  7. Olivier |oh-lee-vee-yay|

  8. Olivier |oh-lee-vee-yay|

  9. Olivier |oh-lee-vee-yay|

  10. Olivier |oh-lee-vee-yay|

  11. None
  12. None
  13. @olivierlacan |figure-it-out|

  14. None
  15. Mistakes

  16. purpose” “On

  17. None
  18. (French flag circa 1803)

  19. None
  20. Mistakes are made

  21. recovery error

  22. recovery error feedback

  23. recovery error feedback

  24. context error recovery feedback

  25. context error recovery feedback

  26. Why?

  27. What?

  28. How?

  29. When?

  30. Where?

  31. Error? What is an

  32. error noun the state or condition of being wrong in

    conduct or judgment: the crash was caused by human error | the money had been paid in error. | ˈerər | a mistake: spelling errors | an error of judgment.
  33. the state or condition of being wrong in conduct or

    judgement
  34. Error (technical): a measure of the estimated difference between the

    observed or calculated value of a quantity and its true value.
  35. observed_value != true_value

  36. Origin: from Middle English errour, from Latin error (“wandering about”),

    infinitive of errō (“to wander, to err”). error noun | ˈerər |
  37. Wandering

  38. Friendliness

  39. Hostility

  40. STOP

  41. None
  42. End-users

  43. USERS 1970 - 2017 Succumbed to yet another Lorum Ipsum

    placeholder text.
  44. Middle-users

  45. None
  46. start

  47. start middle

  48. start middle end

  49. start middle end

  50. start middle end

  51. None
  52. None
  53. None
  54. None
  55. None
  56. None
  57. None
  58. None
  59. None
  60. ArgumentError

  61. def explode(code) puts "#{code} Boom!" end

  62. > explode ArgumentError: wrong number of arguments 
 (given 0,

    expected 1) from (irb):1:in `explode' from (irb):4 from /…/2.4.0/bin/irb:11:in `<main>'
  63. > explode ArgumentError: wrong number of arguments 
 (given 0,

    expected 1) from (irb):1:in `explode' from (irb):4 from /…/2.4.0/bin/irb:11:in `<main>'
  64. def explode(code) puts "#{code} Boom!" end

  65. > explode("abcd") abcd Boom! => nil

  66. def explode(code:) puts "#{code} Boom!" end

  67. :

  68. > explode ArgumentError: missing keyword: code from (irb):9:in `explode' from

    (irb):12 from /…/2.4.0/bin/irb:11:in `<main>'
  69. > explode("abcd")

  70. > explode("abcd") ArgumentError: wrong number of arguments (given 1, expected

    0) from (irb):9:in `explode' from (irb):13 from /…/2.4.0/bin/irb:11:in `<main>'
  71. def explode(code:) puts "#{code} Boom!" end

  72. None
  73. nobutime! 24d38cc447ee122c07208cf87a7899fe77792b02 c00265bbcc5deb1bcfcd0faa0cf8c4c42968de8e 50702d16ab5862413351520b65da820194dbf8d7 fe3decb2017af2092d4b2181e27e4cd8f6bbf4fa 73e41247b93a74c9b2ec95a374736fdb98fcaac5 a48fac6e226d182d7b1a7d05f47bcd7f1d1e7370 9cabbf849e333d2e09abb323fcd3100c4ef51095 496b4267b2015254edb176f98943d7599b43d22f

  74. None
  75. None
  76. None
  77. > explode("abcd") ArgumentError: wrong number of arguments (given 1, expected

    0; required keyword: code) from (irb):1:in `explode' from (irb):4 from /…/2.5.0-preview1/bin/irb:11:in `<main>'
  78. None
  79. 2.5.0 Christmas 2017

  80. None
  81. Help Ruby

  82. Joy

  83. “For me the purpose of life is partly to have

    joy. Programmers often feel joy when they can concentrate on the creative side of programming, 
 So Ruby is designed to make programmers happy.” Yukihiro “Matz” Matsumoto
  84. Rust

  85. None
  86. Elixir

  87. None
  88. Elm

  89. None
  90. Ruby

  91. irb(main):015:0> expode NameError: undefined local variable or method `expode' for

    main:Object Did you mean? explode from (irb):15 from /…/2.4.0/bin/irb:11:in `<main>'
  92. Instant Recovery

  93. Handling Not

  94. None
  95. Voodoo Contextual

  96. None
  97. None
  98. None
  99. foo.call && bar.call NoMethodError: undefined method `call' for nil:NilClass

  100. Did it? Who

  101. @foo.call && @bar.call ^---- NoMethodError: The method `call` is undefined

    on receiver nil:NilClass
  102. Context First,

  103. @foo.call && @bar.call ^---- NoMethodError: The method `call` is undefined

    on receiver nil:NilClass
  104. Feedback Then,

  105. undefined method `call' for nil:NilClass

  106. The method `call` is undefined on receiver nil:NilClass

  107. Clarity Care &

  108. Matters How you say it

  109. None
  110. None
  111. Contextualize Go forth &

  112. None
  113. Elm Street An error on

  114. None
  115. What happened

  116. None
  117. Context: type of error

  118. Where it happened

  119. None
  120. How it happened

  121. None
  122. How to recover!

  123. None
  124. 10

  125. $ bin/rspec spec/ --bisect --seed 36929 Bisect started using options:

    "spec/ --seed 36929" Running suite to find failures... /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/shell_escape.rb:20:in `escape': undefined method `shellescape' for #<Pathname:/Users/olivierlacan/Development/cs/CodeSchool/lib> (NoMethodError) from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:154:in `block in load_path' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:154:in `map' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:154:in `load_path' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:26:in `command_for' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:68:in `block in run_locations' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/server.rb:27:in `capture_run_results' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:67:in `run_locations' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/runner.rb:50:in `original_results' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/example_minimizer.rb:114:in `block in prep' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/example_minimizer.rb:151:in `track_duration' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/example_minimizer.rb:113:in `prep' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/example_minimizer.rb:17:in `find_minimal_repro' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/coordinator.rb:37:in `block (2 levels) in bisect' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/server.rb:18:in `run' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/coordinator.rb:32:in `block in bisect' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/reporter.rb:191:in `close_after' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/coordinator.rb:31:in `bisect' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/bisect/coordinator.rb:19:in `bisect_with' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/invocations.rb:32:in `call' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:69:in `run' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:45:in `invoke' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/rspec-core-3.6.0/exe/rspec:4:in `<top (required)>' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-5.0.6/lib/active_support/dependencies.rb:287:in `load' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-5.0.6/lib/active_support/dependencies.rb:287:in `block in load' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-5.0.6/lib/active_support/dependencies.rb:259:in `load_dependency' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-5.0.6/lib/active_support/dependencies.rb:287:in `load' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/nakayoshi_fork-0.0.3/lib/nakayoshi_fork.rb:24:in `fork' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/nakayoshi_fork-0.0.3/lib/nakayoshi_fork.rb:24:in `fork' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require' from /Users/olivierlacan/.rbenv/versions/2.3.4/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require' from -e:1:in `<main>'
  126. undefined method `shellescape' for #<Pathname:/.../lib> (NoMethodError)

  127. What happened

  128. rspec-core-3.6.0/lib/rspec/core/bisect/ runner.rb:154:in `block in load_path'

  129. Where it happened

  130. Where it happened ?

  131. How it happened

  132. How it happened

  133. How to recover!

  134. How to recover!

  135. 5

  136. Unclear & too late

  137. ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write

    permissions for the /Library/Ruby/Gems/2.0.0 directory.
  138. What happened

  139. What happened

  140. Where it happened

  141. Where it happened

  142. How it happened

  143. How it happened

  144. How to recover!

  145. How to recover!

  146. 5

  147. What’s missing?

  148. A way foward

  149. context error recovery feedback

  150. Resolution Hints

  151. “A library or application not having a functional need to

    rescue a possible error doesn't grant us license to ignore how confusing that error may be for the person who ultimately sees it.” Justin Searls
  152. Libraries

  153. Maintainers & users

  154. Farm-to-table Exceptions

  155. Languages

  156. Implementors & users

  157. Turn-by-turn Contextualization

  158. Work to do

  159. error.c

  160. * The built-in subclasses of Exception are: * * *

    NoMemoryError * * ScriptError * * LoadError * * NotImplementedError * * SyntaxError * * SecurityError * * SignalException * * Interrupt * * StandardError -- default for +rescue+ * * ArgumentError * * UncaughtThrowError * * EncodingError * * FiberError * * IOError * * EOFError * * IndexError
  161. None
  162. ArgumentError

  163. None
  164. ERROR EXCEPTION

  165. ERROR FAILURE

  166. ERROR FAILURE EXCEPTION

  167. ERROR FAILURE EXCEPTION

  168. Let's make it a rule to take better care of

    our exceptions.
  169. None
  170. Merci

  171. @olivierlacan