Chapter 4: Extracting calculations from actions
The chapter introduces a planned refactoring of existing software to extract calculations from actions and improve reuse and testability.
After this chapter you will be able to
- Always-Visible Cart Total. Describe MegaMart’s key shopping-cart feature: it shows the total cost of the cart’s contents even while the customer is shopping.
- Free-shipping icon updates. Describe when a buy button should show a free-shipping icon and how the proposed imperative approach keeps the icons current.
- Tax update timing. Describe when the tax amount needs to be updated and where the section places that update in the existing workflow.
- Business rule testability. Explain why testing the business rules is cumbersome and what George suggests changing to make it easier.
- Reusable shopping cart calculations. Explain why accounting and shipping cannot reuse the current code and describe the proposed changes: avoid the global cart, do not write the answer directly to the DOM, and return it from the function.
- Classifying functions as actions. Explain how to label functions as actions, calculations, or data, and why every function in the current code is classified as an action.
- Function inputs and outputs. Explain what counts as a function’s inputs and outputs, and distinguish explicit inputs and outputs from implicit ones.
- Implicit effects and calculations. Explain why implicit inputs or outputs make a function an action, and how removing them can turn it into a calculation.
- DOM updates and business rules. Explain why a business rule should be separate from a DOM update, even though the application still needs to update the DOM.
- Globals and explicit function boundaries. Describe how reading or writing global variables creates implicit inputs or outputs, and how arguments and return values address them.
- Implicit cart inputs and outputs. Identify the extracted function's implicit input and outputs, and explain why its global-variable read and writes count as inputs and outputs.
- Explicit cart calculation interface. Trace how the two writes to shopping_cart_total become one return value and the read of shopping_cart becomes a cart argument, while the original function handles the global assignment.
- Calculation extraction process. Describe the repeatable process for extracting a calculation: move a suitable chunk of code into a function, identify its implicit inputs and outputs, and convert those inputs to arguments and outputs to return values.
- Shopping cart input and output. Trace how add_item() changes from an action into a calculation: pass the cart as an argument instead of reading the global, then return a modified copy instead of changing the original array.
- Whole-function action classification. Explain that when labeling code A, C, or D, a function containing even one action is classified as an action.
What it builds on
- Actions spread through code (chapter 3) · Actions can spread through code.
- Actions, calculations, and data (chapter 3) · The distinction between actions and calculations.
Section by section
Introduction
The chapter introduces a planned refactoring of existing software to extract calculations from actions and improve reuse and testability.
4.1 Welcome to MegaMart.com!
Introduces MegaMart’s always-visible shopping-cart total and explains what the DOM is.
- Always-Visible Cart Total: Describe MegaMart’s key shopping-cart feature: it shows the total cost of the cart’s contents even while the customer is shopping.
Why it matters: This feature gives the shopping-cart code a concrete purpose. - DOM and Page Updates: Explain what the document object model (DOM) is and why updating it changes a browser page.
Why it matters: The DOM explains how the code changes what a shopper sees on the page.
Key terms: shopping cart, total cost, document object model (DOM), HTML page
4.2 Calculating free shipping
The section introduces MegaMart’s free-shipping icon requirement and a straightforward imperative way to keep the icons updated.
- Free-shipping icon updates: Describe when a buy button should show a free-shipping icon and how the proposed imperative approach keeps the icons current.
Why it matters: The icon needs to reflect what would happen if the shopper added a particular item, even as the cart total changes.
Key terms: free shipping, buy button, calc_cart_total()
4.3 Calculating tax
The section adds tax updating to the cart-total workflow while noting that simply adding it to the existing implementation is not the functional programming approach.
- Tax update timing: Describe when the tax amount needs to be updated and where the section places that update in the existing workflow.
Why it matters: The tax amount needs to reflect the newly calculated cart total.
Key terms: tax, cart total, calc_cart_total()
4.4 We need to make it more testable
The section explains why MegaMart’s business rules are difficult to test and identifies changes that would make testing easier.
- Business rule testability: Explain why testing the business rules is cumbersome and what George suggests changing to make it easier.
Why it matters: Separating the rules from the page updates would let tests check them more directly.
Key terms: business rules, DOM updates, global variables
4.5 We need to make it more reusable
The section explains why the shopping-cart code cannot be reused by accounting and shipping, and what must change to make it reusable.
- Reusable shopping cart calculations: Explain why accounting and shipping cannot reuse the current code and describe the proposed changes: avoid the global cart, do not write the answer directly to the DOM, and return it from the function.
Why it matters: A function is easier to reuse when it does not assume where its input comes from or where its answer must go.
Key terms: global variables, DOM, return the answer, reusable
4.6 Distinguishing actions, calculations, and data
The section classifies the current functions as actions and explains why an action inside a function makes the whole function an action.
- Classifying functions as actions: Explain how to label functions as actions, calculations, or data, and why every function in the current code is classified as an action.
Why it matters: Classifying the current code shows where the work of extracting calculations begins.
Key terms: actions, calculations, data, Actions spread
4.7 Functions have inputs and outputs
The section defines how information and effects enter and leave functions, then shows how that distinction identifies actions and guides their conversion into calculations.
- Function inputs and outputs: Explain what counts as a function’s inputs and outputs, and distinguish explicit inputs and outputs from implicit ones.
Why it matters: Tracking everything that enters and leaves a function lets you see more than its arguments and return value. - Implicit effects and calculations: Explain why implicit inputs or outputs make a function an action, and how removing them can turn it into a calculation.
Why it matters: This gives you a concrete way to recognize an action and see what must change to make it a calculation.
Key terms: inputs, outputs, explicit inputs, explicit output, implicit inputs, implicit outputs, action, calculation, side effects, arguments
4.8 Testing and reuse relate to inputs and outputs
This section connects advice for making code easier to test and reuse with the distinction between implicit and explicit inputs and outputs.
- DOM updates and business rules: Explain why a business rule should be separate from a DOM update, even though the application still needs to update the DOM.
Why it matters: Separating the answer from where it is displayed makes the business rule easier to test and reuse. - Globals and explicit function boundaries: Describe how reading or writing global variables creates implicit inputs or outputs, and how arguments and return values address them.
Why it matters: Explicit inputs and outputs make a function less dependent on its surroundings, helping with testing and reuse.
Key terms: business rules, DOM updates, implicit output, global variables, implicit inputs, implicit outputs, arguments, return value, explicit output
4.9 Extracting a calculation from an action
This section extracts cart-total logic from an action, then turns it into a calculation by replacing global-variable reads and writes with an argument and a return value.
- Behavior-preserving function extraction: Describe how the cart-total code is first moved into a new function and replaced at its original location with a call, without changing what the code does.
Why it matters: Keeping the program working during extraction makes it easier to change the function one step at a time. - Implicit cart inputs and outputs: Identify the extracted function's implicit input and outputs, and explain why its global-variable read and writes count as inputs and outputs.
Why it matters: Spotting data that enters and leaves through globals shows what must change to make the function a calculation. - Explicit cart calculation interface: Trace how the two writes to shopping_cart_total become one return value and the read of shopping_cart becomes a cart argument, while the original function handles the global assignment.
Why it matters: The total rule can now be called without relying on globals or putting its answer in the DOM.
Key terms: extract subroutine, refactoring, action, implicit input, implicit output, shopping_cart, shopping_cart_total, calc_total(), cart, return value
4.10 Extracting another calculation from an action
This section shows how to extract calculations from actions by turning implicit inputs into arguments and implicit outputs into return values.
- Calculation extraction process: Describe the repeatable process for extracting a calculation: move a suitable chunk of code into a function, identify its implicit inputs and outputs, and convert those inputs to arguments and outputs to return values.
Why it matters: This gives you a practical way to separate calculation code from actions. - Shopping cart input and output: Trace how add_item() changes from an action into a calculation: pass the cart as an argument instead of reading the global, then return a modified copy instead of changing the original array.
Why it matters: The cart example shows why passing a global in as an argument is not enough if the function still mutates it. - Reusable business rule calculations: Explain how the tax and free-shipping examples separate business rules from DOM updates by extracting functions with explicit inputs and returned answers.
Why it matters: A business rule that returns an answer can serve callers besides the code that updates the page.
Key terms: calculation, action, implicit inputs, implicit outputs, arguments, return values, add_item(), shopping_cart, implicit input, implicit output
4.11 Let’s see all of our code in one place
The section revisits how to label code as actions, calculations, or data and emphasizes that one action makes an entire function an action.
- Whole-function action classification: Explain that when labeling code A, C, or D, a function containing even one action is classified as an action.
Why it matters: This rule keeps a function from being labeled a calculation when part of it performs an action.
Key terms: action, calculation, data
4.12 Conclusion
The section closes the MegaMart example by reporting that the revised code pleased its users and hinting at further design improvements.
4.13 Summary
4.14 Up next…
The section closes the chapter by noting that some actions remain after calculations are extracted and previews improving those actions in the next chapter.
Where this is used later
- Principle: Minimize implicit inputs and outputs (chapter 5) · Introduces function inputs and outputs.
- (chapter intro) (chapter 5) · Extracting a calculation from an action by eliminating implicit inputs and outputs.
- Aligning design with business requirements (chapter 5) · Extracting a calculation from an action.
- Principle: In an asynchronous context, we use a final callback instead of a return value as our explicit output (chapter 15) · Extracting a calculation from an action establishes the earlier synchronous pattern of separating an action from value-producing code.
- Reducing implicit inputs and outputs (chapter 5) · further reducing implicit inputs and outputs applies the same approach
- The three steps of the copy-on-write discipline (chapter 6) · The copy-on-write discipline develops the copying approach introduced here.
- Aligning the function with business requirements (chapter 5) · Aligning functions with business requirements builds on separating business rules from surrounding action code.
- Categorizing our calculations (chapter 5) · Categorizing functions depends on recognizing which ones remain actions.
Concepts explained in this chapter
- implicit inputAn input obtained by a computation from surrounding state or context rather than supplied explicitly as a function argument.
- implicit outputAn effect of a function that changes external state or performs an observable operation rather than returning the result directly.
- extract subroutineA refactoring technique that moves a block of code into a separately named callable function and replaces the original block with a call to that function.
- explicit outputA computation result made directly available through a function's return value or another declared result channel.
- global variableA variable whose binding is accessible across broad program or module scope rather than being confined to a single function or block.
- explicit inputAn input to a function that is supplied directly at the call site through an argument or parameter.
- immutable collectionData or state whose represented values cannot be modified after creation.
- refactoringThe systematic restructuring of existing code without changing its externally observable behavior.
- actionAn action is a computation whose observable result depends on when or how it is performed and may involve effects beyond producing a value.
- mathematical calculationA calculation is a category of code that deterministically computes a result from its inputs without directly interacting with the outside world.
- DOM updateA modification to the Document Object Model that changes a document's represented content, structure, or presentation.
- return valueThe value produced as the result of a function invocation.
- side effectAn observable interaction with state or the external environment that occurs in addition to producing a computation's return value.
- dataAn inert representation of information that requires interpretation to acquire meaning and can be stored or transmitted.
- validation ruleA rule that specifies behavior or constraints within the problem domain modeled by software.
- functional, stateless philosophyA programming paradigm that emphasizes composing computations as evaluations of functions while minimizing mutable state and side effects.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
