We're sunsetting PodQuest on 2025-07-28. Thank you for your support!
Export Podcast Subscriptions
People
J
Jeff
使用ChatGPT来改善关系和解决争论
P
Peter
Topics
Peter: 我最近一直在做一个游戏项目,最初用Unity和视觉脚本语言编写。随着项目发展,我意识到代码库已经难以维护,许多功能用视觉脚本语言难以实现。因此,我决定重新开始,选择更合适的引擎和编程语言,并运用我学到的新技术。我认为,当代码库过于复杂或技术栈过时时,重新开始可能是更好的选择,可以提高效率并避免陷入技术债务的泥潭。 我理解重写代码需要时间和精力,但有时这比在混乱的代码库中挣扎更有效率。重新开始也让我有机会尝试不同的游戏引擎,选择最适合项目的工具。 当然,这并非总是最佳选择,需要根据具体情况权衡利弊。对于一些简单的项目或时间紧迫的项目,逐步改进可能更合适。 Jeff: 我认为几乎不应该完全重写代码。我过去多次尝试完全重写,结果都不理想。我更倾向于逐步改进现有代码。即使代码存在问题,也应该尽量保留现有功能,并逐步改进。 以我去年重写Kineo应用为例,虽然我移植到新平台并使用了新的UI设计,但事后看来,我本应该逐步迁移,而不是完全重写。 完全重写会浪费时间,因为你需要重新实现已经存在的功能。即使现有代码不够理想,它至少是可运行的。我们可以通过模块化,逐步改进,并添加单元测试来提高代码质量。 当然,如果代码库过于混乱,难以模块化,那么重新开始可能也是一种选择。但即使如此,我们也应该尽量保留业务逻辑,并在新的代码库中重新实现。

Deep Dive

Chapters
Peter and Jeff discuss the pros and cons of starting over on an app versus continuing to work with an existing codebase. Peter recently started over on a game he'd been working on for a couple of years, while Jeff generally advises against it.
  • Peter started over on his game, Project Hack, due to problems with his original Unity codebase.
  • Jeff advises against completely rewriting an app from scratch, citing past experiences.
  • The discussion focuses on the tradeoffs between starting over and working with an existing codebase, considering factors like technical debt, modularity, and available resources.

Shownotes Transcript

Translations:
中文

What's up, everybody? Welcome to another episode of the podcast. I am your host, Peter. Jeff is here again today, your other host. How are you doing, Jeff? I'm doing just great. I've been working on a lot of different projects and

Trying to ship a bunch of stuff all at the same time. Awesome. That's always good fun, right? Because everything always goes according to plan. Never goes wrong, right? 100%. Yeah. So interestingly, in this one, I think we're going to have different opinions, which always makes, I think, for the best conversations, and people just like to hear us disagree. And then they can pick sides, right? I would just wish somebody would pick my side once. That's all I want in life. Yeah.

In this episode, I'm going to be talking about something that I've been doing recently that has sparked a thought here. And it's this idea of saying, okay, you know, I've got an app, a game. You've got some something you're building, right? And you realize there's a point that you say to yourself, you know what?

Maybe the best thing to do here is to start over. And so I want to talk through that process of how I got to where I'm at and the decision I made, and then we'll sort of go into a discussion on it. So some of you may know, I have been working on a game for, gosh, I don't know, a couple of years at this point.

On and off. And it was purely a game I wanted for me and for my friends that had the idea. And it's called Project Hack. Projecthack.net is where you can find it. And...

I went through and I'll sort of break it down a bit. I built the first version. It was great, did everything I wanted it to, but it was only ever meant to be the first version to see, number one, is this going to work as an idea? And number two, can I do the bigger plan? Now, this was a single player game. It's kind of an idle style game. I'm not going to go into all the details. You can go to projecthack.net and see it there. You'll get the idea.

But when it came time to build out what I call in air quotes, the bigger, proper version, I always wanted it to be a multiplayer because that was one of the driving ideas. And I was faced with this decision. I originally built the game in Unity back when I was learning Unity. This is how I learned to make games with Unity building this game. So as you can imagine, I did a bunch of things wrong.

And when I went back to the code base and looked at it and was like, okay, you know what? I cannot save this code base. Or I can, but I've got to basically understand what the hell I did like a year ago before I can start rebuilding it and building the new stuff. That's when this idea of maybe I should just start over came into play. Now, I decided to start over.

And this also gave me an opportunity to go out and try a bunch of different game engines for the same game to figure out which one I was most comfortable with, which one worked the best for this game. Again, this can apply to apps, everything, right? And I knew that I had, I learned new techniques. I learned how to do things, a whole lot of things better because I had become a better programmer in that time as well.

