💳 Secure Payment

Full-Service Web & Software Agency · Klamath Falls and Redding

Apply FRP concepts to software modules

Work with Sean

Here functional reactive programming (FRP) goes to work on one module at a time, in twelve steps: name its events, derive what each screen shows, keep its effects at the edge, and test its core without a browser.

Model the module

  1. Find the events: List what happens in the module, such as an item added, an order placed or a slot booked, and what each screen shows because of it. The steps below turn each event into an action and what each screen shows into state and selectors.
  2. Choose the state layer: In custom apps, the Sean Dinwiddie’s Webmastery team keeps a module’s state in Redux Toolkit: slices define each part of the state and the pure reducers that change it, RTK Query endpoints fetch and cache server data, and the React views stay minimal. The lecture Redux Toolkit and Functional Programming covers the foundation.
  3. Model events as actions: Name each action for what happened, such as orderPlaced rather than setOrders; the reducer takes the current state and the action and returns the next, so no earlier state is overwritten.
  4. Derive with selectors: Compute what a view shows from the state with selectors, composed with createSelector, so each derived value has one definition and recomputes only when its inputs change.
  5. Put effects at the boundary: RTK Query fetches and caches server data, a thunk runs a workflow started from one place, and listener middleware debounces, cancels and reacts to later actions; reducers and selectors stay pure.

Make it hold up

  1. Error handling: Give each expected failure a name and a shape the module can read: the API answers a declined card with its reason, the slice leaves the cart alone because it empties only on success, and a pure function turns the request’s state into the message the view shows, as One feature, scope to launch follows end to end.
  2. Modularize code: Organize the module by feature: its slice, selectors, endpoints and view in one folder, with the slice’s actions and selectors as its public interface.
  3. Testing: Module 2’s scenarios become the slice’s tests: each Given sets the starting state, each When dispatches one action, and each Then checks what a selector returns. Pure reducers and selectors need no browser to test.
  4. Real-time updates: A change the server pushes, such as an order marked ready, is decoded at the boundary like any response, then enters the state as an action or an update to RTK Query’s cached data, so every view that reads it updates with no code of its own.
  5. Collaboration and integration: Other modules reach this one only through its public interface, its actions and selectors, so the rest of the app never depends on the shape of its state.
  6. Documentation: The module’s scenarios are its first documentation: they say what it does in the owner’s words, and they fail when it stops. A short note beside them covers what they can’t, such as why a value is derived rather than stored, for the next webmaster who opens the folder.
  7. Continuous improvement: A module changes the way it was built: a new behavior starts as a scenario, and a slow screen is measured before its code changes. The team keeps researching better ways to do each step, and adopts one once it has proven itself.

The same procedure, as a ladder:

Where one value lives A ladder of four questions, each with a yes arrow to where the value lives and a no arrow down to the next. Derived from state? A selector. Survives a refresh, or shared as a link? The router. A server document reused across the app? RTK Query. Shared by unrelated components, with transitions worth recording? A slice. Anything else stays in the component. derived from state?selectoryesnosurvives a refresh,or shared as a link?routeryesnoa server document?RTK Queryyesnoshared, with transitions?sliceyesnothe component
Ask in order and stop at the first yes. The slice (outlined in violet) is only the fourth answer, and a value that reaches the bottom stays in the component.

To try it, take three values from a screen you’ve built, walk each down the ladder and note where it stops; a value kept in a slice that stops higher up is the first to move.

That completes Module 3: FRP applied to a module, with events named for what happened, a reducer that folds them into state, selectors that derive what each view shows, and effects kept at the edge, where each can be tested on its own.

Module 4 comes next: The API: Haskell Servant and Nile carries the chain to the server, where the API is a Haskell type and the client’s endpoints are generated from it.

Copyright Sean Paul Payne Dinwiddie
All Rights Reserved