Book notes: Grokking Simplicity
Tags: books, clojure, architecture, functional
Published: 2022-02-24 23:09:17

---
title: Book notes: Grokking Simplicity
published: true
canonical_url: https://danlebrero.com/2021/09/08/the-subtle-art-of-not-giving-a-fuck-summary/
tags: books, Clojure, architecture, functional
series: Book notes
description: Book notes on "Grokking Simplicity" by Eric Normand
cover_image: https://danlebrero.com/images/blog/books/grokking-simplicity/grokking-simplicity.jpg
---

These are my notes on [Grokking Simplicity](https://amzn.to/3DJJ0pQ) by [Eric Normand]((https://twitter.com/ericnormand)).

Excellent introduction to functional programming, or at least how I understand it.

# Key Insights

* World is divided in actions, calculations, and data.
* Actions: anything that depend on when they are called or how many times they are called.
* Data is useful mostly because of what it can't do: it cannot be run.
    * Reads to mutable data are actions.
    * Reads to immutable data are calculations.
* Groups actions by layers of meaning.
* Principle: design is about pulling things apart.
* Code within a function should have the same level of detail.
    * Being able to ignore the same details is one clue that the code is at similar level of abstraction.
    * Don't move unclear code to another layer, make it straightforward.
* Design discussions run the risk of getting too abstract. 
* We often write a lot of code just in case something might change in the future.
* There is constant tension between design and the need for new features. Let comfort guide you when to stop.
* A function cannot call other functions in its same layer.
* Simplify collection processing:
    * Transform code into data so that you can name and inspect.
    * Prefer small simple step to big complex ones.
* Use abstraction barrier on deeply nested data to reduce cognitive load.

![onion layers architecture](https://danlebrero.com/images/blog/books/grokking-simplicity/onion-layers.jpg)

# TOC

* [Chapter 1: Welcome to Grokking Simplicity](#ch-1)
* [Chapter 2: Functional Thinking in Action](#ch-2)
* [Part 1: Actions, calculations, and data.](#part-1)
    * [Chapter 3: Distinguishing actions, calculations, and data](#ch-3)
    * [Chapter 5: Improving the design of actions](#ch-5)
    * [Chapter 6: Staying immutable in a mutable language](#ch-6)
    * [Chapter 8: Stratified design: Part 1](#ch-8)
    * [Chapter 9: Stratified design: Part 2](#ch-9)
* [Part 2: First-class abstractions](#part-2)
    * [Chapter 10: First-class functions: Part 1](#ch-10)
    * [Chapter 13: Chaining functional tools](#ch-13)
    * [Functional tools for nested data](#ch-14)
    * [Isolating timelines](#ch-15)
    * [Sharing resources between parallel execution](#ch-16)
    * [Reactive and onion architecture](#ch-18)

## <a name="ch-1"></a>Chapter 1: Welcome to Grokking Simplicity

* Book explains the two main functional programming (FP) skills:
    1. Distinguish actions, calculations, and data.
        * Actions: anything that depend on when they are called or how many times they are called.
    1. Using first-class abstractions.
    
## <a name="ch-2"></a>Chapter 2: Functional Thinking in Action

* Stratified design:
    1. Business layer: Least stable.
    1. Domain layer.
    1. Tech stack layer: Most stable.
  
# <a name="part-1"></a>Part 1: Actions, calculations, and data.

## <a name="ch-3"></a>Chapter 3: Distinguishing actions, calculations, and data

* Data:
    * Facts about *events*.
    * Is useful mostly because of what it can't do: it cannot be run.
    * Must be interpreted to be useful.

## <a name="ch-5"></a>Chapter 5: Improving the design of actions

* Principle: minimize implicit inputs and outputs.
    * Code is more reusable. 
* Choose better level of abstraction: closer function/parameters names to business language (ubiquitous language from DDD).
* Groups actions by layers of meaning.
* Principle: design is about pulling things apart.

## <a name="ch-6"></a>Chapter 6: Staying immutable in a mutable language

* Reads to mutable data are actions.
* Reads to immutable data are calculations.
    
## <a name="ch-8"></a>Chapter 8: Stratified design: Part 1

* Software design: using one's aesthetic sense to guide programming choices to improve the ease of coding, testing, and maintaining software.
* Stratified design:
    * Pattern 1: straightforward implementation.
        * Code within a function should have the same level of detail. This is the [Composed Method](http://c2.com/ppr/wiki/WikiPagesAboutRefactoring/ComposedMethod.html) in [Implementation Patterns](https://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091/).
        * Being able to ignore the same details is one clue that the code is at similar level of abstraction.
        * If a layer is using for its implementation several other layers, then it is not straightforward implementation.
        * Don't move unclear code to another layer, make it straightforward.
* Design discussions run the risk of getting too abstract.

## <a name="ch-9"></a>Chapter 9: Stratified design: Part 2

* Stratified design:
    * Pattern 2: Abstraction barrier.
        * A layer that let us ignore the same thing when working above that layer.
        * Most important benefit: they let you think more easily about the problem you are trying to solve.
* Warn: we often write a lot of code just in case something might change in the future.
    * Pattern 3: Minimal interface.
        * It ask us to consider where code for new features belong.
        * A function cannot call other functions in its same layer (really??).
    * Pattern 4: Comfortable layers.
        * No codebase is ideal.
        * There is constant tension between design and the need for new features. Let comfort guide you when to stop.
* "Ilities":
    * Maintainability: code at the top layers is easier to test.
    * Testability: code at the bottom layers is more important to test.
        * Because it changes less frequently and all other code depends on it.
            * Do I strongly disagree???
    * Reusability: code at the bottom layers is more reusable.
    
# <a name="part-2"></a>Part 2: First-class abstractions

## <a name="ch-10"></a>Chapter 10: First-class functions: Part 1

* Code smell: implicit argument in function name:
    * Similar function implementation.
    * Name of function indicates the difference in implementation.
    * Refactoring: express implicit argument:
        * Argument becomes first-class and part of the API.
    * Treat data as data (data orientation):
        * Bespoke interfaces allow one interpretation of data while prohibiting others == less reusable.
        * Entities at the bottom layers should be reusable/generic.
    * Refactoring: replace body with callback.
    
## <a name="ch-13"></a>Chapter 13: Chaining functional tools

* Simplify collection processing:
    1. Make data: 
        * Transform code into data so that you can name and inspect.
    1. Operate on the whole array:
        * Try to process uniformly.
    1. Many small steps:
        * Prefer small simple step to big complex ones.
    1. Replace conditionals with `filter()`.
            
## <a name="ch-14"></a>Functional tools for nested data

* Use abstraction barrier on deeply nested data to reduce cognitive load.

## <a name="ch-15"></a>Isolating timelines

* Timeline diagram:
    * Sequence of actions.
    * Show sequential or parallel execution.
    * From [Manning site](https://livebook.manning.com/book/grokking-simplicity/chapter-2/58):    

![timeline diagram example](https://drek4537l1klr.cloudfront.net/normand/Figures/f0025-02.jpg)

## <a name="ch-16"></a>Sharing resources between parallel execution

* Queue to guarantee order.

## <a name="ch-18"></a>Reactive and onion architecture

* Reactive architecture:
    * Instead of "Do X then do Y", it says "Do Y when X happens".
    * Atom watchers: when atom value changes, do Y.
    * [ReactiveManifesto.org](https://ReactiveManifesto.org)
* Onion architecture:
    * Layers can only call/know about inner layers.
![onion architecture](https://danlebrero.com/images/blog/books/grokking-simplicity/onion-architecture.jpg)
![onion layers architecture](https://danlebrero.com/images/blog/books/grokking-simplicity/onion-layers.jpg)
    
* Do domain rules need actions?
    * No. You can always implement it as calculations.
    * In truth, it depends on:
        1. The terms used to place the rule in a layer.
            * Domain language in DDD sense.
        1. Readability and awkwardness:
            * Some programming languages makes a non-functional implementation many times clearer.
            * Take technical debt.
            * System performance.