And therefore, you know, again, I was like, okay, you know what, at this point, I can spend months and months trying to relearn my old code base written with a visual scripting language and rebuild it in C sharp because that's what unity uses. And that's, that's the route I wanted to go to, to make it work for a bunch of things that basically just were very difficult to do with visual scripting. So yeah,

That's why I decided to start over. And that brought us to this discussion here today about the pros and cons of doing that for some of you who may be in the same boat, right? You've hit some kind of problem, some kind of wall or something. Maybe you inherited an app. Maybe you purchased an app from somebody else. And you're looking at this code base now, this foreign code base saying, what should I do? Should I start over or should I...

continue to try and make the existing code base work. So that's the backstory here for this. And clearly my opinion on this is sometimes starting over is the good way to go. But Jeff, I think that you have a different take on this. What do you think?

Yeah, my take is the exact opposite. That starting over completely from scratch, I'm going to caveat this with the word almost, but I feel like that almost is entirely minuscule, tiny middle school. Not the right thing to do. Okay. You should almost, almost, almost, almost never, ever just do a complete rewrite of something. And let me say that, you know, I'm going to...

eat my own words a little bit here and, and say that, you know, I've learned this from experience that I have done the full rewrite of things multiple times and it never works. Uh, I sit here and I go, Hey, you know, this seems like this is one of those times where I should go back and rewrite this. And it, it almost always is a mistake. Um,

I think the one that I'm going to refer to most in this particular conversation is going to be the big rewrite that I did last year of Kineo. And I think that that

Seems like it fits all of the areas where you might want to do a big rewrite. I was porting it to a different platform. I was using Apple's newest user interface designs in terms of using Swift UI versus UI kit. I was doing a lot of new features for that app and still in hindsight,

I should not have done a clean rewrite. I should have instead done the incremental migration of piece by piece, breaking it up as needed and not doing the kind of ground up new version of the app for VisionOS. Okay. Can I ask a question there? Because I feel like I need a little clarification here. Because I heard you say, I thought I heard you say that you were doing it for a new platform, right? I was doing it for a new platform. So...

My question is, how is doing it for a new platform not starting from the ground up on that platform? Do you follow me?

Well, okay, so it's still an Apple platform. Oh, okay, okay, so it's not like Android. I can reuse, yeah. I was porting it from iOS and iPadOS to Visual OS. Got it, because that was going to be my follow-up question was, well, hang on, surely you used a different technology? The answer here is no, same platform. Okay, got it. Honestly, for a lot of those things, it may still be true. You may still be able to migrate existing stuff, but I feel like that's more complicated than we want to get into here.

Okay, so there you have it, folks, right? We've got two different opinions, which is going to make for a great conversation here. So why do you think that it is best to, you know, take what you've got and rework? I don't want to use the word refactor because I think that's wrong. But why is it best to take what you've got and keep working with that? You know, be it mistakes, bad...

whatever code, bad patterns, and to keep going with that. Because to me, that sounds like, you know, you're burning time on something that, okay, you may have all the logic in there. You may have what the app does, right? So you've got essentially the skeleton of the app and you're going to, going to refresh it out with, with new, new code, new, whatever you want to call it. So, so why do you think that that is the way to go?

I think you've just made my argument for me. Oh, damn. Yeah. All of these things already exist. And yes, you may have learned better ways to do it. You may have learned a nicer way to do it. But what you have...

presumably works at least to some extent. And so you can leave that there and build scaffolding around it. You can say, okay, I need to add this new feature or I need to improve some existing part of it. And you can leave everything else in there while you build that. You use the term at one point, you're like wasting time on this. But I feel like

The complete throw it out approach is it's self-wasting time. You're wasting time re-implementing things that you already have, that you've already done. And for that, like, yes, they may not be ideal. Nothing is ever ideal. No code is ever ideal. You can sit there and you can kind of put that behind a wall. You can sit there and say, this code, we know this code is bad.

and try to avoid touching it as much as possible. But it's still there. It's still working to some extent. And so it's worth having that code there that you don't have to spend time rewriting from scratch. Okay, so someone in our chat room, we got a chat room on our Discord going here while we're recording this. Hey, if you want to take part in that, come join our Discord. We'll put our link in the show notes. But they pointed out that, oh, well, you can take this modular approach.

But I think that that only works if you've got a good modular approach to begin with, right? And that is part of my argument for why it's good to start over is you could have a code base that is so entwined and spaghetti bold that you just can't unravel that mess. And I don't mean, you know, not break everything because chances are you are going to break everything.

