Two old coupon-admin pages needed a change, and one misplaced quotation mark inside a table cell had already turned a simple edit into a guessing game. The pages were full of little pieces of handwritten web code, with data pushed straight into the middle of the page. A table here, a form there, a value wedged into the markup. It worked, but touching it felt like trying to replace one tile in a mosaic with a hammer.
What the old pages did
We had been working with the old pattern because it was already there. The page took one item from the database, wrote a bit of HTML, moved to the next item, and did it again. A recordset is an old-fashioned data list that you have to step through one item at a time, then remember to close when you are done. The page also mixed its data and its layout in the same dense block of text.
That made every change slow. We had to read the data logic and the page layout at the same time, even for a small adjustment. One quote or punctuation mark in the wrong place could look exactly like a logic problem until the page appeared in a browser. The cost was time and patience. The work was not dramatic, but it was the slow, fussy kind that makes people put off a needed improvement because every small change feels dangerous.
Rebuilding two pages, not the whole application
We did not try to replace the whole application. That would have been like tearing out the kitchen because one cabinet door sticks. Instead, we rebuilt two pages, one at a time, with a small helper that creates the parts of a page in a clearer order.
Rather than writing a long string of page code, we could say, in effect: make a table, then add its heading, then add a row, then add a cell. For the edit page, we could create one field at a time: a label, then the box where someone types, then the value that belongs in it. The result reads like a list of instructions for setting a table, where the old version read like one paragraph with everything jammed together.
The helper was deliberately small. It did not bring in a new framework or change the language the application already used. Each instruction creates one page element, gives it the details it needs, attaches it where it belongs, and lets the next instruction follow. We added new instructions only when a page needed them. That mattered because the old pages could keep working while these two changed.
The data changed shape too. Instead of making the page manage that step-by-step list, the page asked for a normal array, which is a regular list of items. Then it used an ordinary loop to go through the list. The page no longer had to remember whether it had reached the end or whether it had closed the data cursor. That responsibility moved out of the page.
What came with the cleanup
First, it became much easier to see where page values were made safe before being put into the page. In the old version, values went straight into the HTML. In the new version, they passed through one visible encoding step as they entered the builder. Think of it as checking a label before putting it on a package. The check sits in one place where it can be seen and reviewed.
Second, the old decorative clutter fell away. Some of it was leftover rounded-corner spacer code and some was tiny styling instructions typed directly into the page. The new pages used existing style classes instead. The table and form got cleaner without a separate campaign to restyle them.
The most human improvement was a plain empty message. Before, a search with zero coupon codes produced a blank table. Now the page says, “No coupon codes found.” A blank sheet can make someone wonder whether the system is broken. A short sentence answers the question.
What it cost
The newer page code has more lines than the old tangled version. Across the two files, the change was roughly 700 lines: 478 added and 235 removed. You also give up some of the quick visual scan that comes from seeing literal HTML tags. The trade is that the page now has named pieces that can be reused, checked, and changed without digging through one large wall of text.
The release decision reflected that trade. This was an internal admin refactor with no intended user-visible change, so it went to the preview branch and waited for the normal release. That same morning, two actual production bugs were hotfixed and tagged right away. A cleanup needs careful preview eyes. A live bug needs urgency. Treating both as emergencies would make it harder to judge either one well.
Only two pages changed. A few hundred older pages still use the old approach in production. That is why this kind of improvement is possible at all: the new and old versions sit side by side, so nobody has to stop everything to make a page easier to work with. If you ask your own team about an older system, ask whether pages can be improved one at a time, and whether cleanups and live bug fixes go out on separate tracks.