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

Rethinking Errors by Bruce Eckel

Rethinking Errors by Bruce Eckel

Rethinking Errors by Bruce Eckel

PyCon 2013

March 15, 2013
Tweet

More Decks by PyCon 2013

Other Decks in Programming

Transcript

  1. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 2/19 Rethinking Errors Bruce Eckel,

    Consultant Presentation: www.mindviewinc.com/Etc/RethinkingErrors.html www.MindViewInc.com www.Reinventing­Business.com www.AtomicScala.com
  2. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 3/19 Overview Some Error­Reporting History

    A New & Simple Approach: 1. Clump together return object and error object 2. Caller can’t pretend that what they get back is always good How it Works in Go, Scala and Python
  3. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 4/19 The Problem I’m Looking

    At Incorrect inputs, not buggy function or system reliability problems Bad error handling produces bad programs Main problem is novice programmers: “If the compiler or runtime doesn’t tell me I’m doing anything wrong, then I must be doing everything right!” Attitude can persist for a LONG time!
  4. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 5/19 Error Reporting in C

    Numerous experiments, nothing worked: Return an unlikely value (like ­1) Set a global error flag Raise a signal (that you’ve previously set a signal handler for) s e t j m p /l o n g j m p (non­local goto) I could always pretend that I was just getting a good result
  5. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 6/19 Error Reporting in C++

    Introduced exception handling (Liskov, 60’s) Introduced exception specifications (Not enforced) t r y ­c a t c h blocks, f i n a l l y
  6. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 7/19 Error Reporting in Java

    Copied C++ Exceptions, except: Enforced the exception specification via checked exceptions Unified error reporting via exceptions Other languages: Python, deeply integrated & (relatively) efficient. Even an end­of­iteration is indicated with an exception. Ruby Even PHP!
  7. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 8/19 Exceptions Everywhere is Great!

    A single answer to all problems House on fire, throw an exception Dog piddles on carpet, throw an exception
  8. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 9/19 Except … Overhead System

    More importantly, Programmer Appropriateness: One size doesn’t fit all. It’s not always best to Panic and throw it all away Jump to a different context Process boundaries Typically, only one exception can be extant at a time
  9. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 10/19 Go: Initially No Exceptions

    Later added p a n i c and r e s u m e for special cases f u n c O p e n ( n a m e s t r i n g ) ( f i l e * F i l e , e r r e r r o r ) f , e r r : = o s . O p e n ( " f i l e n a m e . e x t " ) i f e r r ! = n i l { l o g . F a t a l ( e r r ) } / / D o s o m e t h i n g w i t h t h e o p e n * F i l e f
  10. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 11/19 Scala’s “Either” i m

    p o r t c o m . a t o m i c s c a l a . A t o m i c T e s t . _ d e f f ( i : I n t ) = i f ( i = = 0 ) L e f t ( " D i v i d e b y z e r o " ) e l s e R i g h t ( 2 4 / i ) d e f t e s t ( n : I n t ) = f ( n ) m a t c h { c a s e L e f t ( w h y ) = > s " F a i l e d : $ w h y " c a s e R i g h t ( r e s u l t ) = > r e s u l t } t e s t ( 4 ) i s 6 t e s t ( 5 ) i s 4 t e s t ( 6 ) i s 4 t e s t ( 0 ) i s " F a i l e d : D i v i d e b y z e r o " t e s t ( 2 4 ) i s 1 t e s t ( 2 5 ) i s 0
  11. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 12/19 Custom Error Reporting in

    Scala i m p o r t c o m . a t o m i c s c a l a . A t o m i c T e s t . _ i m p o r t u t i l . { T r y , S u c c e s s } i m p o r t c o m . a t o m i c s c a l a . r e p o r t e r r . F a i l d e f f ( i : I n t ) = i f ( i = = 0 ) F a i l ( " D i v i d e b y z e r o " ) e l s e S u c c e s s ( 2 4 / i ) d e f t e s t ( n : I n t ) = f ( n ) . r e c o v e r { c a s e e = > s " F a i l e d : $ e " } . g e t t e s t ( 4 ) i s 6 t e s t ( 5 ) i s 4 t e s t ( 6 ) i s 4 t e s t ( 0 ) i s " F a i l e d : D i v i d e b y z e r o " t e s t ( 2 4 ) i s 1 t e s t ( 2 5 ) i s 0
  12. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 13/19 Python: Return a Tuple

    as a Result d e f f ( n ) : i f n > 1 0 : r e t u r n n * 1 0 , F a l s e e l s e : r e t u r n N o n e , T r u e d e f t e s t ( n ) : r , f a i l = f ( n ) i f f a i l : p r i n t n , " f a i l e d " e l s e : p r i n t r t e s t ( 9 ) t e s t ( 1 1 ) Not bad, like the Go language.
  13. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 14/19 Return an Object c

    l a s s R e s u l t ( o b j e c t ) : d e f _ _ i n i t _ _ ( s e l f , r e s u l t , f a i l = F a l s e ) : s e l f . r e s u l t = r e s u l t s e l f . f a i l = f a i l c l a s s F a i l ( R e s u l t ) : d e f _ _ i n i t _ _ ( s e l f , r e a s o n = T r u e ) : R e s u l t . _ _ i n i t _ _ ( s e l f , N o n e , r e a s o n ) d e f f ( n ) : i f n > 1 0 : r e t u r n R e s u l t ( n * 1 0 ) e l s e : r e t u r n F a i l ( " % d i s t o o s m a l l " % n ) d e f t e s t ( n ) : r = f ( n ) i f r . f a i l : p r i n t r . f a i l e l s e : p r i n t r . r e s u l t d e f t e s t 2 ( n ) : r = f ( n ) i f i s i n s t a n c e ( r , F a i l ) : # C o u l d a l s o d o t h i s p r i n t r . f a i l e l s e : p r i n t r . r e s u l t t e s t ( 9 ) t e s t ( 1 1 ) t e s t 2 ( 9 ) t e s t 2 ( 1 1 )
  14. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 15/19 Slapping Bad Programmers c

    l a s s R e s u l t ( o b j e c t ) : d e f _ _ i n i t _ _ ( s e l f , r e s u l t , f a i l = F a l s e ) : s e l f . _ _ r e s u l t = r e s u l t s e l f . f a i l = f a i l @ p r o p e r t y d e f r e s u l t ( s e l f ) : # G e t t e r i f s e l f . _ _ r e s u l t a n d s e l f . f a i l = = F a l s e : r e t u r n s e l f . _ _ r e s u l t e l s e : r a i s e E x c e p t i o n ( " A c c e s s e d R e s u l t . r e s u l t d u r i n g f a i l u r e " , s e l f . f a i l ) c l a s s F a i l ( R e s u l t ) : d e f _ _ i n i t _ _ ( s e l f , r e a s o n = T r u e ) : R e s u l t . _ _ i n i t _ _ ( s e l f , N o n e , r e a s o n ) d e f f ( n ) : i f n > 1 0 : r e t u r n R e s u l t ( n * 1 0 ) e l s e : r e t u r n F a i l ( " % d i s t o o s m a l l " % n ) d e f t e s t ( n ) : r = f ( n ) i f r . f a i l : p r i n t r . f a i l e l s e : p r i n t r . r e s u l t t e s t ( 9 ) t e s t ( 1 1 ) f ( 9 ) . r e s u l t
  15. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 16/19 Package It Up #

    r e s u l t . p y c l a s s R e s u l t E r r o r ( E x c e p t i o n ) : d e f _ _ i n i t _ _ ( s e l f , r e a s o n ) : E x c e p t i o n . _ _ i n i t _ _ ( s e l f , " A c c e s s e d R e s u l t . r e s u l t d u r i n g f a i l u r e " , r e a s o n ) c l a s s R e s u l t ( o b j e c t ) : d e f _ _ i n i t _ _ ( s e l f , r e s u l t , f a i l = F a l s e ) : s e l f . _ _ r e s u l t = r e s u l t s e l f . f a i l = f a i l @ p r o p e r t y # G e t t e r d e f r e s u l t ( s e l f ) : i f s e l f . _ _ r e s u l t a n d s e l f . f a i l = = F a l s e : r e t u r n s e l f . _ _ r e s u l t e l s e : r a i s e R e s u l t E r r o r ( s e l f . f a i l ) c l a s s F a i l ( R e s u l t ) : d e f _ _ i n i t _ _ ( s e l f , r e a s o n = T r u e ) : R e s u l t . _ _ i n i t _ _ ( s e l f , N o n e , r e a s o n )
  16. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 17/19 Final Version f r

    o m r e s u l t i m p o r t * d e f f ( n ) : i f n > 1 0 : r e t u r n R e s u l t ( n * 1 0 ) e l s e : r e t u r n F a i l ( " % d i s t o o s m a l l " % n ) d e f t e s t ( n ) : r = f ( n ) i f r . f a i l : p r i n t r . f a i l e l s e : p r i n t r . r e s u l t t e s t ( 9 ) t e s t ( 1 1 ) f ( 9 ) . r e s u l t Can we get rid of the if­else using functional? m a p ( p r i n t , f ( n ) ) Monads for Python: http://www.infoq.com/presentations/Monads­Code
  17. 3/15/13 Rethinking Errors (1) file:///Users/bruceeckel/Dropbox/_RethinkingErrors/RethinkingErrors.html#(1) 18/19 Even C++ Is Moving

    In This Direction Go to channel9.msdn.com and look for Andrei Alexandrescu and "error"