Programming advice that still matters when the tools change

Use a small input boundary and focused tests to make data contracts, error behavior, and future changes easier to reason about.
Make the contract smaller than the framework
Suppose an endpoint accepts a quantity for a stock reservation. The framework can parse a request and route it to a handler, but it cannot decide whether zero is meaningful, whether decimals are allowed, or whether a string containing extra characters should be accepted. Those are application decisions.
Write that contract before choosing a validation abstraction. For this example, the input is a string containing a decimal integer from 1 to 1000. Surrounding whitespace is allowed; signs, fractions, leading zeros, and trailing text are rejected. The upper bound is an illustrative product rule, not a universal inventory limit.
A small pure function makes the boundary visible. It has no network access, database, clock, or framework dependency. Its output either contains a valid quantity or an explicit error code, so the caller does not have to infer failure from an ambiguous zero.
Reject ambiguous input once
This JavaScript module works in Node.js 22 using ES modules. It deliberately does not use parseInt, which would accept a numeric prefix from a value such as 12boxes. The HTTP handler should pass the untrusted field through this function before creating a reservation.
export function parseQuantity(input) {
if (typeof input !== 'string') {
return { ok: false, error: 'quantity_must_be_text' };
}
const text = input.trim();
if (!/^[1-9][0-9]{0,3}$/.test(text)) {
return { ok: false, error: 'quantity_must_be_integer' };
}
const quantity = Number(text);
if (quantity > 1000) {
return { ok: false, error: 'quantity_out_of_range' };
}
return { ok: true, quantity };
}
Use tests to preserve decisions
Save this test beside the module and run node --test quantity.test.mjs. The cases describe observable behavior, including the boundary values and malformed inputs. They do not assert how many helper functions exist or which regular expression implements the rule.
Node's built-in test runner and strict assertion module are enough for this example. A failure should stop the check with a nonzero exit status. Keep the failure local: no test fixture needs a database just to establish what a valid quantity looks like.
import test from 'node:test';
import assert from 'node:assert/strict';
import { parseQuantity } from './quantity.mjs';
test('accepts supported boundaries and surrounding whitespace', () => {
for (const [input, quantity] of [['1', 1], [' 12 ', 12], ['1000', 1000]]) {
assert.deepEqual(parseQuantity(input), { ok: true, quantity });
}
});
test('rejects malformed values without returning a quantity', () => {
for (const input of [null, 12, '', '0', '-1', '01', '1.5', '12boxes', '99999']) {
const result = parseQuantity(input);
assert.equal(result.ok, false, String(input));
assert.equal('quantity' in result, false);
}
});
test('reports an out-of-range four-digit integer', () => {
assert.deepEqual(parseQuantity('1001'), {
ok: false,
error: 'quantity_out_of_range'
});
});
Keep the next boundary explicit too
Validation does not establish stock availability. Two valid requests can race for the same remaining item. The reservation operation still needs an atomic consistency rule in its persistence layer, and a retried request needs defined duplicate behavior. Do not add those concerns to the parser just because they share the word quantity.
At the request boundary, map the parser's error to the application's documented client-error response. Log an appropriate error category and request identifier if needed, rather than indiscriminately logging the incoming body. Unexpected database failures belong to a different error path.
This separation is useful because each decision can change independently. A future API might accept JSON numbers instead of form strings. Add a boundary adapter and tests for that contract rather than quietly broadening every caller's accepted input.
Name the decision and keep feedback close
Names such as parseQuantity and quantity_out_of_range explain the rule more directly than processValue or invalid. If a new requirement changes the limit, a reviewer can find the implementation and examples without tracing a generic validation pipeline.
Extract a shared abstraction when multiple callers truly share the contract, including their failure behavior. Two fields with similar syntax may still represent different business rules. A little duplication can be cheaper than a shared helper whose flags describe unrelated exceptions.
The durable habit is to make one decision visible, check it quickly, and keep its side effects bounded. Frameworks can change around that work without erasing the reasoning behind it.

