The next rule exposes the hidden contract.
The function fits on one screen. It multiplies price by quantity, applies a discount and adds a delivery charge. A reviewer can understand every operator and still misunderstand the agreement.
Reading tools Listen or translate
Read aloud
Uses an installed voice on your device.
Translate article
Machine translation. Code and evidence notes stay in English.
Original English text.
The function fits on one screen. It multiplies price by quantity, applies a discount and adds a delivery charge. A reviewer can understand every operator and still misunderstand the agreement.
Does the discount apply to every line? Is it rounded per line or after summation? Is free delivery earned before or after discount? Does the threshold mean greater than or greater than or equal? What happens when quantity is negative, the input is empty, or multiplication exceeds the chosen integer range?
These are not implementation details waiting for a later product meeting. The code already answers them, whether deliberately or accidentally. A short expression can hide more policy than a longer function with named decisions.
We will use two synthetic lines and integer accounting units. The example is a software contract exercise, not a production pricing rule. Change eligibility, quantity and threshold in the visual, then compare the original all-lines rule with the revised eligible-lines rule. The receipt is computed from those choices.
The important observation is not which receipt is smaller. It is which change was intended and which behavior changed as collateral damage. The model also lets you set the threshold exactly to the discounted subtotal, where a strict and inclusive comparison produce different answers.
Start with a receipt you can explain by hand
Line A contains two units at one hundred accounting cents each. Line B contains three units at two hundred each. The undiscounted subtotal is eight hundred. Under a ten-percent all-lines rule, the discount is eighty and the net subtotal is seven hundred and twenty.
Now make B ineligible. A's discount is twenty; B's is zero. The revised net subtotal becomes seven hundred and eighty. If the delivery threshold is eight hundred and the charge is fifty, both examples still pay delivery. If the threshold becomes exactly seven hundred and eighty, the revised receipt distinguishes strict from inclusive comparison.
These small numbers are an independent oracle. They are not calculated by running the implementation twice. A test's expected value should expose the intended arithmetic, so a reviewer can see whether it expresses the product rule or merely copies a bug.
The test set should include a case where a policy change matters and a case where it does not. If every line is eligible, the two eligibility policies should agree. If no line is eligible, the revised discount should be zero. A test suite consisting only of ordinary mixed inputs can miss both boundaries.
Give the policy a place to live
One possible representation separates the line's data from the calculation's policy:
public sealed record Line(long UnitCents, int Quantity, bool Eligible);
public sealed record Policy(
int DiscountPercent,
long FreeDeliveryThreshold,
long DeliveryCents,
bool InclusiveThreshold);
The types do not settle every question. They make several questions visible. Eligibility is a property of a line, while the threshold and comparison rule belong to the selected policy. If a later requirement introduces category-specific rates, the design has a clear place to reconsider the representation instead of scattering another conditional through unrelated arithmetic.
The choice of integer units is also deliberate. It avoids confusing this example's accounting unit with a floating-point approximation. It does not establish that every currency or commercial rule should use the same representation. Scale, rounding and legal constraints belong to the real domain contract.
Rounding belongs to the rule, not the formatting
Consider two eligible lines with tiny amounts. Rounding each line's discount and then adding can differ from adding exact discounts and rounding once. Neither order is universally correct; one must match the agreement.
static long RoundedDiscount(long cents, int percent)
{
decimal raw = cents * (percent / 100m);
return checked((long)decimal.Round(
raw, 0, MidpointRounding.AwayFromZero));
}
This helper expresses one policy: round the line discount to an integer unit, with midpoint behavior stated explicitly. The .NET 9.0.4 Decimal implementation is a historically available reference for the operation. It is not evidence that this synthetic policy is appropriate for a real checkout.
A display that prints two decimal places is not a substitute for a rounding rule in the calculation. By the time formatting happens, the decision may already have influenced a threshold or persisted receipt. Changing only the visual string can leave two clients disagreeing about the same result.
Make invalid input fail before partial work escapes
Negative prices and quantities should not drift through the calculation until an unexpected total reveals them. Validate the permitted domain at the boundary. If zero quantity is allowed, decide whether it produces an inert line or should be removed before calculation. If an empty basket has a delivery charge, state that behavior rather than letting an accidental default choose it.
Arithmetic overflow is another input boundary. Multiplying a large unit amount by a large quantity can overflow a fixed-width integer. A checked operation turns that into an explicit failure rather than a plausible but incorrect number.
long gross = checked(line.UnitCents * line.Quantity);
long discount = line.Eligible
? RoundedDiscount(gross, policy.DiscountPercent)
: 0;
long net = checked(gross - discount);
This is a focused fragment, not a complete billing library. A full implementation still needs validation, accumulation, the delivery decision and a clearly defined error contract. Its value is showing where the policy and arithmetic meet.
The browser model uses small bounded integers and an explicit decimal midpoint rule for its examples. It does not claim to prove all C# overflow paths or represent the full range of a production monetary type. A later executable companion can test those boundaries with its actual runtime and execution date attached.
The threshold should be tested on both sides and exactly at it
A threshold test that checks only a clearly cheap and a clearly expensive basket can pass with either > or >=. The equality case is where the rule becomes observable.
For the revised example, set the threshold to seven hundred and eighty. With an inclusive policy, the net subtotal qualifies for free delivery. With a strict policy, it does not. The visual marks the subtotal on the threshold line and moves the delivery charge into or out of the receipt.
Also specify which subtotal the comparison uses. Comparing before discount and comparing after discount are different policies. A refactor that extracts a helper can accidentally pass the wrong intermediate value while preserving the helper's name and return type.
Naming the intermediate values helps a review: gross subtotal, discount total, net subtotal, delivery charge and final total. These are not five ways to say “amount.” They are five points in the calculation where a changed rule can have a different consequence.
Properties can reveal cases you did not enumerate
Examples are strongest when their expected answers are independently understandable. Properties add another view. Under a fixed policy and exact per-line arithmetic, permuting lines should not change the result. Adding an ineligible zero-quantity line should not add a discount. If all lines are eligible, the eligibility-aware rule should match the all-lines baseline for the same rounding convention.
A property is not automatically true just because it sounds reasonable. Splitting one line into two can change a per-line rounding result. That is a useful counterexample, not necessarily an implementation defect. The property must follow the declared policy rather than impose a different one accidentally.
Mutation checks can also be focused. Replace the inclusive comparison with a strict one, or remove the eligibility condition. The corresponding boundary examples should fail. If they do not, the tests are not protecting the distinction the article claims to teach.
Maintainability is not a nanosecond count
Two implementations can have identical behavior and different structure. One can be easier to extend without changing unrelated decisions. A timing experiment can measure a selected execution path, but it cannot prove that a team will understand a new requirement more accurately.
For this small function, a useful review packet includes the current rules, the proposed next rule, examples at the boundaries and a diff showing which responsibilities changed. It can show whether eligibility was isolated, whether threshold semantics were named and whether the error contract remained stable.
That is meaningful evidence about the code. It is not a controlled study of developer productivity. We should not turn “the change touched one helper” into a numerical claim about maintainability, just as we should not turn a fast benchmark into proof of correctness.
The same discipline applies when AI generated the implementation. A plausible function and an explanation of that function are not independent agreement about the requirements. The author still needs an oracle that can disagree with both.
Review the omission as carefully as the feature
This example leaves out taxes, currency conversion, coupons, inventory, concurrent updates and external payment effects. That is a bounded teaching choice. Adding any of them would create new contracts, not merely more branches in the same function.
The practical review question is: which next change would force this implementation to reveal an assumption it currently hides? For our receipt, eligibility and equality at the threshold do exactly that. For another function it might be a new time zone, an empty result or a retry after an uncertain response.
A small function deserves a small but precise agreement. Once the rule is clear, the implementation can become compact without becoming mysterious. Until then, shortening the code mostly shortens the distance between hidden decisions.
GO FURTHER
Inspect the contemporary laboratory.
This is a newly reconstructed historical edition, not a claim of earlier authorship. Later executed experiments, their exact environments and original results are preserved in a separate notebook.