11 Representing state and change

 

This chapter covers

  • The pitfalls of state mutation
  • Representing change without mutation
  • Enforcing immutability
  • Separating data and logic

Greek philosopher Heraclitus said that we cannot step into the same river twice; the river constantly changes, so the river that was there a moment ago is no longer. Many programmers would disagree, objecting that it’s the same river but its state has changed. Functional programmers try to stay true to Heraclitus’s thinking and would create a new river with every observation.

Most programs are built to represent things and processes in the real world, and because the world constantly changes, programs must somehow represent that change. The question is how we represent change. Commercial applications written in the imperative style have state mutation at their core: objects represent entities in the business domain, and change in the world is modeled by mutating the state of these objects.

We’ll start by looking at the weaknesses we introduce in our programs when we use mutation. We’ll then see how we can avoid these problems at the source by representing change without using mutation and, more pragmatically, how to enforce immutability in C#. Finally, because much of our programs’ data is stored in data structures, we’ll introduce the concepts and techniques behind functional data structures, which are also immutable.

11.1 The pitfalls of state mutation

11.2 Understanding state, identity, and change

11.2.1 Some things never change

11.2.2 Representing change without mutation

11.3 Using records to capture the state of domain entities

11.3.1 Fine-grained control on record initialization

11.3.2 Immutable all the way down

11.4 Separating data and logic

Summary