Hacker News new | past | comments | ask | show | jobs | submit login
Things You Should Never Do, Part I (2000) (joelonsoftware.com)
157 points by sealeck 10 months ago | hide | past | favorite | 100 comments



The main reason why developers do rewrites is because it is easier to read your own code than it is to read somebody else's code. Doing a rewrite means you only have to work with code that was written by your current coworkers or by yourself.

This is also the core motivation behind all of the schemes to force a single coding style on all developers at the cost of performance and usually with an extremely complicated design for seemingly no reason. Usually, these turn out to be unreadable messes as well a generation later once everybody has moved onto the latest and "greatest" coding style trend.

Instead of doing rewrites, you can just refactor code. That means, among other things, deleting obsolete code for platforms you no longer support and, in the case of C/C++, converting macros to functions. You can also document the codebase (with comments not commit messages) so that developers understand what the code does and why it is there. But a full rewrite is usually a bad idea that will just introduce new bugs and remove existing functionality.

Refactor vs rewrite is basically the software development equivalent of reform vs revolution in political science and everybody with even a minimal knowledge of history knows that revolutions usually end badly with an even worse regime taking power. Likewise, the failure to accept the need for reform (i.e. refusing to allow refactoring) inevitably leads to revolution.


This is why I recommend using a framework in commercial projects, and following it's idioms as closely as makes sense for your project.

It means there is a shared idiomatic approach across your team and all the documentation for it is just the framework documentation. It is also easier to hire devs, if you can vet their ability to write idiomatic code in a specific framework then you can better assume they will mesh well with yor codebase.

It is a communication and empathy problem at its heart. You are being empathetic to future devs and future you by acknowledging the knowledge they would need to work on your code. Then the communication of your idioms is baked into the framework ecosystem and docs.


Using a framework doesn't help at all because a framework is still somebody else's code. There is nothing special about somebody else's framework that makes it any easier to deal with that somebody else's non-framework.


The idea is that frameworks are generally designed to be used by other people, leading to greater focus on documentation, developer ergonomics, community support and generally more versatile code (scales with number of contributers/users; many will report obscure bugs and edge cases you may never consider testing but would impact your end users). Another huge benefit is you don't have to rewrite an entire system from scratch, saving time and mental load.

I'd say there's quite a bit "special" about all of these attributes, at least enough to warrant careful consideration.


Just because something is designed to be used by other people doesn't mean it's good. There are lots of things designed to be used by other people, leading to all of the features you list: documentation, community, other people finding bugs, yada yada yada... languages, operating systems, libraries... and many of those things still suck. There is nothing inherent about being designed for use by other people that makes things suck less, and there is nothing magical about "frameworks" that makes them suck less than all the other stuff designed to be used by other people but still sucks.

If you qualify this advice to the point where it actually becomes useful it turns into, "Use code written by other people that doesn't suck." And that, of course, is indeed a good idea, but it's a lot easier said than done.


Absolutely; most frameworks will not fulfill their design goal. Most ambitious open source programming efforts tend to wither away due to loss of interest, a failure to gain contributors, lack of experience, lack of time or energy and many other factors.

But despite that caveat, there do exist frameworks out there today that speed up development for some developers. Whether one has the time or energy or will to audit them to find one that works best for them (or learn that none of them do) is up to the individual.

I bring this up because many of us on this website are at times infected by NIH syndrome and think we can do better than a dedicated team of experienced front-end developers. And it's likely true for many frameworks, but not all. Additionally, we may want to extend that attitude to our workplace where our peers and bosses likely value development speed and cross-project consistency over code performance.

I used to eschew any and all frameworks, but now I realize that my values have changed. Projects like Svelte give me hope for a better future for front-end development.


> But despite that caveat, there do exist frameworks out there today that speed up development for some developers.

Of course. But there also exist frameworks that will slow development down. For any X in {frameworks, languages, operating systems, libraries} there exist X's that will be helpful and X's that will not, and so "use an X" by itself is not helpful advice for any X. You have to use a good X, but that isn't helpful either because it just begs the question.


