Hacker News new | past | comments | ask | show | jobs | submit login

Spot on.

I was 1st SE at the company I am at now. Previous applications were developed by outside contractors. I tried making some changes to that code base and found massive issues. Source code was older than the compiled application. Massive methods that were 1k+ lines long. Business rules all over the place in IF statements. Barely any documentation/comments. Only way forward is complete rewrite.

I'm a relatively fresh SE, but I read books/research good practices because I'm trying to avoid major mistakes. Also, it is hard to explain to people who even know some code, how difficult it is to make what seems like a simple form.

At this point I would refuse to work without time for unit testing/refactoring/research.

Interestingly, few days ago I made a very minor change in app I developed straight out of school. App had 0 unit testing and minimal integration testing. It created a bug, because I allowed the specs to change weekly and I just coded it without thinking. Therefore, many lessons were learned that day.




I've been a stakeholder in many a "rewrite is the only way forward" projects, though I have almost never actually advocated/voted for a "from-scratch" rewrite. I obviously say this having none of your domain-specific context -- so grain of salt -- but, in my experience, a total 'scratch' rewrite is rarely the right answer.

Furthermore, it's often nearly impossible to even be able to ascertain the 'right answer' until you've gained significant exposure to both the application & the business needs; in my experience, you'll have a far better understanding & appreciation of the architecture after a year (or three) of exposure. At that point you are much better positioned to objectively understand the potential ROI (or lack thereof) on a rewrite project vs a more conservative but concerted effort towards incremental improvement over time.

When mentoring developers on this general topic, one of the key things that I emphasize is that a functional application (even if substandard in architecture) is already solving a business need and often generating revenue/profit/positive ROI (as the case may be) for what was probably a "[re]write" project at some point in the past. Rewriting is a large undertaking with many unknowns & high costs, often higher than anticipated, and with no guarantees of reaching full functional parity in a given stated timeline. That results in difficult budgeting & ROI calculations (read: risky), and typically means the project itself is risky -- meaning the potential reward would need to be quite large to be worth it & offset the risks. I find that to rarely be the case when you already have a functional application, even if substandard. ;)


Also keep in mind that often the existing application is the only real artifact you have capturing all of the complexity and corner cases your rewrite will have to deal with.


This is a very good point and it's probably far more common than it is given credit for.

Sometimes you manage to catch some of these early on, but often they aren't caught until later in the process -- at which point the cost for the change (and the impact on budget/timeline, and potentially even the very architecture you set out to fix!) is drastically higher.

I've seen it happen a number of times where the 'spec' seemed simple enough at commencement & throughout most of the project; then you'd have each department test & the reports would start coming in... and the result would inevitably be a multiplier on the project scope.

Not from missing features mind you, but via the omission of 'complexity handling' / business logic which was documented -- but the code itself was the documentation, which isn't overly unusual (and IMO isn't even a particularly bad thing in many cases, though not all).


It's important that documentation be clear, discoverable, and up to date.

Code-as-documentation is best-in-class at staying up to date, when it comes to documenting what a system does and how. Often the relevant pieces are very discoverable as you're going to make a change. For other goals, it's much less discoverable. Clarity depends on both how the software is written and who the audience is.

Tests-as-documentation are arguably a special case of code-as-documentation. Outside of the case of well maintained tests-as-documentation, code-as-documentation often has a hard time expressing "why" and distinguishing between what has to be a certain way and what just happened to be that way.

It also has some trouble expressing aspiration - "we've decided it should be this way, but it's not yet".


Late to the thread, but just to chime in, briefly - I would agree unless the underlying platform has been deprecated.

If we're talking about something in Java that could be better, in the abstract, but it still works, agreed: it might not be worth the effort to redo. Java isn't going anywhere, and versioning differences aren't always critical.

If we're talking about deprecated front end frameworks that no longer have any LTS (Angular 1 comes to mind), moving over to a framework that does have LTS is a pretty smart move, if the code or app is that important and valuable.


In my experience it takes months of looking at existing code before you see the good architecture under the superficial mess.

In other words, work in the current code for at least a year before proposing a re-write.

Source code older the the application doesn't mean much as a statement - any good process will build off a CI system which only takes old source code. The question is how different is the application the code generates from what exists, and what to do about differences.

Massive methods are sometimes a sign that the good architecture missed something. Refactor them of course, but that doesn't mean the architecture is bad, just that it needs to change to fit current requirements.

Documents/comments lie. Their value needs to be contrasted to the risk that they mislead you. I'm not saying you shouldn't have them, just not a much as you think.

The problem with books and research is knowing when to apply them. The rules exist for good reason, but they are really guidelines not rules and sometimes they need to be broken. I'm considering that now in my application, the GUI depends on the business logic depends on the network at first glance, but looking closer I'm debating calling it fine because there is no business logic (network sends 5, business logic changes the type from int to mm/s, GUI displays 5 mm/s), so the complexity of making the business logic the thing everything depends on doesn't seem worth it. Maybe, I'm still trying to figure out where we go next, different guesses result in different optimal architectures: if we were really sure they wouldn't be guesses.

I do agree that you shouldn't do anything without creating a test. Note that test is singular, don't try to create exhaustive tests, not only will it take too long, but you often will waste time on a test that is incidental to the implementation and not required. Create a test or two around something you want to change, and then make your change. You get some assurance you didn't break anything, if you were wrong and broke something, you at least get another test out of it.


