liveBook · Manning

Statefulness

As explained in Data-Oriented Programming: Reduce software complexity

Stateful code is code whose behavior or effects involve persistent state beyond the values passed directly to a computation.

A stateful system changes persistent state instead of returning data directly. Its behavior depends on the state it receives and the state it commits afterward. section 6.4

Test a stateful operation by treating the changed state as its observable result:

  • Initialize the system with a known state. section 6.4
  • Execute the mutation with its input member. section 6.4
  • Retrieve the resulting state and compare it with the expected value. section 6.4
  • Test failure paths separately, such as rejecting an existing member. section 6.4

Adding a member

System.addMember receives a system state and a member, reads the previous state, delegates data manipulation to Library.addMember, and commits the next state. It returns no data; the test compares the committed state with the expected library state. section 6.4

Listing 6.21 The functions involved in the add member mutation
System.addMember = function(systemState, member) {
  var previous = systemState.get();
  var next = Library.addMember(previous, member);
  systemState.commit(previous, next);
};
 
Library.addMember = function(library, member) {
  var currentUserManagement = _.get(library, "userManagement");
  var nextUserManagement = UserManagement.addMember(
    currentUserManagement, member);
  var nextLibrary = _.set(library, "userManagement", nextUserManagement);
  return nextLibrary;
};
 
UserManagement.addMember = function(userManagement, member) {
  var email = _.get(member, "email");
  var infoPath = ["membersByEmail", email];
  if(_.has(userManagement, infoPath)) {
    throw "Member already exists.";
  }
  var nextUserManagement =  _.set(userManagement,
    infoPath,
    member);
  return nextUserManagement;
};

Trace the separation between the stateful shell and the data-manipulation functions that calculate the next state. section 6.4

How Data-Oriented Programming: Reduce software complexity covers it

How deep it goes
Explains state retrieval, mutation, commit, and comparison, while stopping short of deeper state-management internals.
Examples
Uses member addition, existing-member rejection, library state, system state, and expected-state comparisons.
What it assumes
Assumes familiarity with functions and maps while teaching how stateful operations expose results through committed state.
What you can do after
Diagnose/debug with it by asserting the state produced by a mutation and checking expected exceptions.
How it connects
Connects stateful systems with mutations, data manipulation, system state, and unit testing.

Also explained in

Compare how 14 books explain statefulness →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Data-Oriented Programming: Reduce software complexity. The section links point to the parts of the book it draws on.