17 ms·
Things You Should Never Do, Part I (2000)
- zimpenfish 13y agoIf you read jwz's output, it's not that "Mozilla decided to rewrite it", it's more like "bunch of idiots who didn't know what they were doing took over and tried to rewrite things whilst ignoring all the sane advice".
- chatman 13y agoThis is esp. true for dynamically typed languages. An IDE helps a lot more deterministically for a static typed language like Java.
- randyrand 13y agoThis has always been my major complaint with dynamically typed languages. This and bad optimization - its a wonder that dynamic languages are so popular. GO is a good compromise though.
- mcphilip 13y agoI took over a large Groovy codebase that was damn near unreadable since it's controller and service layers heavily abused Groovy 'features': the def keyword (basically never defining intended types at all); not declaring return or argument types; implicit return statements; etc. My first project was to spend a few days and literally remove all possible occurrences of def and add back in return and parameter types everywhere. It was possibly the best decision I've made since it didn't involve throwing away any code and made existing code much more readable. It's just sad that the highly capable developers that wrote the original code base didn't take the extra few seconds to declare their types.
- Roboprog 13y agoGroovy 2.x makes a bit of a nod in that direction. There are annotations to turn static typing on (or off) on classes and methods as needed. This allows you to be "safe" in most of the code, and explicitly label the parts with needed "magic". I agree with you that it's probably best to limit def or type-inference-like operations to local variables within functions/methods. Tangent: I like how Go does strict typing with interfaces, but still allows duck typing of parameters by not binding classes to interfaces at class definition time.
- vorg 13y agoThe static typing features in Groovy 2 were written by just 1 person only 1 year ago, Grails doesn't use them in its codebase, and Groovy's only other user with any traction, Gradle, still ships with Groovy 1.x. Best not to trust its features until Grails does.
- Roboprog 13y agoHmm. Thanks for the tip. I've been working on trying to graft Groovy 2.1 onto an old Java app. The static type annotations don't work with Java 1.5. You have to have at least Java 1.6. (I discovered today) So, if you have Java 1.5, you can really only use Groovy 1.x language features, as well. Otherwise, it turned out to be not so hard to start putting little Groovy seeds into a Java garden, which I'm not going to rewrite as Grails. Just being able to use closures with the Groovy Collection extensions is pretty useful.
- kyllo 13y agoSay what you want about Java, its awful "kingdom of nouns" paradigm, its lack of nice functional features, etc., but it is a highly readable programming language.
- jeremyjh 13y agoI think all the boilerplate really does detract from the readability. Your eyes sort of glaze over and you can miss small departures from the boilerplate you expect to see.
- kyllo 13y agoPerhaps, but I think the fact that it's such a boilerplate-oriented language, requiring explicit type declarations, arguments, and returns, and lacking lambda expressions, it really discourages cleverness and subtlety, making it easier to read than dynamic and functional languages. It also lacks the pointer arithmetic, bit shifting, and operator overloading of C/C++ that make those languages so difficult to read. Java may be repetitive, verbose, and dumbed-down, but that definitely keeps it from being a "write-only" language. I do agree that Go is a good compromise, very readable but with less boilerplate, and probably an improvement on the Java paradigm, but the lack of generic data structures makes it kind of hard to use Go as a Java replacement.
- Gravityloss 13y agoPerhaps java is fast to read in characters per minute. But for actual functionality, I'll take something like Ruby any time.
- crucini 13y agoReally? You have trouble with code like this? RegistrarInstallationsChoicesSubclass registrarInstallationsChoicesSubclass = millisDOMX509Grow.getRegistrarInstallationsChoicesSubclass(); KeyedGSSPolygons keyedGSSPolygons = new KeyedGSSPolygons(incompatibleTransliterationNoPerfCombiningContention, iSO885915ConnectionlessAsyncDiagonal, dotDataetJDIMarshallingResourceszhObservablesDiagonal, native2asciizhDelegateEnvarLearned, insertStrategyRTFLearned); keyedGSSPolygons.addISO885915ConnectionlessAsyncDiagonal(iSO885915ConnectionlessAsyncDiagonal); AppendingGuiceJustificationMarshalling appendingGuiceJustificationMarshalling = instantiatorParenthesisForeachOutlineCounted.getAppendingGuiceJustificationMarshalling(); AdaptiveReflogMerges adaptiveReflogMerges = new AdaptiveReflogMerges(); adaptiveReflogMerges.addIishCoolbarTuple(iishCoolbarTuple); AppendingGuiceJustificationMarshalling appendingGuiceJustificationMarshalling = keyedGSSPolygons.getAppendingGuiceJustificationMarshalling(); RanksPessimisticSeparableDialFirst ranksPessimisticSeparableDialFirst = new RanksPessimisticSeparableDialFirst(native2asciizhDelegateEnvarLearned, colorizeHmacComplexJanitorEnvar); ranksPessimisticSeparableDialFirst.removeIncompatibleTransliterationNoPerfCombiningContention(incompatibleTransliterationNoPerfCombiningContention); AdaptiveReflogMerges adaptiveReflogMerges = fixerAppletPerfEs.getAdaptiveReflogMerges(); ReferencerBreakingViewersvAes256RenderingsGJ referencerBreakingViewersvAes256RenderingsGJ = new ReferencerBreakingViewersvAes256RenderingsGJ(membershipDriverConsistency, iishCoolbarTuple, sectorPartsGJForking, ranksPessimisticSeparableDialFirst); referencerBreakingViewersvAes256RenderingsGJ.addISO885915ConnectionlessAsyncDiagonal(iSO885915ConnectionlessAsyncDiagonal); DitherTWSDLGraphemeInserting ditherTWSDLGraphemeInserting = cnxnsCNTWSDL.getDitherTWSDLGraphemeInserting(); Message12DL2ExposeReconcilablePerfEditionUnaligned message12DL2ExposeReconcilablePerfEditionUnaligned = new Message12DL2ExposeReconcilablePerfEditionUnaligned(dotDataetJDIMarshallingResourceszhObservablesDiagonal, sAXXMINamessvInconsistencyAnswerLoopingCommunicatorEdition, insertStrategyRTFLearned, dotDataetJDIMarshallingResourceszhObservablesDiagonal, nIDiffuseGraphemeINAes256Kind);
- danso 13y agoI picked up the Pragmatic Programmer some time ago and among the great lessons it had, the one that sticks with me every day at the code editor is: You spend far more time reading your code than you will writing it. With that in mind, it makes it easy to write tests and more comprehensible variable names (still thinking and re-thinking how to best do documentation...was checking out github's Ruby guide and Tomdoc yesterday http://tomdoc.org/ http://tomdoc.org/)
- nahname 13y agoThat looks like noise to me. There is almost four times more code dedicated to comments than useful code. If you write unit tests it would cover/explain all these cases. I don't see the point.
- moron4hire 13y agoI agree. It would work a lot better of the function were called something like "stringRepeat" or "duplicateText" or something other than "multiplex", because that's really not what multiplexing means. Then, rename that one parameter from "count" to "repetitions" and the function is almost completely self-explanatory. Not to mention, it probably doesn't deserve to exist at all. "text * count" is simple enough that it should probably be inlined.
- nahname 13y agoComments are generally superfluous, sometimes incorrect and often used to explain away bad code.
- moron4hire 13y agoYes. I consider comments to be part of the code, and thus in need of being maintained as much as the code. The more code you write, the higher probability of defects to be written. As comments have absolutely automated 0 checking applied to them, defects in them are all but ensured.
- 13y ago
- igl 13y agoApril 06, 2000. Any progress report on this?
- trebor 13y agoThis article has been posted around 3-4 times this year alone. Most people should already be well aware of the cost of a full rewrite due to all the horror stories. Yet, sometimes the best software has come from a full rewrite.
- moron4hire 13y agoUnless the original system just did nothing of what it was supposed to do, a full rewrite being successful would be in spite of itself.
- deleted 13y ago[deleted]
- niuzeta 13y agoShakespeare is still an entertaining read after five centuries.
- moron4hire 13y agoThis article, when I originally read it 5 years ago, was hugely influential to me. It completely convinced me of the superiority of refactoring existing systems to an ideal over rewriting. It doesn't take anywhere near as much time to fix cruft as it is to create a system from scratch and try to avoid your own cruft. But it's scary and it's an unknown. But if you approach it with courage, it falls quite easily. EDIT: refactoring large systems has also convinced me of the superiority of statically typed programming languages for large projects. When I break code, I want it to break as hard as possible. I want to see absolutely everywhere function XYZ is called, and one way to do that is to rename XYZ to XYZ___ and see where all of the compiler errors show up.
- famousactress 13y agoThe article and Fowler's Refactoring book had a similar effect on me as well. Your point about statically typed programming languages is one that I've been feeling the brunt of, though I'm not convinced yet. I've been 100% python for the last few years, after a career mostly in Java and I definitely miss the sweeping refactoring abilities and hard-breaks during those kinds of refactorings. It does lend courage for sure. I'm just SO MUCH MORE productive in python for most of what I do that I'm not willing to throw out the baby with the bathwater yet. Instead I've been trying to focus on leveling up test coverage, and experimenting with Rope for refactorings ( http://rope.sourceforge.net/ http://rope.sourceforge.net/ ). I'm also slowly learning patterns for coding to make refactorings easier moving forward.. choosing code and data structures that are more easily affect-able later, or even things as simple as naming things for grep-ability.
- GyrosOfWar 13y agoModern statically typed languages (cough cough not Java cough) generally have static type inference, which removes a lot of redundancy from the code. Being able to do val object = MyObject(someOtherObject(12, "hello")) // Scala instead of: MyObject object = new MyObject(new someOtherObject(12, "hello")); // Java saves a lot of time and it just looks nicer. All the while retaining the advantages that static, strong typing have (great potential for refactoring, a lot of errors can't happen at all). Of course, there are some things that will still take up more space than they do in Python or Ruby but it's a great improvement. Languages like Rust, Scala or C# also have a good variety of functional programming tools that can make your life a lot easier.
- bguthrie 13y agoIf you absolutely must rewrite, consider isolating and replacing components piecemeal rather than scrapping the whole thing and starting over. You don't eat the whole cost at once, you can keep moving forward with new features if needed, and you get more modular architecture to boot. It's called the Strangler Pattern. http://www.martinfowler.com/bliki/StranglerApplication.html http://www.martinfowler.com/bliki/StranglerApplication.html
- prawks 13y agoAs a note, you pay for this in regression testing. Just something to consider when you employ this pattern, not necessarily a deal-breaker. If your system does not have adequate automated tests in place it can make regression tests rather ugly.
- davidtpate 13y agoDepending on the nature of your product and your rewrites in my experience a customer facing system that has parts improved in parts can be interpreted as not solving the right problems (if something UI related is being updated). The best thing I could say about it is that when approaching behind-the-scenes pieces this is my preferred approach, but for customer-facing pieces I prefer (and have had better reception on updates) to update those pieces as a whole. But again, this depends on the complexity, updating a small piece such as a button should not require a large change but updating the layout or styling would require more significant updates.
- mcv 13y agoThis is really where unit tests will save your hide. I never did any truly dramatic rewrite, but there was one project (fairly new, even) that had one very badly written, very badly understood module. I started out writing unit tests for it. There weren't any, so I wrote them until I had unit tests that tested everything. Those unit tests also document the behaviour of the module. So then I started asking people what it was really supposed to do. Then I refactored it into something more maintainable. Only after that did I change the unit tests to reflect the behaviour the module was supposed to have, and based on that I finally wrote the code we needed. The unit tests were my anchor in the storm. They keep me grounded. They mean I can do anything to the code, while keeping tabs on the impact my changes have.
- ht_th 13y agoAt first sight, this statement seems odd. For sure, writing a text is more difficult than reading it, and programming is writing a text. But a different kind of text. A program is written to communicate ideas with a computer first, and with humans second, whereas an article or novel is written to communicate ideas with humans only. What if we would have a programming language that allowed us to write to communicate ideas to humans first and have the compiler/interpreter automate the communicating with the computer? Or could it be that a non-trivial program is essentially more complex than an article or novel or any other regular text we encounter daily? Or is reading a program similar to reading a text in an unknown language? Like trying to read some Roman text when you don't really know Latin, but you've access to a Latin-English dictionary and a good grasp of history and the context and topic of the Latin text?
- derefr 13y agoReading and writing themselves are the least difficult parts of reading and writing programs. The majority of writing a program is conceiving of a well-defined model--after that, all you are doing is typing. The majority of reading a program is attempting to reconstruct someone else's conception of a model into your own brain from the typed description. Reading just the text written for the computer answers all of the "what" (as if it didn't, the program would not run), but none of the "why" -- and so makes reconstructing that model very difficult.
- jeremyjh 13y agoYes and even after you have enough working knowledge to support or enhance the code you will still find yourself continuously suprised because your model is not a perfect understanding of the author's intended model, AND the code itself is not a perfect representation of that model to begin with.
- Gravityloss 13y agoThat's why it's so nice to read higher level language code. It's more weighed towards the why and less towards housekeeping.
- semjada 13y agoSo he was wrong then? NS6/firefox seems to be doing alright today... Rewriting your OWN codebase from scratch certainly makes it get better with each iteration - as long as "from scratch" implies constantly referring to the old code.
- rythie 13y agoIn 2000 Netscape had 19.25% market share, it took 8 years to get back to that position with Firefox: http://en.wikipedia.org/wiki/Usage_share_of_web_browsers#TheCounter.com_.282000_to_2009.29 http://en.wikipedia.org/wiki/Usage_share_of_web_browsers#The...
- TheRealDunkirk 13y agoSeems to me that a lot of what Joel was complaining about could be mitigated by some well-placed comments in the code. "This function is 2 pages long! Oh, this part does that, and THIS part does THAT. I see what's going on. This is all good." This seems to be something people don't even bother to argue about any more. Everyone's given up! I don't do much myself, but no one I have worked with over the past 20 years has done ANY. Scary. I've only recently moved out of engineering to a "real" coding firm, but I'm still not seeing it. I guess coders, in general, either think that everyone should immediately understand WHY code should be doing what it's doing, or be fired, or they think it's job security to not share these details.
- pjungwir 13y agoThat's sad to hear. Part of it is an ideology that code that needs commenting should simply be rewritten. But I've written many paragraph-long (or page-long) comments, especially at the class and module level. Where comments are really necessary is to give a big picture overview how all the parts come together. Or to explain the "why". My personal theory is that comments are like chess annotations. Sure you could just read the notation, but the comments show you what is unseen, like what would have happened in six moves if white had taken that pawn. . . .
- omegaham 13y agoThis is a really insightful comment. I've struggled in the past with what the purpose of commenting is. I've written some programs where comments were the majority of the code, and it was actually more difficult to read than if I'd just left it unannotated. I've also written quick-and-dirty programs that gradually turned into behemoths, left them alone for six months, and then come back to them and felt like kicking myself for not putting comments in. I just had a crazy idea for commenting, though - I'm imagining an IDE that is built for two monitors. The left monitor is your source code. The right monitor is your comments. You wouldn't put your comments in and around the code; you'd put them into this application that would be running on the right monitor. When you select a line of source code, the relevant comments pop up on the right side. They can be as complex as you want them to be. If your class needs five pages of comments, you can put five pages of comments and not have to worry that it's going to disrupt the source code. Then, when you select something else, that comment disappears and is replaced by the comments for that line. You could even have extra monitors (or sections of that comment monitor) showing multiple things - for example, you could have the function's comments along with the line-by-line comments. Is this crazy, or more importantly, has this been done before? I think the first thing that someone will say is that it's too much effort, but it doesn't have to be used for everything. You don't need to make a five-page comment for your for-loop, but you might for your massive class that encapsulates ten objects and has forty-five functions that modify different things.
- lowmagnet 13y ago(2000)
- hvs 13y agoGreat article that is still relevant today (sadly, I remember reading it when it first came out). If you really, really feel the need to rewrite from scratch, I recommend instead picking up a copy of "Working Effectively with Legacy Code" by Michael Feathers [1]. It will give you ways to improve those terrible code bases while not throwing out the existing code. Plus you'll still get that "new car smell" of working on your code. [1] http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 http://www.amazon.com/Working-Effectively-Legacy-Michael-Fea...
- ronilan 13y agoThe rewrite meant Netscape 6 used Gecko, which brought us Firefox, which revived the browser wars, which brought us the WebKit browsers. History is a twisted mess...
- dubcanada 13y agoThe real question is would Firefox on old Netscape 4/5 engine run the same and allow them to do what they did with Firefox? Or would they have eventually rewrote it into what Gecko is today?
- yuhong 13y agoI think Mariner (the codename for the cancelled project) was supposed to be developed in parallel with Gecko.
- brudgers 13y agoIt is easier to write an incorrect program than understand a correct one. -- Alan J. Perlis, Epigram 7
- RogerL 13y agoWe have plenty of empirical evidence that you can rewrite from scratch - every competing product in the marketplace is essentially a 'rewrite from scratch' from the perspective of all the other products. Almost very start up poster on here is 'rewriting' an app in that sense. If you can't 'rewrite from scratch' (i.e. write a new app) you probably don't have very good programmers (they are only comfortable bandaiding and throwing a few routines in existing code), or, perhaps, management is tying their hands someway. So, I don't buy into the horror stories. Well, I buy that they exist, just not that they should drive my decisions. Of course, you should expect the cost of your new app to be about the same as entering the business cold. It's particularly difficult to meet every requirement/feature/bug of the old system. Orgs get fossilized around features. If you were to download and install a new IDE you'd expect it to have different features from the old one. You will miss some of the old features, but presumably the new features more than make up for it (otherwise why would you switch). Yet, when we upgrade apps, it's "remove nothing at any cost". It doesn't necessarily make a lot of sense. It can take enormous effort to re-implement some broken feature as opposed to just offering a new way to do things. None of that is to say I blithely throw code away. I did, once, amidst a bunch of hue and cry of 'oh no', but it was the correct decision because the old system was hacked together by 'weekend programmer' (my boss at the time who was very smart but learned programming from a book). I turned it into a modular, decoupled system, and most of those parts got reused over and over in different parts of our vertical. If you have a plan, and the old code doesn't, it can pay off. There's more to be said, but this is a wall of text already. Every day I work in the refactor mode, even while mostly adding new features. Its an extremely powerful idiom. But I also have my eye on code that really needs to go to the big bit bucket in the sky. No one understands it, every fix introduces new bugs, and what it is trying to do is very well served by existing open source code, or code be written from scratch.
- samatman 13y agoThe key sentence you buried there is "It's particularly difficult to meet every requirement/feature/bug of the old system". Because that is precisely the point that Joel is trying to make. My whole job consists of doing that for code that will never, ever be 64 bits or multicore, and therefore had to go. But it is painful. Avoid it if possible.
- kbd 13y agoThis is from 2000. People need to stop posting old articles without putting a date in the title.
- mattlutze 13y agoRelevance and recency are not always directly proportional.
- romaniv 13y agoThis is the most overrated and overquoted piece of (bad) software engineering advice ever. Sure, it's harder to read unfamiliar code than write new code, because your understand the reasoning behind the new code. That's exactly why rewrites often make much more sense than labor-intensive incremental changes. I've had many real-life situations where I successfully chain-deleted thousands of lines of legacy code and replaced it with some sub-100-line method that simply worked. All that without understanding how legacy code works. You're wondering what's the secret here? Instead of trying to deduce the undocumented logic behind legacy code I gathered current requirements and implemented them in the simplest way possible. In most cases the results were dramatically more readable, because I used build-in language capabilities and standard libraries whereas old code spectacularly failed to do so. Also, I didn't have to worry about requirements that were no longer relevant.
- jbert 13y ago> I gathered current requirements and implemented them in the simplest way possible. If you can get complete current requirements, that's fine. The issue with this is "all the stuff which falls through the cracks". In the example from the post, some code to "handle case where internet explorer is not installed". That the sort of thing which would often be missed in requirements gathering, discovered in the field and then patched into the codebase. Sure - if you have one of: * close-enought-to-perfect requirements * close-enought-to-perfect regression tests then a rewrite isn't too hard. But achieving either of the above is something I'd consider a hard problem. Do you have a particular way of getting signoff that your current requirements are "complete"? That would be worth knowing :-)
- kyllo 13y agoYeah, my favorite definition of "legacy code" is "code that has poor test coverage." The regression test suite should literally implement all of the business requirements, and then the two become the same thing (if there's no test for it, it's not a requirement, and vice versa), so then you can work on the codebase with confidence, and it's therefore not legacy code, no matter how old it is or what old school language it's written in.
- 13y ago
- kailuowang 13y agoI always deem readability the number one priority in writing working code. Readability is not just about understanding what the code in front of you is doing but also easiness to find where in code a particular business logic was implemented. Code written with readability as the top priority has the best chance of avoiding the need for a full re-write. And even if it needs to be re-written from scratch, it's so much easier with a readable codebase.
- GVIrish 13y agoOne of the huge pitfalls in the writing from scratch situation is that often times the original application didn't have adequate requirements. So the team sets about building the new version without a comprehensive and detailed understanding of what the old version did. That alone can lead to huge timeline and cost overruns. And if your organization didn't learn from its mistakes the first time around, it'll make many of the same mistakes the second time around, except this time they'll be concentrated in one monster release rather than a number of smaller releases. Especially if the original developers have left.
- shubb 13y agoThis is an interesting article because though the rewrite killed Netscape, the rewrite became Firefox, possibly the most popular browser in the world. It became that way because developers were able to run laps round Microsoft (who clung to an old, bad codebase). And because it was a redesign not just a rewrite, and the redesign redefined what browsers did. Firefox, as we use it today is a rewrite of that rewrite, with god forbid far less features than the original! I wonder, with a little more money behind Netscape, and without anti-competitive MS browser bundling, would Joel's piece look so correct in hindsight?
- outworlder 13y agoWe have no way of knowing that. But I can imagine we'd living in a very different environment, had Netscape succeeded.
- hkarthik 13y agoI remember using IE when they started bundling it with Windows and it was a FAR better experience with instant loading instead of waiting Netscape to load. Everyone likes to blame the bundling of IE as causing Netscape to fail, but in reality, the initial versions of IE just worked better. Netscape's engineers knew this, and probably realized they had to rewrite to compete with the speed of IE. Interestingly enough, these days hardly anyone I know uses IE or Safari even though both are bundled with their respective operating systems. Most of these folks install Chrome because they are familiar with it and it doesn't impose any significant performance penalty. Ideally, Netscape should have been optimizing their browser for speed all along. But since they were the only kid on the block for so long, they became numb to how slow things had gotten. It took IE coming in with a much better experience to shake them into action. Unfortunately, by then it was too late for Netscape as a business to recover.
- emiliobumachar 13y agoFor your information, The bulk of IE loading happened during Windows boot. The user just wasn't informed of it. I don't know whether Netscape could have done the same and didn't, or whether it required some inside access to Windows.
- lxe 13y agoI know I don't have the expertise to argue with Joel Spolsky about software engineering, and while I agree that rewriting from scratch is a huge strategic mistake, it is hardly the worst. Have any of you ever worked for a large engineering firm with a sizable operating budget? There are many "strategic" errors that happen on the daily basis in those kind of shops that range from software stack choices to engineering process drowned in bureaucracy. Rewriting code is hardly the worst. Also, don't assume that even though rewriting code is bad for business, it's bad overall. You iterate, and learn from mistakes you made that were caused by the lack of experience at the time previous code was written. You de-couple components during a rewrite and eliminate unnecessary features, drastically improving maintainability. You make it easier for other programmers (and yourself) to read the code. You can alter core platform pieces, make tech stack alterations, and eliminate reliance on legacy components during a rewrite. The list goes on...
- freework 13y agoIf I had superpowers that allowed me to delete one website from the in internet forever, it would be this article. I find the "complete code rewrite" to be the most powerful programming technique I have in my repertoire. In 2007 I wrote an application called FlightLogg.in. It was basically a clone of logshare.com that I wrote in my spare time with PHP. It was my first really 'big' project. You can see the code here: https://github.com/priestc/old-flightloggin https://github.com/priestc/old-flightloggin If you look around that codebase, you'll see nothing but spaghetti. I starting writing the app in late 2007, back when you could say I was a 'noob' (so noobish in fact, I didn't even use source control). At the time I thought I was writing the most awesome code ever. By the middle of 2008, that project had reached a state where it was pretty much 'done'. I then stopped working on that codebase, and moved on to other projects. Then by late 2008, FlightLogg.in's traffic had kept growing, and there was a list of bugs and really cool features that I had thought up since I last touched the codebase a few months earlier. I set out to continue development on the PHP codebase. The problem was that in the past few months I've been away, I had become a better programmer, and the sight of that spaghetti code made me vomit. It was less about the code being 'bad', and more about me not remembering how things worked. The small set of fetures and fixes I wanted to make would have taken me a few hours to do back when I was first working on this codebase. Since a few months time had passed, it was taking me much longer. Eventually I decided to do a complete code rewrite. This was before I ever saw that Joel Spolsky article. The new codebase is here: https://github.com/priestc/flightloggin2 https://github.com/priestc/flightloggin2 It took me roughtly the same amount of time to build the new codebase as it did the old codebase. Ever since, each and every project I take on, I accept the reality of doing a complete code rewrite might come up. For my own personal projects, I do complete code rewrites all the time. On the other hand, at the various jobs I've had over the years, its a much different story. If I came into work today and brought up the idea of doing a complete code rewrite, I'd either get laughed out of the room, or even worse, threatened with being fired, thanks to this Joel Spolsky article. Thanks Joel.
- oblio 13y agoPersonal projects are one thing. But company projects involving more than 3 programmers? Forget it! He's right about these projects - you shouldn't rewrite them. First of all the experienced people will probably move on, secondly business pressures will never allow you to do things "just right". I can't tell you how many rewrites I've seen fail, compared to the handful of rewrites that actually achieve their goals. And this is a very risky proposition for a company.
- bluedino 13y agoHow does this apply to a platform change? Say, going from an application written on 80's UNIX hardware that's still going strong today on a 9-year old Itanium system? Start writing replacements for individual modules? The original programmers are set to retire in another 5 years and then it's going to get really, really ugly.
- drderidder 13y agoThere's a time and place for everything. Firefox and Mac OS X are examples of successful rewrites. I've had some positive experiences with re-writing certain things from scratch. Not to downplay the issues Joel raised back in 2000, but if a product is tied to a technology that's limiting its effectiveness, and better alternatives have become available, a next-generation implementation bears consideration. I think companies that fail to iterate and evolve this way will ultimately stagnate.
- etler 13y agoThe new historical perspective on this is very interesting. The code rewrite killed the company, but it gave birth to mozilla, which came back to topple IE from its throne and help bring through a new renaissance of browser development. If they hadn't rewritten their code how would have history changed? Would we be where we are today? How many years behind would that setback have put us? The release of Firefox was instrumental at disrupting and evolving the web. With a poor code base could they have done that as effectively as they did? A company may be transient, and killed by choices that hurt them in the short run, but will support them in the long run. But good open source code is eternal. The quality speaks for itself. Their decision may have killed their company but it was astronomical for the web. From a higher level perspective, they did the right thing, and it shows that good code is so powerful, it can even outlive the company that made it.
- masswerk 13y agoOn the other hand it was particularly for this stand-still of NS, why IE was on the throne. And this made HTML/JS effectively a proprietary standard, which brought web development eventually to a stand-still also. When open standards enforcing browsers finally became available (and – saying this as a once ardent NS-follower* – what a buggy mess NS 6.0 was in the beginning!), it was essentially a political question, whether they would succeed or not (as they were incompatible to most of the existing web code base). *) I used to code NS4.x-compatibility and open standards calls then, even, if I wasn't able to bill for these as clients were only interested in "does it work on IE, so it's fine".
- cehlen 13y agoCode may not rust overtime but it does become harder to maintain and more importantly harder to find quality innovative people willing to work on it. I would guess that very few of the people making a pro argument for Joel Spolsky’s article would be willing to support 1970’s COBOL banking software for a living.
- eldavido 13y agoThis article shows how much progress we've made in languages and tools over 13 years. It's vastly more difficult to read large, c++ codebases with tons of memory allocation, pointer arithmetic, macros, and complex locking schemes than much of the Java/Ruby/other mainstream language code written today. Also, it strikes me that this was written in an era where most large-scale systems were giant monolithic codebases sharing an address space, rather than distributed groups of services communicating over a network. Distributed systems are inherently easier to rewrite because a lot of the hard problems around abstraction, state, representation, etc. already have to have been solved by the architecture -- you can't exactly pass a naked void* over the wire.
- yuhong 13y agoAn example is legacy color parsing. I personally figured out where legacy color parsing is in the Netscape classic source: http://stackoverflow.com/questions/8318911/why-does-html-think-chucknorris-is-a-color/12630675#12630675 http://stackoverflow.com/questions/8318911/why-does-html-thi... It is so subtle even Netscape's own Gecko rewrite did not get it completely right the first time: https://bugzilla.mozilla.org/show_bug.cgi?id=121738 https://bugzilla.mozilla.org/show_bug.cgi?id=121738
- ryanackley 13y agoYou usually only hear the catastrophic failure anecdotes. Large, complex, yet successful rewrites I know about: * The Windows kernel. From my understanding, Windows NT was a completely different kernel from Windows 95 and eventually replaced it in Windows XP. * Coldfusion, I used to work with an ex-Adobe guy that told us the story how this was rewritten from scratch at one point. From C++ to Java * I used to work on the SQL Server team at Microsoft. We completely rewrote the Reporting Services product between the 2005 and 2008 releases.
- masswerk 13y agoWindows NT was an incremental update to what would have been the next VAX-OS. (As for my humble knowledge.) See "Dave Cutler and Windows". But another good example for a very successful rewrite would have been Adobe's ActionScript for Flash 5 (turning to an ECMA-script-like language).
- to3m 13y agoWindows NT development started around the time of Windows 3.0.
- powertower 13y agoDoes anyone have a good way to distinguish between - A) Rewriting the codebase. B) Fixing & modularizing the codebase - breaking it up into self-contained units/parts while improving, cleaning, and modernizing them? Because if you throw away the edge-case of completely starting from scratch, B) can easily be seen as A) and vice versa. Is there a thin line here? (*I have a 200K line C#/.NET app that will be evolving and pivoting with it's next major version).
- YZF 13y agoIt's not black and white. There are situations where investing in your old code base is throwing good money after bad and there are situations where the old code base can be better. You need to make educated decisions not blindly follow rules. Refactoring can be a problem because you're always working towards some local minima. It's a little bit like the decision to renovate an old house vs. raze it and build a new one or buy an old car/boat and repair it. There's a good discussion of various factors here: http://programmers.stackexchange.com/questions/6268/when-is-a-big-rewrite-the-answer http://programmers.stackexchange.com/questions/6268/when-is-...
- mtdewcmu 13y agoI can't imagine how a codebase could be so horribly bad that it doesn't do even one thing right, and you have to throw it out wholesale. That is, assuming it was good enough to ship at some point. I don't like to feel that I'm wasting my time doing rework, and vulnerable to getting in way too deep with no backup plan. I'd definitely want to rewrite in pieces without ever discarding the whole, even if eventually there might come a day when every single piece has been rewritten.