A presentation of how to managing errors in Scala, getting all the current way of doing it one by one: exception, Option, Either, Try, Box.
All these solutions have major drowback, so we end-up using a solution with a clean theorical background: scalaz.Validation and scalaz.\/.
But as that last solution is a little raw, I explain how to add syntactic sugar to get nice error logic on top of \/: building a nice generic Fail type with message and root cause, sugar to stack messages, display them, get root cause, etc.
Code is available on Github: https://github.com/fanf/scalaio_2014
2. Say hello !
François ARMAND
far@normation.com / @fanf42
Co-founder & CTO Lead-dev
Discovered Scala
in 2006
OSS convinced
Full time Scala
since 2009 And yes, I'm trying to start a side
business in cloning
3. 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
4. What's about ?
Sharing the (hard) learned lessons
about managing errors in Scala in
our 5 years trip with Rudder
5. What's about ?
http://www.rudder-project.org
IT infratructure
open source automation
+
compliance management
Server Compliance Agents
Scala web application
Started in 2009
By ex-java dev
6. Errors ? What's an error ?
Something didn't worked as it should
■ Who MUST care ?
■ Who MUST handle the problem ?
7. 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
8. Errors classical classification
That's the end of
the universe, don't
care (ops will awake)
▣ 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 »
[1] http://programmer.97things.oreilly.com/wiki/index.php/Distinguish_Business_Exceptions_from_Technical
9. Errors classical classification
That's the end of
the universe, don't
care (ops will awake)
▣ 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
That should be
modeled in data type
□ « 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
10. Errors classical classification
That's the end of
the universe, don't
care (ops will awake)
▣ 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
That should be
modeled in data type
□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed
Always the business
□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
of somebody :
dev, ops, final user
■ 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
11. Errors classical classification
That's the end of
the universe, don't
care (ops will awake)
▣ 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
That should be
modeled in data type
□ « no, you really can't access item #42 of that array of size 2 »
■ Systems in relation with yours failed
Always the business
□ Ex : « hello Database ? Helloooooo ? »
□ Mostly I/O errors : connection errors, bad permession on FS...
▣ Business Errors
of somebody :
dev, ops, final user
■ 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
12. So, what was our trip in error management land ?
13. Origins : the dark age of Java Exceptions
▣ Using Java Exception
■ Worst : Business and Technical Exception, enterprisy style
14. Origins : the dark age of Java Exceptions
Problems ?
▣ 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
15. Origins : the dark age of Java Exceptions
Problems ?
▣ 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
16. Origins : the dark age of Java Exceptions
Problems ?
▣ 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
17. Origins : the dark age of Java Exceptions
Exception: far better tools exists (in Scala)
18. Option to the rescue (really?)
▣ Functionnal programming 101 : use option
■ Option[+A]
□ None
□ Some[+A](x: A)
Need a rich failure type
19. Option – just to denote missing things
Option : good data type. Not for error.
Its semantic is « MISSING ITEM »
20. 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....
21. 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 !
22. Either – for the boilerplate lovers
Either (Scala stdlib): not tailored for errors
23. 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
24. Try – when all your errors are exception
Try: NOT ALL errors are exceptions
Oh, and what could go wrong with ignoring theory ?
25. 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
28. A Lift gift in a Box – with error tooling !
Tooling and error lexical field helps
29. A Lift gift in a Box – with error tooling !
But....
30. 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
33. Desirable properties of error management
Error management must be referentially transparent
Model faillible code with Algebraic Data Type
Must be Unambiguious
Need a rich failure type
No boilerplate !
Tooling and error lexical field helps
34. 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
35. Theory says
Independant Errors Dependant Errors
▣ Form validation
▣ Accumulate them
▣ « best-effort »
▣ List of I/O actions
▣ Chain them
▣ Stop early
Scalaz.Validation
(applicative functor)
Scalaz./
(monad)
36. Independant Errors
▣ Form validation
▣ Accumulate them
▣ « best-effort »
Theory says
Scalaz.Validation
(applicative functor)
40. 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...
41. 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
42. Tooling on top of / (and Validation)
A dedicated Fail data type
43. Tooling on top of / (and Validation)
A dedicated Error data type