Absolutely true.

I just intended to push back against the notion that frameworks should not be considered.


Until $framework decides to rewrite everything too, and now you're stuck on an old unmaintained version or waste time migrating to the new version.


s/$framework/$any-coding-project-written-ever

Don't let bad frameworks represent all frameworks. That is a faulty generalization [0].

[0] https://en.wikipedia.org/wiki/Faulty_generalization


I'll address both your comments here if that's alright,

It's not about code quality at all, it actually doesn't matter that much if the framework is excellent or just okay to reap the main benefit, which is knowledge diffusion through the team and having a set of agreed upon idioms that there's no need to bike shed over. Not every team has a software architect skillset so it's a bit of a risk hedge as well.

There's no need to argue over implementation details, you waste less time onboarding new staff and you have that rich ecosystem of docs and community of solved problems.

That's all. There are great reasons to build your own software but if you're working in a team I feel it's an easier experience to use a known framework. Also a bit more responsible from a business risk management perspective, since you don't have as big of a "bus problem". Only your business logic is trapped inside your org.


That's a sound argument under certain circumstances. If you're building a standard product using relatively unskilled labor then yes, using a framework -- any framework -- can be helpful. But if you're doing something where rewriting an existing code base is even an option you would consider then you almost certainly are not operating under those circumstances. For starters, you probably have people on your team who are plausibly capable of rewriting the existing code, and under those circumstances, hemming those people in with a bad framework can do a lot more harm than good. So I stand by my original statement: "Use a framework" is not good advice in general. It can be the right thing under certain circumstances, but the art is in recognizing those circumstances, not in the use of a framework. Blindly following "use a framework" with no further qualification is a PHB move.


In 2000, refactoring was not really a thing as few projects had many automated unit tests and any change to the code had to be tested manually.


>The main reason why developers do rewrites is because it is easier to read your own code than it is to read somebody else's code.

LOL: so did you read TFA, or just come up with this yourself?


> The main reason why developers do rewrites is because it is easier to read your own code than it is to read somebody else's code.

Did you read the article? He says what you wrote explicitly, in fact there is an entire section on it.


[flagged]


I only have surface-level knowledge of any of these things, but I don't think most people would consider a defeated slave rebellion or a war of independence as "revolutions"

As for the other two ... maybe the people of those countries would have endured less suffering afterwards if they had reformed rather than revolted?


>war of independence as "revolutions"

The war of independence the 13 American colonies waged against Britain is generally called "The American Revolution", but yes, for some reason most other wars of independence aren't called revolutions -- for instance while there was a Mexican revolution in the early 20th century, the earlier war of independence against Spain is just called the "Mexican war of independence" (Guerra de Independencia de México)


> Should the French have tried reforming the feudal society?

Well, the English AFAIK have done exactly that, haven't they?


I think people tend to want to rewrite software for the psychological break from the old, bad and ugly thing they don't want to have anything to do with anymore.

It is so easy to think "If only I could start everything from scratch, life will be so beautiful and I will be so successful and everybody will be happy. I will fix all the problems of the current codebase and people will forever sing songs about how amazingly I turned everything around."

What more frequnetly (much more frequnetly) happens is usually some mix of:

* developers not really understanding why exactly the previous version failed,

* developers not really understanding what actually worked well in the previous version,

* developers completely underestimating actual amount of accumulated knowledge in the old system that they now have to replicate. Obviously, they only discover it along the way when it is suddenly too late to fix the design to take all of that stuff into account.

* developers not appreciating the fact they are in a much very different (worse) situation than original creators of the previous version. The creators of the previous version had time to build the system and then slowly evolve it. But the current team has typically a short time horizon to replicate ALL of it.

* as the resources are shifted from the maintenance of the old system to the development of the new, suddenly the clock starts ticking and the stakeholders are impatient to see the result. The pressure grows quickly and with it comes inevitable compromises and technical debt.

* at some point development team is told they have to start maintaining the old app. The resources devoted to the rewrite shrink, the work grinds to a halt. I have seen many more systems that have been in a state of perpetual migration than I have seen ones that have been successfully completed rewrite.


