Grokking Simplicity

Grokking Simplicity: Taming Complex Software with Functional Thinking by Eric Normand teaches functional patterns and abstractions that we as developers can use to write good code. Throw away the Haskell-on-a-chalkboard imagery; this isn’t like most functional programming (FP) books. The FP topics covered in this book are practical and will improve your every day code. No monads or applicatives here, instead you’ll learn concepts you can apply in any programming language and framework.

Rabbits, the wisest and most functional of all mammals.

Rabbits, the wisest and most functional of all mammals.

In the Beginning there was Data (and Actions, and Calculations)

The book begins by introducing the three basic building blocks of a program:

  • Data: Primitive values, collections, and maps.
  • Calculations: Pure, deterministic functions. eg. add, string_length.
  • Actions: Impure functions where the output depends on when they were called. eg. list_directory, fetch_from_db, current_time.

Software we write contains all three. Calculations are easy to reason with and unit test, we want lots of these. Actions are more difficult to test but are necessary as the software we write often connects to networks, files, and databases. Data is fed into and read from Calculations and Actions. If we’re not careful data can be accidentally changed by our Actions, so it’s important we use immutable data structures. The first third of the book gives a gentle introduction to these topics.

Throughout the book a case study of an e-commerce checkout system is used. It’s written in a simple dialect of Javascript and is readily understandable by anyone who understands at least one programming language. We don’t immediately dive into the toolbox of Promise, map, filter, reduce, and forEach. Throughout the book we see situations where these tools are useful and implement them ourselves.

The narrative and formatting make this an accessible and enjoyable book.

The narrative and formatting make this an accessible and enjoyable book.

The case study is light hearted and fits the book well. It provides a fictional and self aware narrative of the development team and stakeholders involved in the e-commerce system. This narrative and the accompanying cartoon illustrations breaks up the wall of text and provides an alternative way of understanding the books content. It’s no gimmick, but you can understand the technical content without paying attention to it.

High-order Functions

With the fundamentals under our belt the book turns to high order functions: functions which take other functions as arguments, and functions which return a function as a value. Again we look at use cases and patterns to look for which would benefit from high-order functions. We’ve separated calculations from actions, but there are opportunities to further improve these. Javascript programmers are familiar with high order functions through event callbacks. The book sets these aside and instead covers examples of implementing forEach, map, reduce, and filter, as well as a generic logging wrapper.

The section wraps up by looking at functional pipelines; a technique of organising our program so it’s mainly made up of chained functions. This pattern is popular in other languages with Java Streams, .NET LINQ, and F# pipelines.

Functional Architecture and Design Patterns

Writing low-level code in a functional style is one thing but at some point we need to assemble it into a larger program. We know architecture directly contributes to the maintainability of code but how do we do it in a functional style?

Building on top of the foundations of Data, Calculations, and Actions Norman introduces us to Stratified Design: a technique to build software in layers. Over sixty pages this idea is looked at from the angles of simplicity, abstractions, interfaces, and the resulting call graph of the program. These abstract concepts are well backed by code samples from the case study showing the before and after of the refactor. None of these are treated as solid rules and we, the reader, are asked whether applying a particular refactor has actually improved the code.

The Onion Architecture is also discussed. This architecture pattern (aka Functional Core, Imperative Shell) sits over top of Stratified Design. Code is organised into layers. The outer layer deals with the outside world (databases, networks, files) whereas the inner layers are more concerned with domain logic and pure calculations. Layers call inward, and never need to be aware of what is calling them.

Onions, the most architecturally sound of all alliums.

Onions, the most architecturally sound of all alliums.

I found the treatment of this section brilliant. Normand’s software development experience really shines through. Similar to the rest of the book emphasis is put on the way we think about software design and the anti-patterns to recognise, rather than a set of hard and fast rules that we’d need to stick to no matter what.

Functional Geekery

The topics I’ve talked about so far are practical for any software project. The book touches on a few other subjects which may not be applicable to every codebase but all the same are interesting. These include:

  • A recursive pattern for updating nested data structures
  • Timelines and Race Conditions
  • Reactive programming

When dealing with these in the real world we’d reach for a library but the book implements them from scratch. These otherwise somewhat complicated topics are made accessible. It builds on the functional patterns we’ve learned in the book so far and reinforces that knowledge.

Conclusion

Grokking Simplicity is a perfect introduction to practical functional programming. It’s a book I wish I’d read early on in my career and I’ve already recommended it to a few colleagues. As someone experienced with the topics discussed in the book I still learned a whole lot. Normand has a great way with words and his discussions as to why these concepts make code good have stuck with me. It’s also made me appreciate design decisions of languages like Clojure and F#. I learned these languages when I was young without having faced the real-world problems such as concurrency and operations on data structures these languages do so well to solve.

I recommend this book to anyone wanting to learn functional programming fundamentals and improve the code they write. This book is not about writing Javascript applications in a functional way. In the workplace we’d reach for libraries such as immutable.js, lodash, and RxJs. This book teaches you about the concepts underpinning those libraries. Perhaps by accident the book doubles as a guide to refactoring and modernising highly coupled front end code. The narrative and code examples that run through the book do this well.

Read more at: grokkingsimplicity.com.


Related Posts