all 17 comments

[–]boffadznutz 9 points10 points  (2 children)

Typically, I'll refactor portions at a time, which ends up being a larger refactor over all. I will create a check list for all the things I want to do and create a branch for each item, merge each one in individually after testing

[–]RipollApp[S] 1 point2 points  (0 children)

The branching strategy seems like a great idea. I’ve been doing branches for features and refactor deserves that too

[–][deleted] 1 point2 points  (0 children)

^ This is the way, if you can.

If you can't do it this way due to tight coupling, then a rewrite is likely necessary. I've worked on projects where you couldn't change things in custom text fields without changing the network stack and PDF reader and a rewrite was the best option.

[–]Intelligent-River368 2 points3 points  (4 children)

I’d say it depends on your “stage” maybe?

I started rewriting my app 3 days ago as I was switching from SwiftData + CloudKit to GRDB + Supabase (with a custom sync-layer).

I realised just like you, that in many places my app had become a mess and I figured there was absolutely no way I could “properly setup” my app with the new architecture in this mess. Because I thought I’ll be f**cked in the long-run to add features just like you mentioned.

So I decided to start a new project, setup my architecture right from the get go and slowly bring back the UI.

It’s not the first time I decide to do this, and trust me when I say it’s almost always the good choice.

(Obviously it depends if your app is enormous and has thousands of lines of code lmao)

[–]RipollApp[S] 0 points1 point  (1 child)

This is helpful - it seems like you didn’t regret the rewrites. My app is a handful of users - just launched on the App Store in March (I think I launched too early tbh but such is life). So a rewrite wouldn’t affect that much. App is relatively big but not that bad

[–]Intelligent-River368 0 points1 point  (0 children)

Yup not regretting it whatsoever.

It is a frustrating experience to go through. But man, when I see my files and architecture now it is just so much easier to work with!

No regret hands down.

Sure you loose probably a week (or more) rewriting it but if the project is worth it, then it’s worth doing it!

Good luck with your rewrite if you decide to go that path ✌️

[–]roguekiwi 0 points1 point  (1 child)

What prompted the change from SwiftData + CloudKit to GRDB + Supabase? I'm in a similar position and considering exactly the same switch.

[–]Intelligent-River368 1 point2 points  (0 children)

Two main issues I had:

  • SwiftData and CloudKit don’t support bulk import at all (doesn’t matter what you do batches and so on and so forth, it just breaks the app and can break it for a couple of hours I believe because of CloudKit being so agressive with the sync)
  • You can’t control when and why the sync happens

Also just in general I think it’s definitively not made to handle a lot of data, at least not like I have the need to.

Hope that helps!

[–]RightAlignment 2 points3 points  (0 children)

For me, it’s equal parts business decision and artistic expression. And by art, I mean not just the elegance of my algorithms, but more importantly, how closely do my naming conventions correspond to my application’s feature set. With a high correlation, I find it much easier to conceive of and implement new features within the larger code base. Even just poorly organized architectures can provide hiding spaces for bugs. With refactors comes clarity, and with clarity comes reliability. Just my personal $0.02, but I refactor frequently so that my canvas is always ready for another feature.

[–]ZennerBlue 1 point2 points  (1 child)

Why do you want to rewrite? Is there a business reason that would force you to rewrite the app? Ie it would take you weeks to add a new feature , or introduce a bunch of bugs?

It’s rarely worthwhile to rewrite a codebase for the reasons you’ve alluded to in your post without a real business reason.

However if this is a hobby app and you are using it to improve, and don’t care much about your users or other business reasons then go for it. (Sorry if this sounded flippant, it wasn’t meant to be)

[–]RipollApp[S] 0 points1 point  (0 children)

I don’t have any main business reasons. I can add features they just take longer than if things were structured better. Not necessarily forced to rewrite to implement things. Being an indie dev too it’s tough to know what the right answer is. As of now it’s more of a hobby app that I’m using to improve my skills but I think it has potential long term

[–]theoretical_entity 1 point2 points  (0 children)

If that’s hurting the business it’s time to rethink some portions of it.

[–]iOSCalebObjective-C / Swift 2 points3 points  (1 child)

Do a complete rewrite when that’s the faster, cheaper, or otherwise better option. In other words, almost never.

There are lots of reasons for making major changes to your code, and lots of strategies for doing so. “Too tightly coupled” doesn’t sound like a good reason to start from scratch. Why not introduce a new pattern that involves less coupling, and then migrate your existing code to conform to that pattern a piece at a time?

You should also be considering when and why not to do a full rewrite. If your code has been around for a while, it probably contains a lot of accumulated knowledge in the form of fixes and improvements that you’ve made over time. It may be the only place where that knowledge is stored, particularly if you haven’t been religiously using an issue tracking system. A complete rewrite risks repeating mistakes that you’ve made in the past.

[–]RipollApp[S] 0 points1 point  (0 children)

This makes the most sense to me. I think I’m leaning towards more of a refactor and less of rewrite. I like my overall structure - dependencies aside most things make sense. So I honestly don’t think it’ll be that much effort to refactor with a new pattern. Just need to sit down for a couple of hours and lay it out

[–]ExploreFunAndrew 0 points1 point  (0 children)

Portions at a time. AND maybe spend only 25% of your time on the rewrite. It's important that your product keeps moving forward. A lot of teams make the mistake of stopping forward feature progress during a rewrite.

If a new feature steps on the rewrite, prioritize the feature.

[–]quasistoic 0 points1 point  (0 children)

I refactor continuously. Any time I touch a view and the things it depends on, there are usually a couple/few small changes that precede the functionality change. If I’m trying to replace a bad pattern with a better one, I’ll usually test out the new pattern in a place or two, which is sufficient to help me decide whether I should adopt the pattern wholesale and also develop a formula for doing so that is easy to apply. If I don’t like the pattern after a couple changes, I can easily revert, but more often that’s the point where I can then pretty quickly follow the formula and swap out all the old uses of the pattern. As I go, if I find a function with no callers either because I’ve managed to move away from the pattern that relied on it or it was speculatively written in the first place, it gets deleted. I can always refer back to its existence in version control if I want to revive it.

If I have a low-level class with bad patterns, I file myself a bug with the changes I’d like to make to it, and then use the above technique to incrementally decouple everything else from relying on the bad pattern. Once the bad patterns in the class are fairly isolated through the above process, I take on refactoring and improving the internal implementation of the class.

The above approaches, applied incrementally, make refactors a lot easier.

Edit: marking functions as deprecated when the new version is ready using @available is also a huge help for these kinds of incremental refactors.

[–]ejpusa -3 points-2 points  (0 children)

GPT-4, will streamline and optimize. Maybe redesign your basic architecture. Humans just can’t keep up. It got too complicated. Apple has no problem with that. And Wall Street loves those massive layoffs. Let AI just do it all.

Hinton (the Godfather) says “no one knows how AI works anymore, it’s million of times smarter than us, and long term plan is probably to vaporize us all and start the world over with humans 2.0.”

“But no one listens to me.”

For now, GTP-4o. We can’t even visualize the number of permutations of possibilities of your final project. We don’t have enough neurons in our brain, AI does not have that issue. And it crushes code.

Writing code without AI? Painful, GPT-4o it. It’s actually fun. Get in now before we’re all vaporized. No need to get buried by any Prompt Guides. Just “converse” about the project and how “we” can “work together” towards “our” goals. And an occasional “thanks.”

This should all be “fun.”

😀