> * developers not appreciating the fact they are in a much very different (worse) situation than original creators of the previous version. The creators of the previous version had time to build the system and then slowly evolve it. But the current team has typically a short time horizon to replicate ALL of it.

On the other hand, developers writing the new system have the major benefit that the requirements are known. Second system effect is real, but if you can avoid it, and focus on addressing the real requirements (as determined by the lived experience of the first system), you can get something good. Sometimes, something really good, if the old system was built on the wrong abstractions, and the new system has better fitting abstractions.

Of course, if you don't actually know what the current system is doing, you're not really in a better place to design the second system.


that only really works for static or mostly stable requirements. not so great for something like the fast evolving web platform of the late 90s when we re-wrote the Netscape/Mozilla rendering engine.


I don't think real requirements are known and understood in general.

For example, consider a team that has been maintaining the system for a long time. Most or all of the people that has initially created the system have moved on to other positions or companies. Many of the people who stuck with the team did so for reasons of being experts but are also unable or unwilling to communicate well (for example, because they see the value in preserving their position of being one of the few people with expertise).

In a team like that, they might have good memory of things they have worked on recently, but not necessarily things that are working and the users take for granted. Users do not typically spend much time reaffirming the features that are working well.

One of the challenges of working with stakeholders is that close to 100% of the communication tends to be on things that are not working or are missing or they want to get done. As a developer or manager of the team, you need to find some way of answering the question "am I doing well?". Because users are of course unhappy with how the application works, but to understand levels of unhappiness you need to find some other reference (working for some other projects).

I was yesterday in a meeting with developers where they complained about how manual our deployment system is.

Our deployment system requires them to press a button to deploy a version of the application to the environment. Yes, log in and press a button.

I explained, that I worked in the past for teams that had hundred page manuals on how to compile and deploy the software and that manual would be compiled again and again for each release and the process would take from couple of days to a whole quarter.

So you need to have some perspective to be able to judge that kind of feedback.


In my experience, the biggest factors are:

* Many developers prefer working on greenfield code rather than adding to an old codebase

* Working on a rewrite buys you some time in limbo where you can write code while being free from the burdens of production operations. This period is shorter than people dream, but it's often long enough for developers to pitch a rewrite for 6 months, code for 12 months and then skip to the next job with "Spearheaded rewrite of critical infrastructure" on their resume. Time it right and you can get out of there before you have to support the code you wrote.


Oh, then from the ops perspective, the programmers who pretend that the production environment doesn't exist, are the worst nightmare.


It is similar with databases. Developers like to pretend that ten years worth of data doesn't exist or is of no consequence. They would like to pretend everything can be re-deployed from github. They fail to realize the database includes data from version .1 while the application version is now 4.7 with completely new business rules and application logic.


> developers not really understanding

Rewriting software is an excellent way to gain such understanding. I only understood what GNU autoconf was doing when I was in the middle of rewriting its core functionality in pure GNU make.

And who knows? You might actually make a better wheel against all odds.


Or make one you don't understand the purpose of, rewriting GNU Autoconf in GNU make would serve no purpose since what Autoconf does has nothing to do with building, but rather finding out details about the running system.

Maybe you were thinking of GNU Automake ...


Autotools in general, I guess. Detecting OS and features, conditionally including sources in the build, abstracting compiler flags. The most important feature though was automatically figuring out the list of source files in an arbitrary file system tree structure and then mapping them to the build tree as object and dependency files. I somehow conjured up a recursive wildcard function that implements a simple find command in pure GNU make. It's kind of horrifying now that I think about it.

I suppose I was rewriting automake too: I started metaprogramming GNU make by evaluating templates. It's a surprisingly lisplike turing tarpit.


Related:

Things You Should Never Do, Part I - https://news.ycombinator.com/item?id=31122975 - April 2022 (7 comments)

It’s harder to read code than to write it - https://news.ycombinator.com/item?id=31117277 - April 2022 (2 comments)

