There is an old engineering joke that the first 90% of a rewrite takes 90% of the schedule, and the last 10% takes the other 90%. Everyone laughs, nods knowingly, and then signs off on rewriting their most business-critical application from scratch anyway. The laughter, it turns out, is usually the most accurate thing said in the meeting.

A company we worked with had just left exactly that meeting. Their core system was a large Java Swing application, twenty years old and central to everything they did, and they had decided its future was Angular: modern, responsive, and built with skills they could actually hire for. The goal was right. The only real question was how to get there, and the obvious answer was the dangerous one. Rewrite it.

The plan that looks great on a slide

On paper, a rewrite is beautiful. You list the screens, estimate them, draw a timeline, and commit. Some teams sweeten it with an automated converter that translates most of the screens for you and leaves just the last twenty percent to finish by hand. Hold that number, because you have met it before: the last twenty percent is the ten percent that takes the other ninety.

The reason is everything that never reaches the slide. A twenty-year-old application is not its screens. It is two decades of business rules wired silently behind them: edge cases learned the hard way, an exception added after some incident in 2014 that nobody wrote down, the odd little check in the corner of one form that makes no sense and turns out to be the only thing standing between the company and a four-million-euro mistake. As Joel Spolsky argued in his classic essay, the ugly, crufty parts of old code usually hold hard-won knowledge about corner cases and weird bugs, and when you throw the code away you throw that knowledge away with it. A rewrite has to rediscover all of it, from the outside, on a deadline. That rediscovery is where rewrites fail.

“The old one always let me do that”

It almost never fails in the demo. The new Angular build demos beautifully: fast, clean, responsive, everything the Swing original was not. It fails a few weeks after go-live, when someone who has used the original every day for fifteen years clicks three things in an order no developer thought to test, and the new screen does something subtly, expensively wrong. “Oh,” they say, mildly. “The old one always let me do that.” Multiply that one sentence by a few hundred undocumented behaviors and you have the true schedule of the project. Surveying six real rewrite stories, Herb Caudill found the trap from another angle: you cannot ship while you rewrite, so for months you deliver nothing new while the old system, and your competitors, keep moving.

What the company actually did

So they did not start with the rewrite. They started with Webswing. Webswing put their existing Swing application in the browser with no source-code changes: the real application, unchanged, reached through a URL. The delivery problem was solved in days, but the more important thing was quieter. The application was now running in the browser as a live, complete, perfectly faithful copy of its own behavior. Nothing had been reimplemented, so nothing had been lost.

Then they moved to Angular the way you can actually survive it: one screen at a time. Using Webswing, they rebuilt individual screens in Angular and ran them next to the untouched Swing screens inside a single application, in one browser tab. A modern Angular screen here, the original Swing screen there, all of it live. This is the pattern Martin Fowler named the strangler fig: you grow the new system around the old one until the old one quietly fades, instead of switching everything over on one frightening morning.

Why this survives where a rewrite dies

The difference is not effort, it is risk, and it comes down to three things. First, you always have a reference. When a new Angular screen behaves oddly, the original Swing screen is right there, live, showing exactly what correct looks like. You are not excavating twenty years of rules from documentation that does not exist, you are reading them off the running original.

Second, every step is small and reversible. If a rebuilt screen is wrong, you fall back to the Swing one, which never stopped working, and nobody downstream notices. A rewrite gives you no such undo.

Third, and this is the part that settles it: a half-modernized application runs in production perfectly well, some screens Angular, most still Swing, all of it live. A half-rewritten application runs nowhere. It sits dark, a construction site with the power off, until the very last screen is done, which is exactly the twenty percent that takes the other ninety.

The joke, finished

The company is still migrating today, at a pace that suits them, shipping Angular screens as they go, with the business running normally the whole time and no big-bang cutover anywhere on the calendar. They will finish, because every step has already shipped. The rewrite that looked so good on the slide is still working on its last ten percent. It always is.

Sources

Webswing, Modernisation Framework (Rebuild in the technology of your choice, run new web UI alongside the original)

Webswing, Home (run an existing Swing application in the browser, no source-code changes, since 2012)

Joel Spolsky, Things You Should Never Do, Part I (old code embeds hard-won knowledge)

Herb Caudill, Lessons from 6 software rewrite stories

Martin Fowler, Strangler Fig Application (gradual, screen-by-screen replacement)

arrow_back_ios

PreviousLinux Desktop to Web: Bringing Linux Applications to the Browser with Webswing

NextWebinar: Webswing 26.1 Introduction & Beyond Java - Linux apps in Webswing

arrow_forward_ios