Managing errors the right way in Scala
-
Upload
normation -
Category
Technology
-
view
1.065 -
download
1
description
Transcript of Managing errors the right way in Scala
2014-10-{23,24}
Managing errors the right way in Scala
François ARMANDCTO - Normation
Say hello !
[email protected] / @fanf42
François ARMAND
Co-founder & CTO Lead-dev
Discovered Scala in 2006
Full time Scala since 2009 And yes, I'm trying to start a side
business in cloning
OSS convinced
What's about ?
The primary duty of an exception handler is to get the error out of the lap of the programmer and into the surprised face of the user. Provided you keep this cardinal rule in mind, you can't go far wrong.
— Verity Stob
Managing errors so that both futur developpers, ops and users are happy is what differentiate hacking toys projects to building softwares
— Myself
What's about ?
Sharing the (hard) learned lessons about managing errors in Scala in
our 5 years trip with Rudder
What's about ?
IT infratructure open source automation
+ compliance management
http://www.rudder-project.org
Compliance AgentsServer
Scala web applicationStarted in 2009By ex-java dev
Errors ? What's an error ?
■ Who MUST care ? ■ Who MUST handle the problem ?
Something didn't worked as it should
Errors classical classification
▣ Pop culture(1) say :
▣ Technical Errors
■ When your containing universe fails□ Ex : « oups, the underlying OS just ran out of memory »
□ OutOfMemroy Errors, Threads killed, VM crashes...
■ Logical / modeling error□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
■ The one the user want to know about
■ Ex : « oups, I can't withdraw $1M from your empty account, because, well, you know »
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
Errors classical classification
▣ Pop culture(1) say : It's complicated :
▣ Technical Errors
■ When your containing universe fails□ Ex : « oups, the underlying OS just ran out of memory »
□ OutOfMemroy Errors, Threads killed, VM crashes...
■ Logical / modeling error□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
■ The one the user want to know about
■ Ex : « oups, I can't withdraw $1M from your empty account, because, well, you know »
That's th
e end of
the univers
e, don't
care
(ops w
ill awake)
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
Errors classical classification
▣ Pop culture(1) say : It's complicated :
▣ Technical Errors
■ When your containing universe fails□ Ex : « oups, the underlying OS just ran out of memory »
□ OutOfMemroy Errors, Threads killed, VM crashes...
■ Logical / modeling error□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
■ The one the user want to know about
■ Ex : « oups, I can't withdraw $1M from your empty account, because, well, you know »
That should
be
modeled in
data ty
pe
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
That's th
e end of
the univers
e, don't
care
(ops w
ill awake)
Errors classical classification
▣ Pop culture(1) say : It's complicated :
▣ Technical Errors
■ When your containing universe fails□ Ex : « oups, the underlying OS just ran out of memory »
□ OutOfMemroy Errors, Threads killed, VM crashes...
■ Logical / modeling error□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
■ The one the user want to know about
■ Ex : « oups, I can't withdraw $1M from your empty account, because, well, you know »
Always t
he business
of som
ebody :
dev, ops,
final u
ser
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
That should
be
modeled in
data ty
pe
That's th
e end of
the univers
e, don't
care
(ops w
ill awake)
Errors classical classification
▣ Pop culture(1) say : It's complicated :
▣ Technical Errors
■ When your containing universe fails□ Ex : « oups, the underlying OS just ran out of memory »
□ OutOfMemroy Errors, Threads killed, VM crashes...
■ Logical / modeling error□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
■ The one the user want to know about
■ Ex : « oups, I can't withdraw $1M from your empty account, because, well, you know »
Always t
he business
of som
ebody :
dev, ops,
final u
ser
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
That should
be
modeled in
data ty
pe
That's th
e end of
the univers
e, don't
care
(ops w
ill awake)
So, what was our trip in error management land ?
Origins : the dark age of Java Exceptions
▣ Using Java Exception
■ Worst : Business and Technical Exception, enterprisy style
Origins : the dark age of Java Exceptions
▣ Death by one thousand different GoTos
▣ Can't reason about part of the code
■ Hard to understand
■ Hard to compose
■ Hard to refactor
■ Hard to reuse
▣ Exception are the incarnation of side effect
Error management must be referentially transparent
Problems ?
Origins : the dark age of Java Exceptions
▣ Dilution of responsability
■ Nobody ever manage exception in a systematic way
■ Idem in language with error code (C, Python, Go...)
▣ Human being are not very disciplined
■ That why we automate things
Problems ?
Origins : the dark age of Java Exceptions
▣ Human being are not very disciplined
▣ But hey ! Compilers DO ARE very disciplined
▣ Crazy idea:
■ Force the user to take care of failure to reach success values
■ Use a data type denoting Error Or Success
▣ Nice side effects:
■ Clear identification function that could fail in return type
■ Errors as value enable referential transparency
Model faillible code with Algebraic Data Type
Problems ?
Origins : the dark age of Java Exceptions
Exception: far better tools exists (in Scala)
Option to the rescue (really?)
▣ Functionnal programming 101 : use option
■ Option[+A]
□ None
□ Some[+A](x: A)
Need a rich failure type
Option – just to denote missing things
Option : good data type. Not for error.
Its semantic is « MISSING ITEM »
Either to the rescue (ok, still no)
▣ Functionnal programming 101, page 2 : use disjunction
Either[L,R] : Left[L] : failure and Right[R] : success
But....
Either to the rescue (ok, still no)
▣ Functionnal programming 101, page 2 : use disjunction
Either[L,R] : Left[L] : failure and Right[R] : success
???Ticket #SI-5793, close won't fix
No boilerplate !
Either – for the boilerplate lovers
Either (Scala stdlib): not tailored for errors
Nice try
▣ Try[A] – essentially an Either[Throwable, A]
■ Nice on paper (not used in real life)
□ Even with theoric hole (see « Try and monad laws »)
■ But really ? Everything is an exception ?
Need a rich failure type
Try – when all your errors are exception
Try: NOT ALL errors are exceptions
Oh, and what could go wrong with ignoring theory ?
A Lift gift in a Box
▣ Lift, that new web framework (2009 style)
▣ Box[T] : data structure with 3 cases :
■ Full[+A](value: A) extends Box[A]□ a success that hold your item of type T
■ EmptyBox extends Box[Nothing] (abstract)
□ Empty : no results (None for Option) extends EmptyBox
□ Failure(msg: String, exception: Box[Throwable]
, chain: Box[Failure]) extends EmptyBox
A Lift gift in a Box
A Lift gift in a Box – with error tooling !
A Lift gift in a Box – with error tooling !
Tooling and error lexical field helps
A Lift gift in a Box – with error tooling !
But....
So bad it was offered by Pandora
▣ getUser(User("fanf42")) === Empty.
■ What do you thing it means ?
■ Depending of the dev, the refactorer, the tests, it's an error without message.
■ Or a missing item.
▣ In Rudder, the most surprising error where due to Empty
■ Surprise is a bad thing: Empty is forbidden.
■ Object DB { def getUser(id : UserId) : Box[Option[User]] }
Must be Unambiguious
(Pandora) Box might have been good
Box: good tooling, too much ambiguity
Finally, let's go shopping ?
So, no error management framework ?
Desirable properties of error management
Must be Unambiguious
Error management must be referentially transparent
Need a rich failure type
No boilerplate !
Tooling and error lexical field helps
Model faillible code with Algebraic Data Type
It's a kind of magic
▣ You know what ? People worked on theory about that. ■ Theory-backed model free you mind : you know it WILL work. It's proved
■ http://typelevel.org/blog/2014/02/21/error-handling.html
■ http://stackoverflow.com/questions/12307965/method-parameters-validation-in-scala-with-for-comprehension-and-monads/12309023#12309023
Independant Errors Dependant Errors
▣ Form validation
▣ Accumulate them
▣ « best-effort »
▣ List of I/O actions
▣ Chain them
▣ Stop early
Theory says
Scalaz.Validation(applicative functor)
Scalaz.\/(monad)
Independant Errors
▣ Form validation
▣ Accumulate them
▣ « best-effort »
Theory says
Scalaz.Validation(applicative functor)
Scalaz.Validation – accumulating errrors
▣ It's an applicative functor : no for-comprehension
Dependant Errors
▣ List of I/O actions
▣ Chain them
▣ Stop early
Theory says
Scalaz.\/(monad)
Scalaz disjunction – a sane Either
So, no shopping after all ?
▣ Validation is great for applicative style failure.
■ It's more generic / less powerful
■ In fact only used in very specific cases
▣ \/ is great for general error management
■ Toward monadic application
▣ But...
Tooling on top of \/ (and Validation)
▣ Nothing in \/ is in the semantic domain of errors.
▣ And it's desirable to have :
■ One default generic Failure data structure
■ With tooling (message, root cause, etc)
■ À la Box.
▣ Some leads to follow :
■ Design your own Failure with sugar to add messages / Throwable
■ User library extension with implicit to add more sugar
What follows are JUST ideas and example
Tooling on top of \/ (and Validation)
A dedicated Fail data type
Tooling on top of \/ (and Validation)
A dedicated Error data type
Tooling on top of \/ (and Validation)
Tooling on top of \/ (and Validation)
2014-10-{23,24}
Questions ?
[email protected] / @fanf42
François ARMAND
Code available on GitHub : https://github.com/fanf/scalaio_2014