Things You Should Never Do (2000) - https://news.ycombinator.com/item?id=23725867 - July 2020 (83 comments)

Things You Should Never Do, Part I (2000) - https://news.ycombinator.com/item?id=6327021 - Sept 2013 (154 comments)

Things You Should Never Do, Part I - https://news.ycombinator.com/item?id=3624830 - Feb 2012 (40 comments)

Things You Should Never Do [2000] - https://news.ycombinator.com/item?id=3449953 - Jan 2012 (2 comments)

Things You Should Never Do, Part I - https://news.ycombinator.com/item?id=608431 - May 2009 (40 comments)


And a bit earlier:

https://news.ycombinator.com/item?id=6327021 - Sept 2013 (154 comments)


Whoa I missed that and several others - not sure what happened there. Added above now. Thanks!


A tool I wrote at a previous job was thrown out after a few years of everyday use within the team. The team lead had noticed that my 300 or so lines of code was unnecessarily complex and could be replaced by ten lines of $TEAM_LEADS_FAVORITE_LANGUAGE. So it was.

Every few weeks someone came to me complaining that something didnt work in "my" tool. Thanks to git I could port the old, working code over to the new tool almost every time. Eventually the 10 lines grew to a few hundred again.


I once worked with a guy that probably would be classed as a 10x developer.

Always when the discussion about an edge case came up, he'd dismiss it as "that's never gonna happen".

The of course when those never-gonna-happen things happened, he would absolutely not want the responsibility to fix them.


It's easy to convince management you are brilliant by tackling the common cases of a problem and leaving the edge cases to someone else to solve further down the line.


> they think the old code is a mess. . . . they are probably wrong. The reason that they think the old code is a mess is ... It’s harder to read code than to write it.

I suppose I think the reason people think code is a mess is because it _is_ a mess. Just yesterday I saw a team decide to override $PATH in 50 separate files because they didn't understand how to package a python library. (I'm not innocent in crazy stuff either, we're all human).

My experience is that rewrites happen when a team doesn't have anything clear to do instead, so it's more like "teams/businesses with no clear objectives" struggle rather than inherently rewrites.


There's mess and there's "override $PATH in 50 files" mess. "The old code is a mess" is a really easy conclusion to come to when trying to grok a complicated codebase, and it's not always correct.


Genuine question, is your experience that it is often more your lack of understanding than the code actually being a mess? I ask because while I've been guilty of judging too soon myself, it's much more common the code is just bad, written by someone who's already left. (I work in healthcare and startups though, so different industries are probably different. Also, I've probably been the person who wrote that bad code too!)