But that's kind of the point, I guess, in some ways, right?

But the idea I'm saying is, yes, you're throwing out the code, but you're not throwing out all of the problems that you have solved, meaning the business logic and the rules and everything that you had in the original app still exist. You're just using those as the template to build the new app with maybe the new technology, right? I mean, I think...

I will say that I don't think rebuilding with the same technology is worth it, right? I feel like that's kind of like, well, you're just going to end up in exactly where you were. Why are you doing that, right? But I think that that's kind of where I'm coming from on some of this is sometimes trying to unravel the spaghetti is harder than...

Just acknowledging it's there and building it, building the idea and the philosophies behind it, but in a newer, cleaner way. Yeah. Let me tackle this a couple of pieces at a time. You said you're throwing away the code, but you're not throwing away the business logic. I think for a lot of people, the...

business logic is your code. You likely have not been documenting your code to the extent, like to the bug for bug match up of here is everything that I've chosen and here is every decision that I've made and here is this extent. When you recreate a piece of software like that, you are going to make changes. You are going to make things that are different unless you fully understand your code to the point of

In order to recreate the business logic that you've already created, you're going to have to understand the code to the level that you're talking about not wanting to do in the first place. Okay. To unravel that spaghetti. Sure. And I should say here, yeah, I agree that if the only rules or...

whatever you want to call it, documentation, you have to follow as to what this app is, how it does it and how it was built is the code without documentation. Then, you know, from my perspective, you know, you're in a hard place either way, right? You've got to reverse engineer before you can either repair or restart either way.

Unfortunately, it's easy to sit here and say, of course, none of us would do that, right? But yes, we would all. We've all done that. And something that I want to throw in here, and I'm curious now that I think about it, do you have the same opinion whether it's an app that you built, meaning you, your team, whatever that may look like for you,

or one that you have inherited from somebody else? Would you say that the opinion is the same on both? Given that this... I would say that... Sorry. Given that maybe the app that you inherited, the code is all you've got by way of what does this thing do? Yeah. I would say in a case where the code is all you've inherited, that almost double down on, you should not rewrite that because you have that existing as it is. But I would say nobody is...

so good to understand their own code. However long ago they wrote it. Um, you know, there's, there's the old adage of, uh, realize like realize when you're writing code that the person that has to maintain it later knows where you live. Yeah. Yeah. That's true because it's you. Yeah. And, and so like, I, I feel like,

That is going to be the problem. Whether it was somebody else that wrote it or whether it was you that wrote it, the you in the past is somebody else that wrote it. Absolutely. They are a completely different person. Obviously, the whole reason that you're talking about rewriting this in the first place is because you made decisions then that you would not have made now. And so I don't think there's much of a reason to...

treat those two things differently to say, hey, you know, whether I rewrote this or sorry, whether I wrote this originally or whether somebody else wrote this originally and I'm just maintaining it after the fact, I feel like those are similar enough that no, in both cases, I would avoid doing a rewrite. OK, so.

To me then, that also – and I get what you're saying there, right? Because if I understand it correctly, we could say, hey, regardless of which – whatever path I choose to take here, the me from six – me six months from now will still be – will be looking at the me now with the same eyes that the me now is looking at me from six months ago, right? Right.

Yeah, no, I totally get that. Yeah, no, I understand. And also, hey, you know, whatever I decide now will be just as wrong six months from now as it was six months ago for different reasons. I think that's what you're saying, right? Now, to go back to the idea of modularization and kind of unraveling the spaghetti, as it were, I

I agree that this is generally a approach that you should move towards and that making things more modular does make it easier to do these refactors as you're going along. But I think that it's not a reason to...

completely throw out something that already exists if it is not modularized what you should do instead i'm going to refer to a great great book uh i came with refactoring by martin fowler and i came with uh working effectively with legacy code by michael feathers that's interesting you know that working with legacy code is a book on my amazon list to read one day it it is such a great book you should definitely read this book and we'll folks will um everybody everybody should know this yeah

Both of these books, highly recommended. You should read both of them. All right. Period. I'm trying to remember which one in particular refers to the thing that I want to refer to. Yes, it is working effectively with Legacy Code. It's on page 30 of my copy. It is very early in on the book. Seems. Okay. Yep. So the idea being that what you do is you take that code, that big blob of spaghetti code that you've already got.

You take that code, you put that in a module. That is your one module. You can call this module, whatever you want. I tend in my projects where I'm going back and doing something like this, call it just core or legacy or something like that. And you, you put it off to the side, you wall it off. Then what you do with that code, as you need pieces of that code, as you need to bring this into your modern architecture, your modern rewrite, your modern, whatever, um,

