When is it the right time to rewrite code from scratch?



  • Continuing the discussion from MyWTF:

    @Bulb said:

    A programmer who creates a class named MyFunctions should be shot on the spot. In our case it actually most likely was the founder (who lost the company to the single worst strategic mistake).

    According to Joel, the Single Worst Strategic Mistake is rewriting code from scratch.

    Here's the thing, though... I've seen code units (classes, etc...) that are so poorly written that I thought there was more value in rewriting the majority of it from scratch with the exception of specific business logic that is copied into the new version.

    So, when exactly is there more value in rewriting something instead of attempting to modify what's already there?



  • I think there is a difference between a refactor that might replace a few classes and a complete rewrite.
    Doing a rewrite usually entails trying not to repeat previous mistakes (which is good) but also usually leads to over-engineering (which is probably bad).
    If I can rewrite something in a single change, then I'll go for it. If it is going to be gutting something out and likely have 2 versions co-existing then it will probably be out of scope and result in a tail of unexpected regressions.
    I'd probably prefer to deprecate something than to rewrite an existing program.


  • Winner of the 2016 Presidential Election

    @powerlord said:

    So, when exactly is there more value in rewriting something instead of attempting to modify what's already there?

    One day before you leave the company?

    Filed Under: :trollface: 🚎


  • I survived the hour long Uno hand

    @powerlord said:

    when exactly is there more value in rewriting something instead of attempting to modify what's already there?

    When the technology or language it was written on is no longer supported.

    We're moving CF8 code to Node.js instead of continuing with Coldfusion (which is on...11? 12?), which entails a complete rewrite.



  • This particular case was a textbook example of the single worst strategic mistake.

    The company had a product. It was cobbled together with out much architecture and a lot of work was done by interns that left afterwards, but the code worked and while it had it's problems, it certainly was amenable to piecewise refactoring.

    However the owner managed to hire a “programmer” with a really bad case of NIH syndrome and that individual persuaded the boss to do a rewrite from scratch. Back then the only platform was Windows CE and the rewrite included:

    • Writing his own rendering engine (ok, the natively available bits were a bit limited).
    • Writing his own basic data structures, because “I don't trust what I don't write myself” includes std::vector and such: “we had problems with std::vector so we better not use it” (the problems were caused by somebody using std::vector<std::vector<something>> and not minding the complexity of insert).
    • Writing his own wrapper for files, because of complete misunderstanding of what “stream” means (we still have a class named Stream for use in code we didn't manage to fix yet that is in fact an in-memory buffer).
    • Writing his own memory allocator to check how much memory we use.
    • Writing his own math library, because floats are slow.

    The other problem was that the individual had absolute lack of understanding of complexity. So while he was talking about not using floats (I am sure it is slower, but done few enough time it is inconsequential) while writing own string class with linear extension (of course one day we ran into case where composing longer string was absurdly slow from all the reallocating and copying).

    The one think that kinda sorta somewhat makes some sense is the GUI framework with definition of widgets in XML compiled to some binary blob and a mechanism for defining which functions should be called in response to events, because portable GUI frameworks are still in short supply. Except:

    • The tool for designing the layout is utter crap.
    • We added some scaling ability, but it still sucks and we need bunch of separate definitions for various sizes anyway. And the definitions are separate, maintained kinda sorta consistent by having a feature in the designer that allows changing corresponding property across the multiple definitions.
    • It contains a turing complete “language” for calling the entry points to the core application that is, obviously, pain to work with (only function call with arguments, only string or integral values, blocks have to be named…).
    • It was intended to help customizing the application for different customers, but it mostly failed at that anyway, due to complete lack of ability to build abstractions in it.

    I, along with several colleagues, was hired for this rewrite at the time our previous employer was letting go many people. For that previous employer we also did a GUI framework for WinCE, except it:

    • didn't have ambition to define the binding to logic—it generated C++ classes that were derived to define that and
    • had support for derived dialogs, a functionality that I haven't seen in generic frameworks, but was very handy for dialogues on mobile devices where a bunch of menus repeats similar layout all over again.

    Unfortunately that bit was already written when we were hired, so we had no saying in that.



  • @Nprz said:

    Doing a rewrite usually entails trying not to repeat previous mistakes (which is good) but also usually leads to over-engineering (which is probably bad).

    Doing a rewrite without looking at the previous code, as was our case, leads to repeating previous mistakes and doing many more due to over-engineering. And when combined with bad case of NIH, it is textbook recipe for disaster.

    @Yamikuronue said:

    When the technology or language it was written on is no longer supported.

    C++ is still supported, it is the only language in which it can be done given the target platform and performance requirements and both the previous and the new versions are in C++.

    Yes, I agree that moving from obsolete, crappy platform to new and hopefully less crappy platform deserves it. Definitely not our case.



  • @Bulb said:

    A programmer who creates a class named MyFunctions should be shot on the spot.

    I did that, but it was like my first assignment out of college.



  • I understand naming is hard. However the textbooks that all feature examples sporting contrived subclasses named MySomething don't help the cause.



  • The problem is ending up with a standalone set of utility functions and not knowing where to put them, so you throw them in a static utility class.



  • @powerlord said:

    I've seen code units (classes, etc...) that are so poorly written that I thought there was more value in rewriting the majority of it from scratch

    The article by Joel isn't talking about rewriting a segment, but the entire project. Redoing a class or library is different from burning the whole thing to the ground and salting the earth it stood on.

    @Yamikuronue said:

    When the technology or language it was written on is no longer supported.

    Things should have been broken into libraries that you can call from other languages. If they weren't then first refactor the existing program into some libraries so you aren't throwing them away. Then over time you can replace these components one at a time without having to go completely from scratch, you still have something that works while the rewrite is being done (though this is after the refactoring/architecting of the original).



  • I've seen it happen twice to two different large codebases at two different companies. One time it was because a major shift in quality attributes (going from large batch jobs to small jobs with requirements on high throughput), and the other time it was because the codebase had been so optimised for one particular requirement that when that requirement changed (from read only to read/write) they decided to shift to a completely new codebase. In the second case they also moved from C to C++.



  • @locallunatic said:

    The article by Joel isn't talking about rewriting a segment, but the entire project.

    Well, I was part of a project to rewrite a platform.
    It required the users to rewrite code, but it reduced the amount of code they had to write from 100+ lines to 10-20 lines, without reducing the feature set.

    All we did was make the feature set more uniform, and simply exposed the C+ methods on classes to the proprietary version of COBOL the company was using, by simply allowing someone to serialize method calls into strings, and using reflection to determine the method being called.

    It worked well and was actually faster than what we had before, all for a lot less code.



  • @locallunatic said:

    The article by Joel isn't talking about rewriting a segment, but the entire project. Redoing a class or library is different from burning the whole thing to the ground and salting the earth it stood on.

    I would love nothing more than to do a complete rewrite on the web application I'm currently working on (using raw Java Servlets and JSP, manually writing JDBC database calls, etc...) but I'm not actually allowed to do that.


  • ♿ (Parody)

    @Bulb said:

    This particular case was a textbook example of the single worst strategic mistake.

    I think you're now competing with @Arantor and @Weng for most WTFy workplace.



  • @locallunatic said:

    The article by Joel isn't talking about rewriting a segment, but the entire project. Redoing a class or library is different from burning the whole thing to the ground and salting the earth it stood on.

    Well, it mentions rewriting segments. As the correct approach instead of throwing the whole thing out of the window.

    @locallunatic said:

    Things should have been broken into libraries that you can call from other languages.

    I dream of a world where I can write a library in arbitrary language and, without much pain, call it in other language. It is a nice dream, but it unfortunately has very little resemblance of reality.

    @Mikael_Svahnberg said:

    In the second case they also moved from C to C++.

    Since C++ includes C, this is not the case where switch of language warrants a full rewrite.



  • When you have the time/funding to actually pull it through to the end.

    Usually, you don't.


  • ♿ (Parody)

    About the only time I would justify (outside of unsupportable stuff) would be if the requirements were drastically changing. IOW, whatever the users were doing is no longer what they are doing and adapting the system to the new reality is actually worse. In this case, a lot of the old workarounds and quirks are getting thrown out, too.

    Joel's advice is an application of Chesterton's gate to IT systems. We should apply it more often.



  • @Bulb said:

    I dream of a world where I can write a library in arbitrary language and, without much pain, call it in other language. It is a nice dream, but it unfortunately has very little resemblance of reality.

    Oh there will be pain. Sometimes you may even need to make them small command line programs to fake library calls if the original language is awful and the new one isn't much better, but the point is not to throw the old work away.



  • Which is kinda the case I was talking about.

    Instead of the requirements changing, the workload on the users was being reduced, by a magnitude or more.

    Of course, they didn't want to retrain, so I don't know if it is even being used, and that's ironic given that they kept harping on their application layer being simple enough that a high school dropout could program on it.

    But we had an example program converted, and it ran faster, with 90% less code. The platform had a trivial amount of code compared to before, the middleware had double the code, and the app layer had a trivial amount of code as well.

    Yet, the company owner was proud of introducing millions of lines of code to their product every year.
    Because in his mind, lines of code had a direct X to 1 translation into usable features



  • @boomzilla said:

    I think you're now competing with @Arantor and @Weng for most WTFy workplace.

    No. The individual fortunately screwed up and was sacked, coincidentally at the moment the company was sold.

    The new boss at the beginning was, despite working in software development for quite some time already, showing serious lack of understanding of the efforts involved and generally how things can and can't work, but fortunately at the time our team leader (who came from the same company as I did and unfortunately left since) was experienced and managed to put things on workable track.

    So now we have some crappy legacy code, but much of it we managed to gradually improve or at least fence off and it is still a bit cowboy operation, but it mostly works fine.


  • :belt_onion:

    @powerlord said:

    According to Joel, the Single Worst Strategic Mistake is rewriting code from scratch

    What is the definition of "from scratch" being used here?

    As in literally delete the old code and don't look at it at all to help determine how to make the new system better? Because that would be a stupid mistake.

    I might not be editing the original or even remotely adhering to design patterns or logic from it, but I'm not going to ignore it altogether.



  • I think it means, no reuse.

    You can look at it, but you can't reuse anything from it.

    If you reuse parts, then you aren't rewriting from scratch.



  • @Bulb said:

    Since C++ includes C, this is not the case where switch of language warrants a full rewrite.

    No, they just took the opportunity while they were at it. The changing requirement was the primary driving factor for the rewrite.

    Mind you, neither of these were small rewrites of just a few classes - the entire codebase was completely rewritten, because it was decided that this was cheaper than trying to locate all the dependencies and places with assumptions about the (quality) requirements.



  • Never.

    If you can't refactor it, you need better tools.



  • @Bulb said:

    I dream of a world where I can write a library in arbitrary language and, without much pain, call it in other language.

    Both .NET and JVM offer this.

    Not sure it'll ever be possible without some sort of underlying VM, though. C++ seemed to have the delusion that they could pull it off, but.

    @boomzilla said:

    Joel's advice is an application of Chesterton's gate to IT systems. We should apply it more often.

    It also reminds me of JWZ's article about how Netscape hired a bunch of "rockstar" new programmers who immediately tore out his email threading code and tried to write their own, which repeated all of his mistakes and bugs and never worked as well as the original. IIRC that's what prompted him to leave Netscape.



  • @blakeyrat said:

    Never.

    If you can't refactor it, you need better tools.

    Not even if it's written in <insert unsupported language here>, doesn't meet a single requirement the business now has for it, and is total spaghetti code on the inside because the language in question provides practically no support for abstraction of any sort?



  • @tarunik said:

    doesn't meet a single requirement the business now has for it

    How do the requirements change that much without updates being applied beforehand. I know it could happen in theory, but in the real world requirements mutate not just get replaced.



  • @locallunatic said:

    How do the requirements change that much without updates being applied beforehand. I know it could happen in theory, but in the real world requirements mutate not just get replaced.

    Unlikely, but possible -- the system may just not be able to evolve fast enough to deal with the rate of requirements changes coming in. More likely is that the old system makes deep-seated assumptions about certain things that a changed set of requirements proceeds to violate, making refactoring much trickier. (Imagine having to take a 50s COBOL line-of-business app and make it work with Unicode, through and through.)



  • @tarunik said:

    Not even if it's written in <insert unsupported language here>, doesn't meet a single requirement the business now has for it,

    Then you throw it away and make a new project from scratch. If it doesn't meet a single requirement, why are we even discussing this?

    Come on, people, if you're going to ask hypothetical questions, make them non-stupid.



  • You said never -- so I went into full counterexample mode. Don't use absolutes when you don't mean 'em.



  • Oh right, pedantic dickweedery. It's been awhile.



  • @blakeyrat said:

    Both .NET and JVM offer this.

    I can use Java library from C# or vice versa? That's news to me.

    The VMs allow it between languages running on those respective VMs and carefuly designed to have the same object system. In JVM, everything is derived to match the Java object semantics and in .NET C# and VB are basically different syntaxes for one language.

    It does nothing to allow calling Perl libraries from Ocaml, Haskell libraries from Ruby, Smalltalk libraries from Common lisp and similar.

    @blakeyrat said:

    It also reminds me of JWZ's article about how Netscape

    That also makes one of the prominent examples in the Joel's article.



  • @tarunik said:

    Imagine having to take a 50s COBOL line-of-business app and make it work with Unicode, through and through.

    And? That isn't your doesn't match a single requirement, that is change how it handles characters through and through. Which is significant I'll give you that, but it doesn't remove whatever business logic that should be applied to things the program is working on.

    @tarunik said:

    You said never

    Specifically he said never in reference to rewriting a program from scratch, with none of the same requirements that isn't the same program.



  • @Bulb said:

    I can use Java library from C# or vice versa? That's news to me.

    Nobody's stopping you from making a Java that compiles to .NET.

    @Bulb said:

    It does nothing to allow calling Perl libraries from Ocaml, Haskell libraries from Ruby, Smalltalk libraries from Common lisp and similar.

    Nobody's stopping you from implementing any of those language in .NET.


  • ♿ (Parody)

    @blakeyrat said:

    Nobody's stopping you from making a Java that compiles to .NET.

    Nobody's stopping you from punching yourself in the face.

    How to Condition Your Face – 03:03
    — EnterTheDojoShow

    This is terrible pedantic dickweedery.



  • The CLR's type system isn't rich enough to support Haskell. It can just about support the Haskell 98 standard now. Maybe in 5-10 years, it will be able to support the Haskell 2010 standard.


  • FoxDev

    @Bulb said:

    I can use Java library from C# or vice versa? That's news to me.

    Java can consume COM objects, which can be written in any .NET language; not sure if you can do the reverse, but I wouldn't be surprised if you could


  • FoxDev

    @Captain said:

    The CLR's type system isn't rich enough to support Haskell

    That's like saying it's not rich enough to support lists or stacks. Which can be found in System.Collections.Generic.



  • Huh? Haskell's type system is significantly more expressive than the CLR's. The CLR isn't capable of doing the kinds of type inference and type checking Haskell compilers do.


  • FoxDev

    The CLR doesn't do type inference; that's a language feature, not a CLR feature


  • ♿ (Parody)

    @RaceProUK said:

    Java can consume COM objects

    Meh...I could just write stuff in both that communicated solely by stdout/in and then we could all call each other<jerks, call each other jerks>.


  • FoxDev

    You could do it with any one of the millions of ways of doing IPC too; that's not the same as running it all in the same process, which COM interop allows


  • ♿ (Parody)

    Yeah, if I run it in WINE.


  • FoxDev

    I glad this time you're bringing up genuinely interesting points instead of yammering blindly about shit that doesn't matter since we're clearly talking about something else



  • I glad

    I'm glad...


  • FoxDev

    😛

  • ♿ (Parody)

    @RaceProUK said:

    I glad this time you're bringing up genuinely interesting points instead of yammering blindly about shit that doesn't matter since we're clearly talking about something else

    Hang on...you're saying this?

    :caughtwithmypantsdown:


  • FoxDev

    Someone asked 'Can I call between Java and C#'.
    I said 'Yes, via COM'. This is a direct answer to the original question.
    Then you bring up Wine, as if it's relevant.


  • ♿ (Parody)

    @RaceProUK said:

    Then you bring up Wine, as if it's relevant.

    Oh, shit, I even missed the sarcasm, because I was serious and I thought you were, too (I thought you were complaining about something else). Yes, you figured out a small corner case. Huzzah! That won't work for me, as I explained. How is that less relevant than your comment?

    I am still enjoying irony the lecture.



  • @RaceProUK said:

    You could do it with any one of the millions of ways of doing IPC too; that's not the same as running it all in the same process, which COM interop allows

    It still requires writing a lot of glue. Enough glue that people still find rewriting stuff in yet another language preferrable.


Log in to reply