Notes from Functional and Reactive Domain Modeling

I’m a big fan of the book, Functional and Reactive Domain Modeling, and these are some of my notes (“CliffsNotes”) from the book, most of them coming from the first chapter.

Chapter 1. Functional domain modeling

  • domain model
    • the representation of how the business works
    • blueprint of the relationships between the entities
    • objects that belong to the domain
    • behaviors those objects have
    • the language/vocabulary of the business
    • the context within which the model operates
  • essential complexities - complexities inherent to the business
  • incidental complexities - complexities introduced by the solution itself

Domain-driven design

  • bounded context - smaller model within the whole; a complete area of functionality within the larger system
  • the complete domain model is made up from a collection of bounded contexts
  • bounded contexts communicate via services/interfaces/APIs (me: think of them as web services)
  • ubiquitous language = domain vocabulary

Entities and value objects:

  • entities have an id (like a database id), and they are mutable; usually has a definite lifecycle
  • value objects (like an address) don’t have an id; they are identified by the values that are contained, and are therefore immutable
  • entity has an id that can’t change, and value object has a value that can’t change

Services:

  • services = behaviors = functions
  • usually models a use case of the business

Object lifecycles:

  • creation
  • participation in behaviors
  • persistence to a data store
  • factories (p.9)
    • centralize code to create entities
  • aggregates - a transaction boundary in the model
  • aggregate root - guardian of the graph and single point of interaction of the aggregate with its clients
  • Effective Aggregate Design by Vaughn Vernon

Scala:

  • Use case classes to model aggregates (ADTs)
  • Traits let you define modules which can be composed using mixin composition

Repositories:

  • the interface (trait) has no knowledge of the underlying data store

Thinking functionally

  • functions are the main abstraction to model domain behaviors (standalone functions in modules (traits), like Haskell)
  • mutable state is an anti-pattern when it comes to reasoning about your code
  • pure functions ...
  • general principles:
    • model immutable state as ADTs with case classes
    • model behaviors as functions in modules
    • behaviors in modules operate on their corresponding ADTs
  • more:
    • ADTs have no behaviors
    • services are defined in modules, which are implemented as Scala traits
    • when you need a concrete instance of a trait, create it with the object keyword

1.3.2 Pure functions compose (p.22)

  • good examples
  • composition = Unix pipeline (me)
  • HOFs like map are known as combinators
  • andThen and compose examples
  • takeaway: “appreciate how function composition through combinators can lead to enrichment of domain behaviors”

1.4 Managing side effects

  • stuff like I/O
  • decouple side effects as far as possible from pure domain logic

1.5 Virtues of pure model elements

  • equational reasoning
  • substitution model of evaluation
  • substitution model only works if functions are pure
  • referentially transparent expressions
  • three pillars of functional programming
    • referentially transparency
    • substitution model
    • equational reasoning

Other good quotes/notes

“Abstractions compose when types align; otherwise you’re left with islands of artifacts you can’t reuse and compose.”

About monads and effects in functional programming:

  • Future models latency as an effect
  • Try abstracts the effect of failures (manages exceptions as effects)
  • Option models the effect of optionality

Add new comment

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.