You go in and you find the seams. You find the bits of code where you can go, oh, I can stick in a point of injection here. Injection in the terms of like dependency injection or something like that. Where I can go, I can connect to this code with my new code. I can plug in here. This is my entry point. And you go in and you find that. And then once you've got that seam there, it works very much like a...

I don't know, carving a rock, carving something out of marble. You've got your chisel in there. And once you've got your chisel in there, you can start to pick around. You can pull a piece off. And that's how you get around this spaghetti code. You pull off small pieces at a time. You get in there, you go, oh, this bit of business logic, I can separate this out. I can put in a connection to it right there. And then using that connection, I can start to pry this bit out. And now that bit...

Again, still kind of a self-contained module, maybe inside of it. It's not the prettiest. It's not what you want, but you can pull that small piece out into your new architecture.

And then once you've got that small piece out into your new architecture, you've got a much more minimal interface around it. You've got a much smaller thing to have to communicate with. And you know what you've got when you have that small thing to communicate with? You can write tests for it. You can write unit tests around it. And then once you've got unit tests around it, you know what you can do with it then? Then you can rewrite that small little piece. You rewrite that small little piece, you make that small little piece better. And you've got it completely unit tested. You've

You've got it separated from all of the rest of your spaghetti ball. And you've got that piece.

Okay. All right.

you've, you've, you're able to make progress on your project as a whole. Oh, and so you've been able to build everything that you're still doing and you're able to make those improvements over time.

without having ever needed to step back, take a huge amount of time to rewrite all of these bits. Time for a break. Hey, everybody. It's Peter Whittem here from the CompileSuite podcast. I want to tell you about Setapp. Setapp is a service that provides a subscription fee of just $10 a month, and you get access to over 200 Mac applications, and it's also available now on iOS as part of that deal.

I use the service because it just has a ton of really good first-rate apps that I use all the time. For me, it's invaluable as a developer to have access to tools for things like APIs, for planning projects, writing emails, writing documentation, and you get all of these things, including database apps, all of that kind of stuff right there on the Setapps service for just $10 a month. You can use as many or as few applications as you need.

If you're interested in checking this out, go to peterwhitam.com, P-E-T-E-R-W-I-T-H-A-M dot com forward slash set app, S-E-T-A-P-P. And you can see the details there. And it's got a link that you can go over and start using the service and see how it works out for you. I strongly recommend this to every Mac user. Break time over. All at once. Okay. All right. And that sounds...

Very similar to what they're saying in the chat room. You know, as far as, oh, yeah, well, let's wall this off and then... See, you know, I guess the thing for me is, like in the chat room where they're saying about refactor it later. And that's kind of the part that bothers me about this is, no, if you're going to go to the trouble now, refactor it now. Right? But...

But the segment that you're talking about, right? Module, however you want to phrase it, whatever it means to anybody. And I don't disagree with that. I think, would it be fair to say that is what most of us did as we migrated to Swift and

Okay, well, I'm going to rewrite this controller as Swift from Objective-C. I'm going to rewrite this view in SwiftUI from whatever it was, storyboard hell, right? And picking them off one by one like that because it's also a technology that allows us to do that, right? But it would have been silly, I think, for a lot of people to have gone back and go, you know what?

Swift is the new thing. Swift is the new hotness. Swift is cool. What we need to do is completely throw away all of our objective C code, not look at it and build a new app from scratch in Swift based on, uh, what we had before. Okay. I don't think that, that people think that would be a good idea. I, I'm sitting here trying to say like, if you think that's a good idea, uh, you're wrong. Um,

No, because I think it is wrong. But at the same time, like I, I feel like there, I'm going to have people pushing back. They're like, Oh no, that's definitely a guy. This is where things get awkward because I have to cross back over the other side of the fence and stand with you here because that, that is what I went through. Right. And I'm still going through is yeah. You know what? Hey, guess what? Companies and that won't give you time to start from scratch, you know, but so I've been through that and yes, it,

but it was extremely painful because you also have to try and pick and choose the right parts to start with. Like you say, I do agree with the idea of, well, you know, it's kind of like building a house, right? Use that analogy. Let's make sure the core foundation is good first. Otherwise all hope is lost, you know? And so I get that, but I don't know. I think for me,

Some of the attraction, and I will admit this, I think part of the attraction of starting from scratch is the freedom to choose maybe different technologies, but certainly a different approach. But I also get and acknowledge that sometimes, well, just refactoring this part first, you

is the way to go. Because there is a very good argument to keep the product alive. But I'm also thinking, hey, either way you go, you're keeping the product alive, right? Because if I'm starting a completely new app, the old one is still there to be patched and updated and sent out. Whereas if I...

