Refactoring gets really bad reviews, but from where I’m sitting as a hobby programmer in relative ignorance it seems like it should be easier, because you could potentially reuse a lot of code. Can someone break it down for me?

I’m thinking of a situation where the code is ugly but still legible here. I completely understand that actual reverse engineering is harder than coding on a blank slate.

4 points

Refactoring is good work. Rewriting is shallow fun.

Do the math.

Exception: perl is write-only code. Always rewrite.

permalink
report
reply
2 points

Responding as a java/kotlin maintainer of one single large system with frequent requirement changes. what i call “high entropy” programs. Other developers have different priorities and may answer differently based on what kind of system they work in, and their answers are also valid, but you do need to care about what kind of systems they work on when you decide whether or not to follow their advice.

In my experience, if the builder of the original system didn’t care about maintainability, then it’s probably faster to rewrite it.

Of course, then you’d have to be able to tell what maintainable code looks like, which is the tricky part, but includes things like,

  • Interfaces
  • Dependency injection
  • Avoidance of static or const functions
  • Avoidance of “indirect recursion” or what I call spaghetti jank that makes class internals really hard to understand.
  • Class names indicate design patterns being used. Such as “Facade”. This indicates that the original builder was doing some top-down software design in an effort to write maintainable code.
  • Data has one, and only one, source of truth. A lot of refactoring pain comes from trying to align multiple sources of truth, since disgreements cause mayhem to the program state.

Bad signs:

  • Oops, all concrete classes.
  • Inheritance. You get one Base Class, and only one, before you should give the code the death glare. Its extremely difficult for a programmer to be able to tell a true “is a” relationship from a false one. For starters you have to have rock solid class definitions to start with. If the presence of Inheritance smells like the original builder was only using it to save time building the feature, burn it with fire! Its anti-maintainable.
  • Too much organizing - you have to open 20 files to find out what one algorithm does. That’s a sign that the original builder didn’t know the difference between organizing for organizing sake and keeping code together that changes together.
  • Too little organizing - the original builder shoved eveything into one God class so they could use a bunch of global variables. You’d probably have a hard time replacing a component so big. Also, it probably won’t let you replace parts of itself - this style forces you to burn down the whole thing to make a change.
  • Multiple sources of truth for data: classes that keep their own copies of data as member variables are a prime example of this kind of mistake.
permalink
report
reply
1 point

Neither.

If you can code it in a week (1), start from scratch. You’ll have a working prototype in a month, then can decide whether it was worth the effort.

If it’s a larger codebase, start by splitting it into week-sized chunks (1), then try rewriting them one by one. Keep a good test coverage, linked to particular issues, and from time to time go over them to see what can be trimmed/deprecated.

Legible code should not require “reverse engineering”, there should be comments linking to issues, use cases, an architecture overview, and so on. If you’re lacking those, start there, no matter which path you pick.

(1) As a rule of thumb, starting from scratch you can expect a single person to write 1 clean line of code per minute on a good day. Keep those week-sized chunks between 1k and 10k lines, if you don’t want nasty surprises.

permalink
report
reply
1 point
*

Legible code should not require “reverse engineering”, there should be comments linking to issues, use cases, an architecture overview, and so on. If you’re lacking those, start there, no matter which path you pick.

Yeah, I just added that bit in to keep away the “ACKTUALLY if it’s written UNIVAC III assembly you have to rewrite it” answers. Technically correct, but not what I need.

There’s no practical problem I’m immediately facing here, I just didn’t understand some of the opinions I was hearing and was curious. (All my hobby projects are either new software from scratch or adding features to existing code, right now)

permalink
report
parent
reply
1 point

Makes sense. As for the opinions, over time people end up cussing the same tools that were introduced to fix their previous problems, all tools can be misapplied 🤷

permalink
report
parent
reply
2 points

From a professional perspective I’d say: don’t rewrite if you’re unsure about it. Rewrite if there’s a particular problem you need to solve and a rewrite is the only way to do it.

For example, you need to make major changes in the tech stack. Like switching from PHP to NodeJS. This is difficult to do without a complete rewrite.

Rewrite for the sake of rewrite is usually a waste of time, and it’s not certain that the code will turn out better in the end. You might end up with a similarly convoluted system either way. And the worst part is: now you have two systems to maintain at the same time.

Likewise, refactor if there’s a particular problem you want to solve. Don’t refactor just for the sake of refactoring. If you don’t have a clear goal, then you’re just scrambling the code around.

From a hobbyist perspective: do whatever you feel like. A complete rewrite can be a good learning experience.

permalink
report
reply
1 point

Yes, do nothing is an option too, of course. When this has come up on Lemmy, it’s usually because there’s an identifiable issue.

Personally, I’m not really in the market to refactor anything right now, this isn’t a practical question. Honestly there’s plenty of FOSS that hasn’t been made the first time.

permalink
report
parent
reply
27 points

Rebuild from scratch gets a bad reputation sometimes because it’s the go-to response of a junior programmer with a little experience. They know the system could be done better, and it seems like the fastest way to get there is to throw out everything.

What often happens next is the realization that the existing system was handling far more edge cases than it initially appears. You often discover these edge cases when the new system is deployed and someone complains about their use case breaking. As you fix each one, the new system starts to look worse than the old while supporting half its features.

This often leads people to prefer refactors rather than rewrites. Those can take a lot longer than expected and never quite shed what made the old system bad. Budget cuts can leave the whole project in a halfway state that’s worse than if it was left alone.

There are no easy answers, and the industry has not solved this problem.

permalink
report
reply
1 point

My sense from all these answers are that the guys in programmer humour communities that hate refactoring are probably inexperienced junior programmers.

permalink
report
parent
reply
7 points

What often happens next is the realization that the existing system was handling far more edge cases than it initially appears. You often discover these edge cases when the new system is deployed and someone complains about their use case breaking.

The reverse is also sometimes true and it’s when a rewrite is justifyable.

I’ve worked with many systems that piled up a ton of edge cases handling for things that are no longer possible, it makes the code way harder to follow than it should.

I’ve had successful rewrites that used 10x+ less the amount of code, for more features and significantly more reliable. And completely eliminated many of the edge cases by design.

permalink
report
parent
reply
1 point

Yes, there’s usually a niche case, right? That’s why cargo cult engineering comes nowhere near the real thing.

permalink
report
parent
reply
5 points

My current team has had a great solution to this, which is to re-build in parallel. Build the new system alongside the old one, including the reporting and integrations. You’ll find the edge cases pretty quickly.

permalink
report
parent
reply
2 points

So how is that different from refactoring?

permalink
report
parent
reply

Programming

!programming@beehaw.org

Create post

All things programming and coding related. Subcommunity of Technology.


This community’s icon was made by Aaron Schneider, under the CC-BY-NC-SA 4.0 license.

Community stats

  • 333

    Monthly active users

  • 134

    Posts

  • 336

    Comments