Rethinking Errors by Bruce Eckel

Rethinking Errors by Bruce Eckel

Rethinking Errors by Bruce Eckel

Afcfefa1f067d10bd021de0cc2e5e806?s=128

PyCon 2013

March 15, 2013
Tweet

Transcript

  1. 2.

    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.

    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. 4.

    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. 5.

    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. 6.

    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. 7.

    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. 8.

    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. 9.

    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. 10.

    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. 11.

    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. 12.

    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. 13.

    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. 14.

    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. 15.

    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. 16.

    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. 17.

    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. 18.

    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"