and work, you know, yeah, I can make a new branch and work on migrating that code and improving that code and whatever term you want to use. But I still have to make sure that it's shippable one way or the other, right? As opposed to knowing that it is shippable at any moment because I'm not touching the existing version. And I get you probably don't agree with that, but you see where I'm coming from? I see where you're coming from. But the problem is I...

Don't believe you. That's fine. As long as you understood, I'm going to edit this so that it sounds like you said, yeah, yeah, no. When you're talking about keeping a project alive, keep it, keeping an app alive. Um,

You're talking about like, oh, well, we can build this new thing and we can patch the other one at the same time. And the problem is every resource that you're spending on doing this rewrite is a resource not spent on patching, on doing new features, on doing all of this. If you have unlimited resources, yeah, you can have two completely ongoing projects at the same time. Right.

You run into problems where you're doing stuff like, oh, well, this app is going to need this new feature. Well, now are you building the feature in the old app and in the new app at the same time? Because you're building it twice because you've got to build it in both places. And so I think that at those times, you are effectively spending a lot of time on solely just doing this rewrite.

regardless of whether you've got two streams at the same time, you've got the same amount of engineering hours in the day. And you need to say any engineering hours that I put on just rewriting code that already exists is engineering hours that I can't put into just doing improvements, just doing bug fixes or new features or anything like that to the old project. Yeah. And you do...

At least from where I sit. Along the way somewhere, somebody, usually me, you have to justify to other folks why and where you're burning those hours. So, for example, let's take a slightly different tack here.

you know that this app has a limited shelf life in the maybe it only ever meant to exist for a certain amount of time or for a specific reason and then will be killed off. Certainly that is something you don't want to rewrite. I will say up front, that is a complete waste of time. You know, that is definitely, you know,

Maintain it, keep it alive for as long as it needs to be, and then let it die. Don't burn the hours unnecessarily. And I would actually go as far as to say don't burn these hours unnecessarily on either path. You know, I would say that there's certainly no business in refactoring something either necessarily.

Unless you have to, for some reason, right? Some serious bug, some security flaw, whatever it may be. But if your app has an L shelf life, this probably shouldn't even be a consideration in either direction. And you should just keep it alive and then let it die. But if your app or apps have a unlimited life in the, you know, Hey, as far as you know, this is going to live forever. Um,

That's where this conversation comes into play. But I think... I don't know. I've got to say, I feel like maybe you've swayed me a little bit. But I think I would still evaluate on a per-app basis as to, okay, which is the best path to go here, right? Because I still feel that for me, I feel like there are scenarios where a code base can be so old that it's just...

it's not that it's beyond saving is that it's, it's not worth it. I'm still, I can save it, but I'm still going to be left with technical debt of, of how it's working on what it's doing. Does that make sense? Yeah. I definitely a hundred percent get the appeal. And like I said, I've done it before myself. It, I definitely understand why somebody might think, Hey, you know, it's a good idea to just throw this all away and start over.

The problem is, again, it all comes down to what are the resources you have? What are the where is your time best spent? I think it is very, very rare, if ever at all, that the tradeoff of we need to just do something a second time.

is better than we need to take what we have and make it better. Okay. All right. Yeah.

All right. So there you have it, folks. We went into this knowing that we both had different viewpoints, which is great. I think that those make for good conversations. I feel like we both presented pretty good stance on both sides. We never promised to have the answer for you. Go make that decision for yourself.

But it's good to have two different viewpoints and take it from there. If you want to tell us about your viewpoint, hey, well, you know what, Jeff, where can they find you? You can find me at Cocotype.com, which should be undergoing a significant redesign soon. It actually has more links to things. More links to things, folks. Yeah. And you can find me, of course, at PeterWhitam.com. Now, here's the surprise, folks. You didn't see this one coming.

In the next episode, we have finally reached the end of our journey. We have been high and low. We've been to the Himalayan mountains, to the deepest oceans. We have found the new name and branding, I guess, to go with that for the podcast. And all will be revealed in the next episode. So, hey, you know what? If you haven't followed and subscribed already, you should go do that.

And if you want to go the extra mile and hey, always go the extra mile, right? Go to patreon.com forward slash compile swift and you can become a member there and support what we do here. We greatly appreciate all of our members. Shout out to all of you. Thank you so much for supporting us. And you get ad free versions. And sometimes you get to know about this, you know, these episodes or anybody else. So with that, everybody, hey,

Who knows what we'll be calling it next time? We know. You'll have to come and find out. See you later, folks. Goodbye.