A customer lives in Paris and orders a gift for her sister in Lyon. The parcel needs to go to Lyon. The invoice needs the customer’s details in Paris.

The shop in this example is fictional. Its software stores one address per order. Both the parcel label and the invoice are generated from that same value.

Stored address Parcel label Invoice
Paris Paris, wrong destination Paris, as requested
Lyon Lyon, correct destination Lyon, wrong details

Neither value satisfies both requests. The problem exists before any code changes. Adding a field to the form will resolve it only if the software also learns to distinguish the two uses.

The second field exists, but the invoice still reads the first

The developer adds a billing address. The order now stores Lyon for delivery and Paris for billing. The form is correct and both values are saved.

The printed invoice still says Lyon. The program producing it reads the original field. It cannot infer that adding a second field has changed the meaning of the first.

The fix makes the invoicing program read Paris while leaving Lyon for parcel preparation. The accounting export also uses the original address. It needs a separate change, or the PDF and the export will describe the same order with different details.

There are already three changes behind the request to “add an address”: storing the new value, using it on the invoice and using it in the export. The delivery label must keep its existing behaviour. Finding those uses throughout the software accounts for part of the cost that the form design does not reveal.

Old orders do not contain the new value

The new version handles orders created with two addresses. An order placed the day before still has only one. If the invoicing program requires the new field, reprinting that invoice fails.

In this example, the fallback rule is to use the address stored on an old order when it has no billing address. This preserves its previous behaviour. It cannot reconstruct a different address that was never recorded.

There is also the customer moving house. If a reprint retrieves the current address from her profile, a January invoice can change in October. The document therefore needs the details retained for that sale, independently of those used for future orders.

A test covering only the new gift order would miss both defects. Existing sales are another source of work in the change.

Four orders make the discussion specific

Before estimating the work, the team can establish four cases and their expected results. For this shop, they fit in one table.

Case to check Expected result
Buying for oneself Parcel and invoice use the same address
Gift from Paris to Lyon Parcel to Lyon, invoice to Paris
Old order Invoice reprinted with the retained details
Customer moves house Old invoice remains unchanged

A new developer can run these cases and compare the resulting documents. They no longer have to guess what “do not break old orders” means. Automated tests can use the same cases, with an additional check of the accounting export.

This does not remove the need to examine the code. It does save each developer from rediscovering, through a conversation or an incident, what the team intends to preserve.

What makes the change complete

The work can be considered complete when the four cases pass, the PDF and export agree, and the parcel label still uses the delivery address. None of those checks requires rebuilding the product catalogue or payments.

That boundary distinguishes a targeted change from a general rewrite. It also rules out a false finish: two visible form fields with an export still connected to the old one.

The next delivery request will have an identified data field and verification cases to build on. It may introduce other difficulties, but the distinction between parcel recipient and invoice recipient will no longer have to be invented.

At Gridky, the scale of incidents led us to the wider effort described in Drynuary. The five faces of technical debt distinguishes this code problem from delays created by the organisation.

Resources for this article

Continue reading

A fix finished on Tuesday, released the following week

At Gridky, a month and a half without new features