It's usually a little of both. Sometimes it's a little messy but before you get full understanding, it appears a lot messier. But having the experience of coming across code that I think sucks until I fully understand it and recognize it as something I wrote two years ago (but maybe someone moved to a new location, so I didn't remember it) makes me a little more humble when it comes to judging code.


I first read this as a 22-year-old software engineer. Re-reading it as a 46-year-old CTO, it still tracks and still is truer than not. Most re-writes happen because the engineers want to, not because they really need to.


Not only that, it’s often an unconscious way for engineers to regain a sense of self-direction and autonomy. As folks have difficulty actually articulating that need as such, it can often be accomplished in much more productive ways that are not harmful to firms.


Do you have any examples of more productive alternatives?


Not really. You have to begin by being able to be honest about the experience with yourself and decide what you want to do about it and if anything can be done.


I hear Joel on this, I really do, but can one imagine using any code from Netscape Communicator 4 in whatever Firefox I'm typing this on?

Perhaps it's rose tinted glasses, but I distinctly remember that Netscape 4 had to repaint the screen on window resize. Like the code was that bad. The product was rushed to market and features were bolted on because there was a browser race/war where quality suffered greatly.

This POV would have been impossible to see if you use Netscape 6 because it was so unusable no one used Netscape 6 except for nerd points and to try out "does my browser support this CSS" tests.


I try to avoid rewriting code (especially if it was originally written by others), and when I do it, I try to do it selectively, and for quality reasons.

For example, one place I worked as a C and C++ programmer, they hired lots of recent grads from a top CS program. Unfortunately, production-grade C code is much harder than most people think it is. The bug reports in core code used throughout the system often to lead to functions that weren't even on the right track for the quality level of C that we needed. So I started killin' code that needed killin'. Management seemed to approve of those decisions, and I don't think I stepped on any toes. (I suspect that the recent grads who'd written code like homework assignments didn't care if anyone rewrote it, so long as it was done quietly.)

Another time, there was a single Web service endpoint that pretty much had to work correctly, if the company was going to stay in business. So I rewrote it much more methodically and resilient than Web backend code typically gets written.

There was another time I simply walked away from a new consulting project, once I saw the code and realized that it was unsalvageable, and that the client wouldn't understand rewriting. (Imagine an undergrad who enthusiastically kludged together something demo-grade from numerous off-the-shelf components, and now the client "just needs someone to polish it up and extend it".) The functionality could've been recreated rapidly, and rock-solid, in a fraction of the time it would take to start to improve this code. The barrier was political, and since it was a new client, and looking like it would be a bad client, not worth the ulcers to salvage.


My guess at the problem: we all feel a sense of relief when the codebase gets smaller, but making an existing, working codebase smaller is really, really hard work. Deleting it and starting over front loads all the reward


"Deleting it and starting over front loads all the reward"

Except that you then have nothing that actually runs. So yes, no more bad code, no mess. But also no good code, except the theoretical possibility for shiny new good code.

Refactoring is usually the way to go. Can be painful as well, when you are in the middle of it and not sure if it works out (I am in the middle of it, while also switching to a different graphic engine, but I finally see the light) - but mostly you still have something that actually works. And then you can incrementially improve on it. Seperate things that should be seperated - remove things nobody uses anymore (tricky and hard to be sure). And rewrite parts, that need a clean rewrite.

With my limited energy now (or my more realistic conception of my limited energy) - that process is way more rewarding for me, than giving in to the illusion that if I just could do it from scratch, it will be all beautiful.


I enjoy coming back to re-read this article every few years, because it's one of the rare things that I continue to agree with every time.

Joel mentions the "build one to throw away" mantra, and notes that it can be dangerous, but I'd go further with that: assume the "prototype" you build is going to be the product, and it will never get thrown away and rewritten. Because that's often what ends up happening, and you (and your colleagues) will be much happier working over the next many months or years inside a project where there was at least some thought given to architecture and abstractions when it was started.

The only time where I think a rewrite might be warranted is if you, no matter how hard you profile and work on it, have realized that the framework (or even language runtime/interpreter) you have built on is just not going to give you the performance you need. Even then, you should really be sure that you can't optimize it better, even if that means digging into the framework you're using to make changes. (Digging into the language runtime or interpreter might be a step too far, though, depending on the circumstances.)

Ok, I guess there's one more time: if the architecture of the code is just so completely wrong that you can't add new features or fix issues anymore, and your velocity completely drops to zero. And you are pretty sure that starting from scratch would get you to feature parity faster than embarking upon a series of gigantic refactors. But even then, I think most people underestimate how long that rewrite will take.

But otherwise... nah, it's probably not worth it, unless you're doing it on your own time, as a toy project, for learning or just fun. I might take an old personal project written in C and decide to rewrite it in Rust because I'm sick of C, and just don't care to work on it anymore, even though there are more things I want to do with that project. Now, I'm not saying that's necessarily a good reason to do it, but if I have no professional obligations around that code, it's my prerogative to spend my time however I want.


Am I wrong in understanding that this rewrite is what produced Gecko, which is still one of the top browser engines a quarter of a century later? I really think Joel called this one wrong.


Netscape could have been as big as Google. Instead, Microsoft ate their lunch. Now, even Firefox too has become niche.

Off-topic: anyone else remember the Mozilla browser before Firefox? Remember XUL? That was with KDE and Gnome 1.x, when the Linux desktop was just round the corner. Who needs Word when you could use StarOffice....


He's giving business advice, and it's hard to argue a success from that perspective.


Netscape Navigator used to be a commercial product that people paid for. Firefox is now free and is used by so few people (me included) that a growing number of sites see no economic value in supporting it.

I think Joel's advice is holding up pretty well.


He makes an exception for open source projects. But a from scratch rewrite is one factor that killed Netscape. Wonder how many thousands of hours were burned on xul at a critical moment.


Whenever I come across these Nevers and Always, I look for the exceptions.

I mostly agree with the sentiment. Slow, incremental changes, whether to code or even a website's style. Mostly. But sometimes you run across code so malign, so neglected, so undocumented, uncommented, twitchy, troublesome, inexplicable, that the risks of the Second System Effect are worth it.

Really, I think the crucial point comes when your system is a kind of obelisk. You tiptoe around it, make offerings, but you don't know how to appease its wrath. It's like the weather.

Then it is time.


That obelisk (we call it the monolith) effect is what led to the approval in my org to take a small team and start work on replacing our nearly 25 year old pile of enterprise Java with a new codebase. I agonized over doing this, tried to fix and refactor and guide effort to just having better code, but in the end the code base has become an inscrutable, angry monolith and it's impossible to know what code improvement appeases it or triggers a series of critical production bugs.

Joel Spolsky is a smarter man than I, but his examples here are table stakes stuff compared to two decades of poorly implemented Java enterprise MVC patterns. And we don't sell software, we sell a service, and that service will continue even if our rewrite team never delivers, so the rewrite can't be more than just an expensive financial boondoggle if I'm wrong.


Something I've found useful for avoiding the ever-present urge to rewrite things: build software with comprehensive documentation and automated tests.

In my experience, the main reason a rewrite feels like a good idea is that the existing software has grown into what feels like an unmaintainable mess: changing the software in any way at all is so painful that it feels like you'd be better off starting from scratch.

Done right, automated tests dramatically reduce the cost of changing software. You can make a change and feel confident that you've not broken anything outside of the area that you're working on because the (mostly integration) test suite continues to pass.

Likewise, documentation. Without good, comprehensive documentation you quickly find that there are all sorts of areas of the project that you don't understand - which can also make a rewrite feel like it could be justified.

The catch there is that you have to _trust_ your documentation. If you (or your team) know it to be out-of-date you'll lose trust in it - so you have to get to a point where the documentation is thorough and any mistakes in it are treated as high priority bugs to be fixed.

But... if you can get both of these things in order - your automated testing strategy and your documentation process - my hunch is that rewrites will be FAR less tempting.


One greenfield/rewrite project I saw had a large team, which previously was maintaining and evolving a legacy system that the new system was to replace. (I wasn't from that team, so more on the sidelines.)

The new system was to support new requirements, have fewer legacy constraints, and benefit from using more off-the-shelf libraries and frameworks. It was more complex than it was bulky (i.e., cross-domain designs to nail, not tons of rote coding to churn). They had an aggressive timeline.

One risk you might imagine is Second System Syndrome. And there was some of that, more with everyone wanting to jam in every feature, and maybe also Analysis Paralysis on some parts the architecture.

But the biggest problem was that, collectively, that particular team just couldn't build a new system that would come together in a sufficiently timely fashion.

At least part of the problem was that management definitely dropped some balls they couldn't afford to. Had the engineers been organized better, and used more appropriate process, I don't know whether they could've risen to the challenge.


Code may not rust, but it may be broken out of the gate. Joel and others may not have seen really bad code, but it exists. All of us have written code in our careers that we're not proud of. And there's code written by people who are proud of everything they've written or code written by people who just don't care. These two are usually good candidates for rewrites.


You are right. But IMO you're still missing his main point. His thesis is in that case, to rewrite ONLY THE REALLY BAD CODE.

There is not team that is 100% bad so you don't need a full rewrite of 100% of the code base.


That's exactly it - really bad code can be refactored piece by piece.

What people rewrite is not really bad code, it's just middling annoying muck code.


Weird to suggest that a veteran of the industry might not have seen "really bad code". I cannot imagine that's true.


I think there's two kinds of bad software

The first kind was written by people who know about software, has some attempt at following some conventions, variable names, etc. etc. It's not "clean and shiny", but you can see someone tried. Like if a bunch of first year apprentices built a house. They tried their best, and often did a half reasonable job - at least for a first timer. Plenty of companies are using this kind of software to make many of millions of dollars. I would say this is extremely common in the real world.

And then there's codebases that consist of a single source file that has hundreds of thousands of LOC and that file is called indexNEW.php, indexNEWNEW.php index2022-1.php (and so on). Nobody who works on it has ever studied any kind of software course at any kind of school, and literally nobody has any real understanding of what/why/how, because it gets passed along like a hot potato everytime someone quits due to the insanity. Nobody who works on it even knows what source control is, has no idea why you shouldn't copy and paste code, and has never heard of TDD or automated testing or bullding or literally any software discipline. This isn't like first year apprentices building a house, this is like Homer building the Canyonero - an utter disgrace that just barely functions at all. [1]

I wouldn't be surprized if Joel is talking about type one, and doesn't even really consider type two to be "software" or "a system". It's just a stinking pile of garbage.

(I worked at a very large Telco. The vast majority of code plugging the systems together was type two - it was a nightmare of spaghetti so bad that when a power outage and failed backup generator took down everything (including 911), it took more than two weeks just figure out how to start everything back up again.)

[1] https://www.youtube.com/watch?v=PI_Jl5WFQkA


Do you have any examples of type two code you could link to? I want to see how bad it can get!


I mean, it's not like it's in github or anything like that - again, the people that write it don't even know what version control is.

Imagine a file with 100,000 LOC, some commented out, copies of functions like "addCustomer()" and then "addCustomerNEW()" and then NEWAddCustomer() and then "makeCustomerDanGNewest()" and so on and so forth. Absolute gong show.


A important point that programmers often overlook is that even writing a buggy but large software and managed to finished it with a lot of functionalities is fundamentally hard than a writing simple program. So unless you really are much better than them (and even so you need to make sure you are the only one actually going to rewrite it, which unlikely), you will have small chance doing better.

However there is a time rewrite is a good solution, that is when you find a lot of the functionalities the old code base provides are NOT actually needed. In this case, it is perfect (and you should rewrite it), because you are writing a much simpler software and you have a much greater chance of success.


I’ve heard from a couple people that Stripe is in limbo because they started a rewrite of their monolithic ruby app, but it stalled when the champion of the rewrite left. So now they are supporting both the new app and the legacy app in prod. Sounds miserable.


So, ah, Square (aka Block, Inc.) are currently doing precisely the same thing...


The real question is whether you’re allowed to start a rewrite of gen 2 before gen 1 is completely decommissioned.


I think as always in software, "it depends". The author appears to be assuming there are no tests on all of these paths that we will apparently miss when we migrate the code over. If so that is a problem with testing rather than migration.

Also how messy are we talking? I've seen code at a bank where a junior contractor implemented, in reams of code, his own database locking primitives, apparently unaware that the db could handle concurrent accesses on its own.

Rewrites aren't such a big issue these days, this seems a little dated. The real issue where we get painted into a corner now is architectural, say if you went really hard down the microservices route and tried to back up out of it.


I don't let myself rewrite code from scratch until I've made and reviewed an Anki deck that explores my questions about how the old coffee works. This is enough of a hurdle that I usually just end up refactoring the original code instead.


I think a good reason to start from scratch is when the language/framework/library you used turns out not to be the right tool for the job, or the general approach turns out to have major limitations.

What other good reasons can you suggest to do a rewrite?


There is another fallacy that I believe Netscape fell into at the time.

Rewrites often have the goal of "this time we are making everything perfect".

Which leads to tons of unnecessary abstractions and endless design proposals.

For Netscape 6 it was the idea of introducing XPCOM. "Classes are stupid everything is an interface".

Which later led to the "DeCOMtamination" project.

https://wiki.mozilla.org/Gecko:DeCOMtamination


I always thought it was easier to read code than to write it.


Other way around in my estimation.


I've read every line of a 300,000 line web application in less than a year working at a company. I doubt I could write that many lines of code in that amount of time.


300,000 lines of code doesn't seem unattainable for a single developer in a year. If I'm in the zone, I can easily bang out 5-10k lines of code over a weekend if I know what I want to write.

But that's the thing: a lot of development involves not writing any code, as you re-think your abstractions, plan the architecture of the next bits you'll write, debug what you've written, etc.

So I don't think we're necessarily talking about speed when we say that it's harder to read code than to write it. I think reading -- and truly understanding -- code (especially when it's someone else's, or even yours, that you haven't seen in a long time) can require quite a bit more mental effort than writing code.


Surely you jest, nobody writes a full shopping platform by themselves in a year, yet I read it and deleted all the old code that we didn't need.


Interesting. I usually think about it at a different scale; its much easier to write something small and clever than it is to read and understand it later.


What language do you use? In UI you can reach that 300k loc quite quickly.


PHP, so some of it was JS and some HTML


Yes and no, sometimes you have to shed weight and kill some older use cases to start going back fast again. But yes, maybe for smaller projects.


I keep hearing this nonsense over and over. I've led two full and very successful software 50-100K LOC rewrites, both with the team and stakeholders who had a lot of experience in the problem space. We replaced unmaintainable systems by a much fresher, MUCH faster codebase. They used largely boring and reliable technology. Rewriting 1%, 10% or even 50% would make no sense and essentially get us little or nothing.

Yes, you need to know what you're doing if you plan to rewrite anything, and make sure that the people who know the little legacy details of your system are around, but it's absolutely the right thing to do in many situations.


50-100K LOC are less than the amount of code for the build system in a couple of projects I worked on.


Then you've got bigger problems


It turns out a lot of people have a lot of problems bigger than yours.


Oh, for sure. Giant C++ projects have lots and lots of issues.

Yet, they do useful work and just abandoning them in-place and rewriting them from scratch is rarely a good solution for these problems.


You would think that it would have been standardised by 2024, but building stuff is still a surprisingly hard problem.


that's a tiny project. call back when you've got millions of lines


The thing is, there are a lot of small systems maintained by a lot of small teams. Unfortunately, when Joel wrote

“They did it by making the single worst strategic mistake that any software company can make: They decided to rewrite the code from scratch.”

some people took the “any software company” to heart and now apply the same principle even in those smaller contexts when sometimes the code really is that bad and rewriting the whole thing really is by far the best plan. I’ve seen very senior people citing the Netscape case study to support a no-rewrite position while discussing a 10kLOC system that could be rewritten from scratch in a couple of weeks by a single developer.


Generalizations are generally wrong, and I'm always right. I prefer to assess objectively whether to rewrite or refactor on a case by case basis.


I used to read joelonsoftware religiously back in 2000 and it’s pretty funny seeing this post again in 2024.


I often share this article to new team members as a part of the onboarding journey.


"As if source code rusted." - Not unless you rewrite in Rust.


I liked a quote from a No Boilerplate video [0] noting how some of the most commonly used Rust libraries hadn't had any git commits in multiple years: "They're not abandoned, they're done."

[0] https://youtu.be/Z3xPIYHKSoI?si=qHLJyUu6yqbIQUr7


Meh. I rewrilote our backend in about 3 month, and in the end of rewriting another service. All good so far!

Sometimes stuff is broken so badly you better start over


Sure do that for a few lines or even tens of thousands of lines. Don't do that for millions of lines without real serious consideration, and I'd add, a good reading of Joel's post.


Well, millions of lines, you should just create a new company.


Thanks Joel, this makes sense.


An oldie, but a goldie.


The HN story immediately above this one is "A Social History of Jell-O Salad".

A perfect pairing.


Rewriting from scratch is harder than it looks, but it all depends on how far you existing software is from your goal. Imagine that what you have is a word processor and you need a web server, surely you would start from scratch. You might say that I chose an absurd example here, but it shows that sometimes what you have is too far from what you need for evolutionary approach.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: