Chapter 5. Design patterns against complexity
This chapter covers
- The issues with imperative error-handling schemes
- Using containers to prevent access to invalid data
- Implementing functors as a mechanism for data transformation
- Understanding monads as data types that facilitate composition
- Consolidating error-handling strategies with monadic types
- Interleaving and composing monadic types
Null-references ... was a billion-dollar mistake.
Tony Hoare, InfoQ
Some people mistakenly view functional programming as a paradigm devoted only to academic problems, mostly numerical in nature, that are, for the most part, oblivious to the probabilities of failure real-life systems deal with. In recent years, however, people are finding that functional programming can treat error handling more elegantly than any other development style.
Many issues can arise in software where data inadvertently becomes null or undefined, exceptions are thrown, or network connectivity is lost, to name a few. Our code needs to account for the potential of any of these issues occurring, which unavoidably creates complexity. As a result, we spend countless hours making sure our code throws and catches the proper exceptions and checks for null values everywhere we can think of, and what do we get? Even more complex code—code that doesn’t scale and becomes harder to reason about as the size and complexity of applications increase.