DEV Community

Cover image for Book notes: Grokking Simplicity
Dan Lebrero
Dan Lebrero

Posted on • Originally published at danlebrero.com on

1

Book notes: Grokking Simplicity

These are my notes on Grokking Simplicity by Eric Normand.

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

TOC

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.
    2. Using first-class abstractions.

Chapter 2: Functional Thinking in Action

  • Stratified design:
    1. Business layer: Least stable.
    2. Domain layer.
    3. Tech stack layer: Most stable.

Part 1: Actions, calculations, and data.

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.

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.

Chapter 6: Staying immutable in a mutable language

  • Reads to mutable data are actions.
  • Reads to immutable data are calculations.

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 in Implementation Patterns.
      • 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.

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.

Part 2: First-class abstractions

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.

Chapter 13: Chaining functional tools

  • Simplify collection processing:
    1. Make data:
      • Transform code into data so that you can name and inspect.
    2. Operate on the whole array:
      • Try to process uniformly.
    3. Many small steps:
      • Prefer small simple step to big complex ones.
    4. Replace conditionals with filter().

Functional tools for nested data

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

Isolating timelines

  • Timeline diagram:
    • Sequence of actions.
    • Show sequential or parallel execution.
    • From Manning site:

timeline diagram example

Sharing resources between parallel execution

  • Queue to guarantee order.

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
  • Onion architecture:

    • Layers can only call/know about inner layers. onion architecture onion layers architecture
  • 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.
      2. Readability and awkwardness:
        • Some programming languages makes a non-functional implementation many times clearer.
        • Take technical debt.
        • System performance.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more