> it takes months of looking at existing code

All the while listening to management say, “this should be a one line change, why should it take more than a few hours?”


> this should be a one line change

Oh great, you do it then.


Sometimes it's completely obvious that a design decision is flawed.


And when that's true, the design decision in question is often flawed.


I disagree with the term obvious.

Sometimes it only seems completely obvious until you discover an unexpected constraint that the design decision address well. Sometimes those constraints are no longer a limiting factor and you can safely rethink the design, sometimes they are an elegant way to prevent a specific real problem and you shouldn't.


Even though the code you are interacting with appears awful, you may want to reconsider the rewrite strategy. This post may be helpful: https://www.joelonsoftware.com/2000/04/06/things-you-should-...

Consider rewriting only a handful of small parts that are causing problems critical to the success of the product, and making small improvements to the rest of it as needed over time.


This is impossible in my case, the source code is outdated. We do not have the source code of the project, which we run in production. The dev lost it.

I have tried working with the source code but it has many bugs and it appears to be two years out of date. This leaves us with an application only in its current state with no way of making any changes.

I may be able to extract pieces of information, reuse some stored procedures and so on.


At least you have something. You need to tell your boss that all features in the last 2 years need to be rewritten from scratch, with no lessons learned to speed up the effort, but that is still faster than starting over (particularly if the boss can say some things didn't turn out useful).


Would you take this approach even if the framework is outdated? Part of rewrite is to switch to a newer framework and make general improvements in maintainability, reliability and speed.


Yes. By the way - „Working effectively with legacy code”.

https://www.amazon.com/Working-Effectively-Legacy-Michael-Fe...

If you start from scratch you may bump into the same edge cases that the original writers bumped into, and end up with a code that is not much better than the original - even in the original is 2 years out of date.

I’m sure there were cases when writing from scratch was a good call, but I don’t remember hearing about it.


I guess if I do rewrite, I shall write about it as I go. If I fail it will make for a good story.


I'd emphasize that failure on a project like this may not be what you'd traditionally have in mind when thinking 'that project failed', though it happens and it could be that bad in the absolute worst case.

The issue is primarily that of the reward versus cost -- especially the opportunity cost.

When the system is rewritten, will the business have increased revenue or decreased cost? Will it do so significantly, surpassing at least the cost to rewrite (salaries, etc) -- that's the absolute minimum bar, but then you have to consider the opportunity cost which is the real concern:

If you had instead spent the same amount time adding new features, implementing an A/B test suite to increase conversions, improving marketing capabilities, retention mailers, or really any other activity that could positively impact the company business metrics -- would the impact be better than the impact of the rewrite?

In most cases the customers (internal or external) don't really know or care how good/bad the underlying code is, as long as the product serves their needs. When that's true, even partially, the value of 'rewrite' almost never exceeds the opportunity cost alone, let alone the absolute cost (and that's to say nothing of the risks).


Yes. A framework is a detail, the business logic shouldn't care. Even if the framework is tied in I'd keep using it while moving newer stuff to something else. I've been in big rewrites to change the framework and everything else, on hindsight I believe I could have done an in-place refactor of everything to the new framework and been working the whole time, at less cost.

That isn't hypothetical, in the above rewrite we took one part that was considered too essential to wait brought it in, wrapped it, and used the new framework. It was working much sooner than the other code. It still isn't completely re-written - but it doesn't need to be as the core business logic is known to work.


If it's language that has byte-code like java or .net you might be able to decompile the production binary.


Even if it's not, decompilation might be useful. What I'd try is decompiling both the running version and the build of the available source code, and see if the diff is informative.


Last time I checked x86 decompilers were not that useful.

They were producing code that is not compilable, often completely failing on more complex, translating code compiler boilerplate into code.

This was a while ago so maybe things improved since then.


The goal here is some window into "what changed". For that, we don't need "compilable", and boilerplate won't be an issue provided it's stable (by no means guaranteed, to be sure).

If I had to bet at even odds, I'd bet against it being useful. But the win is potentially large and the effort isn't.


Good suggestion.

I have decompiled the version in production. I will admit that reading it, is extremely frustrating as there are no objects and fields are named field1, field2, field3.


Still, you can compile + decompile the code you have, and compare that to decompiled production app. This might allow you to apply any cganges back to the code.

Btw, it's not a dev who lost the code, it's the company and inadequate development process. It should never have been the single dev's responsibility to make backups.


Definitely did not mean to only blame the dev. The company knows that errors were made on both sides, hence why we are working on improving the process.


Slightly relatedly, we bundle our source code into our deployable artifact along with the revision. A bit silly and it increases the artifact size, but it's just another layer in the Docker image and so it's not that painful.


At the end of the day, GP is claiming zero confidence on being able to maintain this piece of code. It's come out of their mouth as "I want to rewrite this" but what it means is "I think it would be less painful to rewrite in a way I can support than to bumble around like an idiot for 3 years in this one."

There are a lot of things you can do with that input but you really have to acknowledge that there's a pretty big problem here, and some empathy is going to be part of our path out of this mess.



Don't take the Joel On Software article as gospel (not saying that anyone is). There are other models out there as well: https://medium.com/@herbcaudill/lessons-from-6-software-rewr...


Sounds like you don't even have source control and a CI system.


You are correct.

We have implemented source control and CI is the next obvious step, but those things were not in place 10 years ago when the application was developed.




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

Search: