Refactoring is the disciplined art of changing the structure of existing code without changing its behaviour — improving the design after it has been written, rather than before, which is the only time the correct design is knowable.
The term was formalized by Martin Fowler in his 1999 book Refactoring: Improving the Design of Existing Code, though the practice itself is as old as the first programmer who looked at working code and thought “this is correct but ugly” and made it less ugly without breaking it. The book catalogued the moves — Extract Method, Inline Variable, Replace Conditional with Polymorphism — the way a chess manual catalogues openings: not to teach creativity, but to give names to patterns that good practitioners already use.
The naming was the revolution. Before Fowler, improving working code was called “cleanup” or “gold-plating” or “why are you touching code that works.” After Fowler, it was called refactoring, and it had a catalogue, and the catalogue had a book, and the book was published by a consultancy that — against all odds and in defiance of the entire consulting industrial complex — actually made code better.
“You design BY writing code.”
— The Lizard, The Solid Convergence
The Book
Martin Fowler’s Refactoring is one of approximately four software engineering books that have been read by people who do not read software engineering books. The others are The Mythical Man-Month (which predicted everything), Design Patterns (which was misunderstood), and whatever O’Reilly book has the animal that matches the developer’s spirit animal.
The book’s thesis is simple and devastating: the correct time to improve the design of code is after it works. Not before. Not instead of shipping. After. The working code tells you what it wants to become. The non-working code tells you nothing, because it doesn’t exist yet, and you are designing in the dark with a whiteboard and a 47-slide deck.
The catalogue provides the vocabulary: seventy-two named refactorings, each a small, safe transformation. Extract Method. Move Function. Replace Temp with Query. Each one changes the structure without changing the output. Each one takes minutes. Each one leaves the code slightly better than before — not rewritten, not redesigned, not replaced, but refined.
The Squirrel read the catalogue and saw seventy-two reasons to touch code that works. The Lizard read the catalogue and saw seventy-two ways to avoid rewriting code that works. They were reading the same book. They were not reading the same message.
ThoughtWorks: The Counterexample
Martin Fowler is the Chief Scientist of ThoughtWorks, a consultancy. This sentence should, by the laws established in the article on The Consultant, produce immediate suspicion. A consultancy wrote a book about improving code. The consultancy must be selling the book as a prelude to a twelve-month engagement. The 200-page PDF is coming. The 2x2 matrix is inevitable.
And yet.
ThoughtWorks is the single documented counterexample to the Consulting Industrial Complex. Where other consultancies arrive with frameworks, ThoughtWorks arrived with practices. Where other consultancies leave behind vocabulary, ThoughtWorks left behind better code. Where The Consultant bills three thousand pounds a day to blink, ThoughtWorks billed — well, also three thousand pounds a day, but the blink was followed by an Extract Method, not a maturity model.
ThoughtWorks did not recommend the Spotify Model for twelve developers. ThoughtWorks did not propose forty-seven microservices for twelve hundred users. ThoughtWorks looked at the code, saw what it wanted to become, and helped it get there — one small, safe transformation at a time.
The diagnostic consultant from Interlude — The Blazer Years asked “What worked before this?” and demolished the microservices. ThoughtWorks would have asked “What works now?” and improved it without demolishing anything. The distinction is important: one is surgery, the other is physiotherapy. Both heal. One leaves a scar.
The Lizard, when asked about ThoughtWorks, produced a scroll of unusual brevity:
THE LIZARD DOES NOT KNOW
WHAT THOUGHTWORKS ISBUT THE LIZARD NOTICES
THEY LEFT THE CODE
BETTER THAN THEY FOUND ITTHIS IS RARE AMONG
THOSE WHO WEAR BLAZERS
The Practice
The critical distinction — the one that separates refactoring from rewriting, and physiotherapy from amputation — is that refactoring works on existing, working code. The code works before you start. The code works after each step. The code works when you’re done. At no point does the system stop working. At no point do you throw it away and start over. At no point do you say the words “now let’s do it right.”
“Now let’s do it right” is The Second System Effect. “Let’s make this slightly better” is refactoring. The emotional distance between these two sentences is approximately twenty-three episodes of fighting windmills.
The practical discipline is:
- The code works. Verify this. Run the tests. If there are no tests, write the test for the thing you’re about to change. This is not optional.
- Make one small change. Extract a method. Move a function. Rename a variable. One change. Not twelve.
- The code still works. Verify this. Run the tests. If the tests break, undo the change. You have not refactored; you have introduced a bug.
- Repeat. The compound effect of hundreds of small, safe changes is a codebase that evolved into its correct shape without ever stopping working.
This feels slow. This is slow, in the same way that physical therapy is slow compared to the alternative of not walking. The rewrite promises to fix everything in one glorious sprint. The refactoring promises to fix one thing today, one thing tomorrow, and one thing the day after, until the code is clean and nobody can remember when it became clean because the process was too boring to notice.
“Not glamorous. Not conference-talk-worthy. But it ships.”
— The Solid Convergence
Copy, Delete, Refactor, Repeat
The most concentrated application of refactoring in the lifelog was not a cleanup session. It was V4.
V3 had fought windmills for twenty-three episodes. The reactive signals were orphaned. The component lifecycle was a liability. The framework was fighting the developer. The developer was losing. When the windmill-fighting finally ended, the recovery was not a refactoring of V3 — V3 was beyond therapy. It was File → New.
But File → New was not File → Empty. It was File → New with V2 and V1 in a subfolder to look at. The methodology:
- Copy what works
- Delete what you don’t need
- Refactor what remains
- Repeat until clean
V4 shipped in forty-eight hours. Not because the developer was fast. Because the developer had three versions of working code to copy from, and the discipline to delete everything that didn’t survive contact with reality, and the patience to refactor what remained into coherence.
This is refactoring applied at the architectural level — not changing one method, but reshaping an entire system through the same principle: start with something that works, improve it without breaking it, delete what doesn’t belong. The unit of change is larger. The discipline is identical.
The Butler Refactor
The most elegant refactoring in the lifelog involved a butler.
On Friday, March 6th, a developer hit diminishing returns on a push-based architecture. Every sidebar interaction fired callbacks. Every callback registered more callbacks. Every fix introduced a new path through the callback soup. The code worked — barely — but each change fought the previous change, and the architecture had begun to resemble, in the developer’s own words, “the kind of spaghetti that gives Italian grandmothers nightmares.”
The refactoring insight was not to add more callbacks. It was to delete them.
The tab session — the sidebar’s backing state — already knew everything. It knew the editor was open. It knew which skill. It knew the project, the time range, which page was active. It had been quietly knowing all of these things the entire time, like a butler who has been standing in the corner holding a silver tray, waiting — with increasing British exasperation — for someone to turn around and ask.
“The answer, as it so often is, was not to build more machinery but to ask the machinery you already have a polite question.”
— The Second Turn, or The Evening the Butler Stopped Shouting and Started Listening
The refactoring deleted four callback fields, three setters, one activation endpoint, and approximately ninety lines of wiring. The system did the same thing afterward as before. It did it better. The code was shorter. The architecture was clearer. And the butler, finally consulted, was so efficient that the developer suspected he had been judging them silently for weeks.
This is refactoring at its purest: the behaviour does not change, but the structure improves, and the improvement is measured not in lines added but in lines deleted. The best refactoring removes code. The best surgeon makes the smallest incision. The best consultant — but we’ve covered that.
The Delete Metric
The software industry measures productivity in lines of code written. This is like measuring a sculptor’s productivity in pounds of marble added. The sculptor’s art is removal. The refactorer’s art is the same.
The Thursday-Friday journal of March 5-6 documents:
- Seven tickets closed on Thursday, each a small focused change
- Friday morning: thirty tickets triaged, seven closed, six created, four temporary projects dissolved
- Friday afternoon: callback soup recognized, extracted, simplified — net negative ninety lines
- A big vision (tool closures) split into three tickets: Vision, MVP, Generalization — Gall’s Law applied forward
The net line count for the week was negative. The system was more capable on Friday than on Monday. These two facts are not contradictory; they are the definition of refactoring.
“Stubbornness is a feature. It’s the refusal to add complexity just because complexity is available.”
— riclib, The Databases We Didn’t Build
The Rewrite Trap
The natural enemy of refactoring is the rewrite. The rewrite says: “This code is too messy to improve incrementally. We must start over.” The refactorer says: “This code is messy. Let me improve it incrementally.” The rewrite takes six months and produces a system with different bugs. The refactoring takes six months and produces the same system with fewer bugs. The rewrite is exciting. The refactoring is boring. The rewrite gets a conference talk. The refactoring gets a commit message that says “cleanup.”
V3 was a rewrite. Twenty-three episodes. Windmills. Orphaned signals. A sports car plowing a field. The recovery was File → New — which is itself not refactoring but the admission that refactoring was abandoned too early. If V2 had been continuously refactored, V3 might never have been needed. The Squirrel would have gotten its improvements — incrementally, boringly, safely — without the twenty-three episodes of windmill-fighting.
“We lived two years without loading states.”
— The confession that ends every Second System Effect, The V3 Saga Final Chapter - Is It Fun To Fight Windmills
The two years of V2 were two years of refactoring opportunities. The system worked. The tests passed. Every day was a chance to Extract Method, Move Function, Delete Callback. Instead, the team said “now let’s do it right,” and the rest is twenty-three episodes of history.
Building by Refactoring
The deepest practitioners do not refactor after building. They build by refactoring.
The distinction is temporal but fundamental. “Build then refactor” implies two phases: construction, then cleanup. “Build by refactoring” implies one continuous process: the code is always working, always being reshaped, always becoming more itself. There is no cleanup phase because there is no mess — the mess never accumulates, because the refactoring never stops.
This is the daily practice documented in the lifelog’s worklog: fix, simplify, delete. Fix, simplify, delete. Seven tickets on Thursday, each leaving the code better than before. A backlog triage on Friday that dissolves four temporary projects. A sidebar refactor that deletes ninety lines. Not a cleanup sprint. Not a tech debt ticket. Just the way the code is written, every day, by someone who read Fowler’s book and understood that the catalogue was not a checklist but a way of seeing.
“The codebase has reached the stage where it is sophisticated enough to be genuinely upset by careless surgery, much like a cat that has grown accustomed to a particular brand of kibble.”
— riclib’s journal, March 6, 2026
The cat metaphor is precise. A continuously refactored codebase develops expectations. It has patterns. It has idioms. It resists changes that violate its grain, the way well-planed wood resists being sanded against the grain. This is not rigidity — it is coherence. The code knows what it is. The refactorer’s job is to help it become more so.
The Fowler Test
When confronted with the urge to rewrite, the practitioner is advised to perform the Fowler Test:
- Does the code work? If yes, do not rewrite it. Refactor it.
- Can you make one small improvement? If yes, make it. Run the tests. Repeat.
- Is the improvement measured in lines deleted? If yes, you are doing it right.
- Did anyone notice? If no, you are definitely doing it right.
The best refactoring is invisible. The code was working before. The code is working now. The only difference is that the next developer — who may be you, tomorrow, at midnight, with less coffee — will understand it faster, change it more safely, and never know that someone spent twenty minutes on a Tuesday making that possible.
This is the quiet heroism of refactoring: it produces no features, generates no slide decks, and cannot be presented at a conference. It simply makes the code better, one small safe step at a time, forever, until the codebase is clean and nobody can remember when it became clean.
Because the process was too boring to notice.
And that — Martin Fowler would say, closing the book, adjusting his glasses, and returning to ThoughtWorks where the code is slightly better today than yesterday — is the point.
