The post has been translated automatically. Original language: Russian
In the early 2000s, I regularly read Joel on Software. Joel Spolsky already had experience working on Excel at Microsoft, and then founded Fog Creek Software. For us, his articles were valuable because he talked not only about code, but also about the real life of software projects: why developers make strange decisions, why good systems become ugly over time, and why sometimes the most dangerous decision is to start all over again.
On April 6, 2000, Joel published the article Things You Should Never Do, Part I. Her main thesis was simple: completely throwing away a working system and rewriting it from scratch is one of the riskiest things a software company can do.
Why do you want to start over?
Joel made a very accurate point: reading existing code is often more difficult than writing new code. When you create a system yourself, the architecture is in your head. When you disassemble the old one, you have to restore someone else's logic, the history of the project and the reasons for the appearance of strange solutions.
Hence, the temptation is easily born: why waste time on analysis? It's easier to throw everything out and do it normally. The new architecture seems cleaner, the names are more correct, and the old crutches can finally be destroyed.
The problem is that the old code has already been through real operation. Over the years, it has accumulated fixes for rare errors and exceptional situations that a new developer may simply not see. Joel cited the example of Netscape, where a massive browser rewrite from scratch led to a multi-year gap between major versions.
I had my own project.
One of the most difficult projects in my life was related to the Ministry of Defense. I've been running it for about ten years, and almost every year I've had the urge to throw out all the code and write it all over again.
And it was my own code. I designed it myself, wrote it myself, and maintained it myself, and still, a few years later, I looked at the early solutions and thought: I would have done it differently today.
But this system had one fundamental feature: it had to work accurately and never crash. Over the course of ten years, every mistake she found, every non-standard case, and every correction gradually became part of her behavior.
Therefore, I increasingly found myself thinking that every letter and every comma there served the same purpose — the system should continue to work.
The beauty of the code became secondary.
"It works and it works, the main thing is not to touch anything"
Around that time, I remember an old programmer's joke.
A child approaches his father, a programmer who is sitting at a computer, and asks:
— Dad, why does the sun rise in the east and set in the west?
The father looks up from the monitor for a moment:
"Is it like this every day?"
- yes.
— It works and it works. The main thing is not to touch anything.
By that time, I already had two children myself, so I remember the joke especially well.
Of course, this is not an engineering principle in the literal sense. Old systems need to be developed, fixed, and rebuilt. But before making a change, it's useful to understand why the working part of the system looks the way it does.
Not to "not touch", but to change gradually
From Joel's article, they sometimes draw too simple a conclusion: the old code cannot be rewritten. That's not really what he was talking about.
Individual parts of the system can and should be replaced. You can change interfaces, allocate modules, fix architectural problems, and rewrite specific components. First of all, the idea of completely throwing out an already working implementation and starting from scratch is dangerous.
The difference here is significant. With a gradual redesign, most of the proven behavior remains in place, and the risk area is limited. With a complete rewrite, you have to go through a lot of problems that the old system had already solved.
AI has made rewriting tempting again
In 2026, this topic has become particularly relevant. Previously, the idea of "let's rewrite everything" quickly ran into cost: it took months of team work. Now you can give away the old AI module and get a new implementation in a short time, and sometimes a completely new architecture.
This creates a dangerous feeling that Joel's main argument is outdated. If writing new code has become much cheaper, why not just start over?
But the problem has never been just the cost of writing code. The new code should preserve all the important behavior of the old system, including rare cases that no one remembers anymore.
This is where AI can mistakenly boost our self-confidence: it rewrites the program text well, but it doesn't always know the history of each check and each strange condition.
But AI helps to understand the old code.
There is also a downside. AI can reduce not only the cost of rewriting, but also the cost of understanding the existing system.
Today, you can ask the model to explain a large module, build a dependency map, find all the places where a particular state changes, offer regression tests and compare the old and new behavior.
And this, in my opinion, is a much more useful application of AI to older systems. Instead of "rewrite everything", you can first say: "help us understand what's going on here and what we risk losing."
After that, the decision to redo becomes much more meaningful.
What would I add to Joel's advice today
Over the years, I've come to another rule: if we're rewriting an important part of the system, it's advisable to be able to show that the new behavior is no worse than the old one.
For ordinary software, these can be good regression tests, stable interfaces, and real datasets. For critical systems, you can go further and formally describe the individual properties that the new implementation must preserve.
Then the main question changes. Not "has the new code become more beautiful?", but "has it retained the behavior for which the old system existed at all?"
What's left after a quarter of a century
I remember Joel's article because for almost ten years I lived inside a project that I wanted to rewrite every year. Over time, it became clear that the old code might look worse than the new one, but it has a huge advantage — it has been exposed to the real world for many years.
Today, AI allows you to rewrite almost anything much faster than twenty-five years ago. Therefore, professional caution only becomes more important.
Before you throw out the old system, you should first understand what exactly has accumulated in it and why it still works.
And only then decide what really needs to be changed.
Sometimes the old programming advice still sounds very reasonable.:
it works and it works — the main thing is, don't touch anything at first.
В начале 2000-х я регулярно читал Joel on Software. Джоэл Спольски уже имел опыт работы в Microsoft над Excel, а затем основал Fog Creek Software. Для нас его статьи были ценны тем, что он говорил не только о коде, но и о реальной жизни программных проектов: почему разработчики принимают странные решения, почему хорошие системы со временем становятся некрасивыми и почему иногда самое опасное решение — начать всё заново.
6 апреля 2000 года Джоэл опубликовал статью Things You Should Never Do, Part I. Её основной тезис был прост: полностью выбрасывать работающую систему и переписывать её с нуля — одна из самых рискованных вещей, которые может сделать программная компания.
Почему так хочется начать сначала
Джоэл очень точно заметил: читать существующий код часто труднее, чем написать новый. Когда создаёшь систему сам, архитектура находится у тебя в голове. Когда разбираешь старую, приходится восстанавливать чужую логику, историю проекта и причины появления странных решений.
Отсюда легко рождается соблазн: зачем тратить время на разбор? Проще всё выкинуть и сделать нормально. Новая архитектура кажется чище, названия — правильнее, а старые костыли можно наконец уничтожить.
Проблема в том, что старый код уже прошёл через реальную эксплуатацию. За годы в нём накопились исправления редких ошибок и исключительных ситуаций, которые новый разработчик может просто не увидеть. Джоэл приводил в пример Netscape, где масштабное переписывание браузера с нуля привело к многолетнему разрыву между крупными версиями.
У меня был свой такой проект
Один из самых сложных проектов в моей жизни был связан с Министерством обороны. Я вёл его около десяти лет, и почти каждый год у меня появлялось желание выбросить весь код и написать заново.
Причём это был мой собственный код. Я сам его проектировал, сам писал, сам сопровождал и всё равно спустя несколько лет смотрел на ранние решения и думал: сегодня я сделал бы иначе.
Но у этой системы была одна принципиальная особенность: она должна была работать точно и никогда не падать. За десять лет каждая найденная ошибка, каждый нестандартный случай и каждое исправление постепенно становились частью её поведения.
Поэтому я всё чаще ловил себя на мысли, что каждая буква и каждая запятая там служат одной цели — система должна продолжать работать.
Красота кода становилась вторичной.
«Работает и работает, главное ничего не трогай»
Примерно тогда мне запомнился старый программистский анекдот.
Ребёнок подходит к отцу-программисту, который сидит за компьютером, и спрашивает:
— Папа, а почему солнце встаёт на востоке, а садится на западе?
Отец ненадолго отрывается от монитора:
— И что, каждый день так?
— Да.
— Работает и работает. Главное ничего не трогай.
К тому времени у меня самого уже было двое детей, поэтому шутка запомнилась особенно хорошо.
Разумеется, это не инженерный принцип в буквальном смысле. Старые системы нужно развивать, исправлять и перестраивать. Но перед изменением полезно понять, почему работающая часть системы выглядит именно так.
Не «не трогать», а менять постепенно
Из статьи Джоэла иногда делают слишком простой вывод: старый код нельзя переписывать. На самом деле он говорил не об этом.
Отдельные части системы можно и нужно заменять. Можно менять интерфейсы, выделять модули, устранять архитектурные проблемы и переписывать конкретные компоненты. Опасна прежде всего идея полностью выбросить уже работающую реализацию и начать с чистого листа.
Разница здесь существенная. При постепенной переделке большая часть проверенного поведения остаётся на месте, а зона риска ограничена. При полном переписывании приходится заново проходить через множество проблем, которые старая система уже когда-то решила.
ИИ снова сделал переписывание соблазнительным
В 2026 году эта тема стала особенно актуальной. Раньше идея «давайте всё перепишем» быстро упиралась в стоимость: требовались месяцы работы команды. Сейчас можно отдать старый модуль ИИ и за короткое время получить новую реализацию, а иногда и совершенно новую архитектуру.
Это создаёт опасное ощущение, что основной аргумент Джоэла устарел. Если писать новый код стало намного дешевле, почему бы просто не начать сначала?
Но проблема никогда не была только в стоимости написания кода. Новый код должен сохранить всё важное поведение старой системы, включая редкие случаи, о которых никто уже не помнит.
Именно здесь ИИ может ошибочно усилить нашу самоуверенность: он хорошо переписывает текст программы, но не всегда знает историю возникновения каждой проверки и каждого странного условия.
Зато ИИ помогает понять старый код
Есть и обратная сторона. ИИ может снизить не только стоимость переписывания, но и стоимость понимания существующей системы.
Сегодня можно попросить модель объяснить большой модуль, построить карту зависимостей, найти все места изменения конкретного состояния, предложить регрессионные тесты и сравнить старое и новое поведение.
И вот это, на мой взгляд, куда более полезное применение ИИ к старым системам. Вместо «перепиши всё» сначала можно сказать: «помоги понять, что здесь происходит и что мы рискуем потерять».
После этого решение о переделке становится гораздо более осмысленным.
Что я бы добавил к совету Джоэла сегодня
За годы работы я пришёл к ещё одному правилу: если мы всё-таки переписываем важную часть системы, желательно уметь показать, что новое поведение не хуже старого.
Для обычного программного обеспечения это могут быть хорошие регрессионные тесты, стабильные интерфейсы и реальные наборы данных. Для критичных систем можно идти дальше и формально описывать отдельные свойства, которые новая реализация обязана сохранить.
Тогда главный вопрос меняется. Не «стал ли новый код красивее?», а «сохранил ли он то поведение, ради которого старая система вообще существовала?»
Что осталось через четверть века
Статья Джоэла запомнилась мне потому, что я почти десять лет жил внутри проекта, который ежегодно хотелось переписать. Со временем стало ясно: старый код может выглядеть хуже нового, но у него есть огромное преимущество — он уже много лет встречался с реальным миром.
Сегодня ИИ позволяет переписать почти что угодно гораздо быстрее, чем двадцать пять лет назад. Поэтому профессиональная осторожность становится только важнее.
Прежде чем выбрасывать старую систему, стоит сначала понять, что именно в ней накопилось и почему она до сих пор работает.
А уже потом решать, что действительно нужно менять.
Иногда старый программистский совет всё ещё звучит очень разумно:
работает и работает — главное, сначала ничего не трогай.