Course progress0%
Course content

Module 1

Module 2

Module 3

Module 4

Module 5

Module 6

Module 7

Module 8

Module 9

Module 10

Module 11

Module 12

Module 13

Module 14

Module 15

Module 16

Module 17

Module 18

40 min

Separate Validation, Calculation and Presentation

Coordinate clear steps without mixing their responsibilities

By the end of this lesson

  • Coordinate clear steps without mixing their responsibilities
  • Refactor a working program with behavioral checks

A quote has stages

Validate input, calculate a subtotal, format the result and print it. Before refactoring, write expected behavior for one valid case and one invalid case. The restructuring must not change them accidentally.

function validateQuantity(quantity) {
  if (!Number.isInteger(quantity) || quantity <= 0) {
    throw new Error("Invalid quantity");
  }
}
function calculateSubtotal(unitPriceCents, quantity) {
  return unitPriceCents * quantity;
}
function formatQuote(subtotalCents) {
  return `Quote: ${subtotalCents} cents`;
}
function prepareQuote(unitPriceCents, quantity) {
  validateQuantity(quantity);
  if (!Number.isSafeInteger(unitPriceCents) || unitPriceCents < 0) {
    throw new Error("Invalid price");
  }
  const subtotalCents = calculateSubtotal(unitPriceCents, quantity);
  if (!Number.isSafeInteger(subtotalCents)) throw new Error("Amount too large");
  return formatQuote(subtotalCents);
}
console.assert(prepareQuote(500, 2) === "Quote: 1000 cents");

Number.isSafeInteger ensures integer arithmetic stays within JavaScript's safe integer range at the checked point. The coordinator establishes preconditions before calling the small calculation. Not every internal function needs duplicate validation if its boundary is explicit.

Guided refactor procedure

Capture behavior, extract one responsibility, rerun checks, then extract another. Renaming, moving files and changing business rules at the same time makes a mismatch harder to explain.

Independent lab

Make prepareQuote return a numeric subtotal instead of formatted text. Move formatting to its caller. Explain whether this is a behavior-preserving internal refactor or a change to its public contract.

Correction

It changes the function's return contract. Update its caller and contract tests intentionally. The underlying numeric pricing rule can remain the same. A change can improve design while still requiring coordinated caller changes; do not call every rewrite a harmless refactor.

Review

A clean program exposes its decisions at the right boundaries. Do not pursue purity at the expense of useful behavior: the final program still needs an entry point that connects calculations to observable output.

Lesson complete?

Your progress is saved on this device.