Under the Radar

292: You Can Always Come Back Later


00:00:00   Welcome to Under the Radar, a show about independent iOS app development. I'm Marco Arment.

00:00:04   And I'm David Smith. Under the Radar is usually not longer than 30 minutes, so let's get started.

00:00:09   So today I want to talk through some things that I recently sort of had to work through in a big update that I did to

00:00:16   Pedometer++, and specifically

00:00:18   it was dealing with a feature that I

00:00:22   intentionally, but I'm not sure if wisely, but I intentionally decided not to implement in the big update that I shipped at the end of

00:00:30   last year.

00:00:31   And specifically that update had a lot to do with the ability to download

00:00:36   offline hiking maps before you go out for walks. You know, so if you're going to an area that doesn't have great connectivity,

00:00:41   you have the ability to download your map ahead of time so that you can use it, use the navigation and planning features

00:00:47   inside of Pedometer++, even when you're, you know, out somewhere else.

00:00:51   But in building that feature,

00:00:53   which has been very well received and I've been very happy with the way that the feature turned out,

00:00:59   when I built that, I only allowed you to download maps. I

00:01:04   provided no mechanism whatsoever to remove maps that you had downloaded.

00:01:08   Which is a bit strange in some ways, that that was like what I ended up doing,

00:01:13   but it was one of these situations where I had a lot of

00:01:18   challenges in coming up with a way to do downloaded maps. I think there's lots of issues that I think maybe even talked about this

00:01:24   on a couple, you know, show months ago.

00:01:26   But it's the thing that is so tricky about this problem is like how

00:01:30   you're solving like three different problems at the same time and very different use cases.

00:01:35   Are you, you know,

00:01:36   are you going out for a hike that you know you're going to do a particular route and so you want to download the maps around

00:01:40   that route and then how wide around that route? Are you trying to download maps for a particular area just like around you?

00:01:47   But anyway, the end solution which I think works really well that I have now where I have this sort of

00:01:53   semi zoomed in map, but not too much that you can choose sort of blocks to download, which I find is very intuitive, works really well,

00:02:00   or you can download the maps along a route.

00:02:03   But it works well because it's very user focused in terms of it's very much about what are you doing today?

00:02:09   It's all centered, you know,

00:02:11   it's based on where you are physically and it's very much set up to the concept of I'm gonna go on this hike,

00:02:16   I know what I'm doing or I know vaguely where I'm going, I'm gonna download it.

00:02:19   But the download, the deleting and sort of handling the deletion side of that, I turned out to be something

00:02:25   I found really complicated because I think that mechanism that I have in there now works well on the download side,

00:02:31   but doesn't really work very well on the delete side. And I tried a bunch of prototypes back,

00:02:35   you know, last December when I was building this,

00:02:37   I just couldn't come up with something that I liked and so I got to this point and this is I think the topic that

00:02:42   I sort of want to talk about is this, I decided, you know what,

00:02:45   I'm gonna ship this incomplete and I'm going to A)

00:02:48   make sure that the feature is actually well received, that people like it, that it's intuitive,

00:02:54   because the way in which I would solve this problem, not that I knew with a solution at this point,

00:02:59   but I knew that whatever the solution I wanted it needed to sort of coordinate well with the actual,

00:03:06   the downloading part of this and so if I end up changing that because I get lots of feedback that it's super confusing or

00:03:11   doesn't work well or it's, you know, I'm going down this road, that would be problematic.

00:03:15   Or I'd be building something that would be in sort of incongruous there.

00:03:19   Or, I mean, there was a slightly naive part of me that hoped that like inspiration would strike

00:03:23   and I would just suddenly have this magically best better solution for it.

00:03:28   But ultimately I was just like, you know, this, I was getting stuck.

00:03:31   I was getting to a place that it was the last feature on my to-do list and

00:03:36   I didn't know how to solve it and it was one of those, I could spin my wheels on this for weeks or months

00:03:42   or who knows how long or I could just punt it and say, you know what, I'm not going to ship with this feature.

00:03:47   And in the end I think that was fine.

00:03:49   And it's, I think there's something interesting about this, about deciding whether a feature is missable.

00:03:55   Like you can just ship, you know, ship the app with sort of this incomplete feature and it'll be fine.

00:04:01   You know, I think of, you know, they seem like overcast.

00:04:04   If you had the ability to download podcasts but not delete them, I don't think you could get away with that

00:04:09   because fundamentally like organizing your files is one of the core functionalities of that app.

00:04:16   Whereas for this, it's like you download these maps and the, basically the downside is that there's some extra files

00:04:21   hidden away that you can never see that are taking up space in your iPhone, which isn't great.

00:04:27   Like I totally wish that, you know, that I wasn't able, didn't have to have this consequence to a user

00:04:32   if they download these massive sets of maps that there's no way for them to get rid of them.

00:04:36   But it wasn't impacting the actual core functionality of the app.

00:04:39   I think that was the thing that I was like, it's fine.

00:04:41   As long as the core functionality of your app is doable and you, you know, you can ship features that are on the,

00:04:48   sort of the sides of things that don't, you know, that aren't complete and that create these opportunities.

00:04:55   And I think it's maybe as soon as being honest with yourself that you are going to go and fix it.

00:04:58   I knew eventually I needed to solve this problem.

00:05:00   Well, did you? I mean, like how, how much space are we talking?

00:05:04   So my largest mapping set, which is for the entire Lake District of the, in the UK, which is, I don't know,

00:05:12   it's like 1000 square miles or something was about two gigs.

00:05:15   Oh, okay. That's, that's significant. Yeah, I was gonna say like, you know, with podcasts, it's, it's, it's necessary

00:05:20   because you can accumulate a large podcast collection on your phone. And that does take up, you know, non-trivial

00:05:25   amounts of space. Whereas like, you know, I feel like a lot of a lot of tendency for us as nerds might be to

00:05:30   over optimize for this and to provide, you know, UI to delete things that are like, you know, 100 megs or

00:05:37   something, which like is like, logically a lot of space, but on a phone, like, you're never going to notice

00:05:42   that compared to like one app update from Uber or something like that. Right. But the other thing I wanted

00:05:48   to ask is like, could you theoretically rely on iOS is purgeable storage system for this?

00:05:54   So no. And specifically, because I once you've downloaded a map, I need the from the user's perspective, it is,

00:06:03   it must be reliably there in the future.

00:06:07   Oh, yeah, of course, that makes sense.

00:06:09   Because if they downloaded something and expect it to be there, then even if it's been a few weeks, and they've

00:06:14   had a, you know, they downloaded a bunch of movies that took up space, and so the purgeable thing, you know,

00:06:19   watchdog kicked off, I don't want it to go and download these files. So as far as the system is concerned,

00:06:24   I've, I am I they are set up as though they are like user documents that are not deleteable are absolutely,

00:06:30   you know, must stay there. Because, in theory, like, it's a safety concern, even that, like, someone is expecting

00:06:35   a file to be there.

00:06:36   Yeah, you could like, take a picture on the top of a mountain and that kicks off the purge, and you lose your

00:06:40   entire map.

00:06:41   Yes. And like that, that would that would not be good. That would that would very much not be a desirable outcome.

00:06:47   And so, yeah, so I had to do something to deal with it. I couldn't rely on the system to be purging these

00:06:53   files or managing them, which is, I think, in very, in a lot of ways, is something that you could reasonably do

00:06:59   for a lot of caches, you know, if you were viewing this more as a cache, then it will then as a user feature,

00:07:06   that was one of the big changes I made is previously, in the version before I did the offline mapping UI, I did

00:07:13   cache the user maps there. But because I was making no guarantees to the user, in that case, it was that kind of

00:07:20   like purgeable, you know, sort of caching store that would could come and go at any point. And the user, I was

00:07:27   making no, you know, expectations with the user that what they were doing would have a persistence. And while I did

00:07:33   persist for most of the time for many people, because unless you happen to download tremendous amounts of or

00:07:39   could, or like, you had to physically visit all of these places. So if you were like, I don't know, hiking for

00:07:44   hours and hours every day, like you're doing a through hike of the Appalachian Trail, maybe you could have

00:07:48   accumulated gigs of cached maps. But for most people, just would never have gotten to that because you had to

00:07:53   physically go to these places. Whereas now you have the ability to, you know, in one button push, you could

00:07:59   download, you know, areas, you know, hundreds of square miles of mapping tiles. And so it was a very different

00:08:05   problem at the once I reached that point. But I think it's one of these things that it's like, it's okay to not ship

00:08:11   something complete, which I think is weird, as something that I think very often we think about our designs as

00:08:16   wanting to be complete. And I think the difference is just one of these things that is, you know, bouncing around

00:08:20   my head this week, as I should ship this update, was this, like, it's that difference between a, it's better for

00:08:27   something to be missing than to be sort of bad, I think, generally, that I what I didn't want was to ship a bad

00:08:36   implementation of this. And we'll can talk through some of the actual things that I eventually was able to do to

00:08:40   this. But it's like, I think it was better to wait, and only ship something when I could actually be confident

00:08:46   that it was good that I'd found the solution that I wasn't just trying to shoehorn some solution into this problem,

00:08:52   because I felt like it was, you know, the app wasn't complete without it. It's like, it's better for it to be

00:08:56   complete. And like, as far as I know, I think I had one report in the last like, four months, five months, that this

00:09:03   app has been out there that people were like, complaining that they couldn't download the maps. And so like, it

00:09:08   turns out that was the right choice that I missing this feature was fine, until I could be confident that I actually

00:09:13   had the best solution. And I feel like this is one of the things I feel like we often run into with the way we talk

00:09:19   about Apple approaching problems is they don't necessarily they tend to not ship, sort of half baked solutions, they

00:09:25   tend to wait until they're fully baked. And once they're fully baked, then they release them rather than sort of

00:09:31   only, it's like, it's better for it to be missing and you know, just not there, and to ship the wrong thing and have

00:09:36   to deal with that in the future going forward.

00:09:39   Yeah, it takes a certain level of patience and a little bit of gusto, I'd say, to be willing to do that. And, and the

00:09:46   thing is, like, you can do that badly, and it can blow up in your face to like, because it, the reason it takes a bit of

00:09:52   courage to ship, you know, to ship something that's lacking in certain features, or the same complete is that you got

00:10:00   to be really sure that's the right move. Because you're going to be judged by your customers and by reviewers, if

00:10:06   you're lucky to get reviews and stuff like that, you're going to be judged by what's there when you when you ship it.

00:10:10   And like that, like those one star reviews, or those press blog posts or whatever could be there for months or years

00:10:19   afterwards as what people see when they search for your app. So you have to really be sure that that whatever you are

00:10:25   intentionally omitting or deferring is not that important and is not like that, that not that many users are going to go

00:10:33   looking forward, expecting it to be there. And so I think in your case, I think you did find that balance and your

00:10:37   feedback shows that. But But certainly, this is not like a blanket lesson that like, oh, just ship that half your stuff,

00:10:42   and it'll be fine later. It's like, well, think about it firstly, be be a little careful about what what you are omitting

00:10:49   before you before you make that leap. And I think something like this, where it's like, I'm accommodating an edge case. I

00:10:56   think that is a good area where that's usually a safe move.

00:11:01   Or similarly, I think there's an element of waiting until it's like this problem would get worse over time as people

00:11:07   download more maps. And so it isn't a problem. The first week I shipped the app, it's a problem months later, when they

00:11:13   have lots and lots of maps. And so it becomes this in some ways you can have been there's sometimes also benefits,

00:11:18   benefits where you can omit a feature that you know, won't be a problem until later. As long as you're disciplined in

00:11:25   actually getting it shipped before it becomes a problem, you can potentially also do that as well.

00:11:28   Yeah, or it could be you know, some kind of like technical detail. Like if I if I built a search index with every

00:11:33   episode you ever viewed and overcast, and I just never deleted anything from that search index, that wouldn't be a

00:11:38   problem. You know, it would be a couple 100 megs for a decent size podcast collection for a little while. But then after

00:11:44   like after 10 years, that could be a few gigs. And so like, you'd have to have some mechanism eventually, but you

00:11:51   could get away with it for a little while and it'd be fine. Yeah. All right, we're brought to you this episode by

00:11:55   Indeed. We're driven by the search for better when it comes to hiring, the best way to search for a candidate isn't to

00:12:01   search at all. Don't search match with Indeed. If you need to hire you need Indeed. Indeed is your matching and hiring

00:12:09   platform with over 350 million global monthly visitors according to Indeed data, and a matching engine that helps you

00:12:15   find quality candidates fast. So ditch the busy work, use Indeed for scheduling, screening and messaging. You can

00:12:21   connect with candidates faster. And Indeed doesn't just help you hire faster. 93% of employers agree Indeed delivers the

00:12:28   highest quality matches compared to other job sites, according to a recent survey by Indeed. Leveraging over 140 million

00:12:36   qualifications and preferences every day, Indeed's matching engine is constantly learning from your preferences. So the

00:12:41   more you use Indeed, the better it gets for you. Join more than 3.5 million businesses worldwide that use Indeed to hire

00:12:49   great talent fast. Listeners of the show get a $75 sponsored job credit to get your jobs more visibility at Indeed.com/undertheradar.

00:12:58   Just go to INDEED.com/undertheradar right now and support our show by saying you heard about Indeed on this podcast.

00:13:07   Indeed.com/undertheradar. Terms and conditions apply. Need to hire? You need Indeed. Our thanks to Indeed for their

00:13:15   support of this show and Relay FM.

00:13:17   So the actual solution I came up with, which is probably the next thing that's worth talking into, I think is interesting

00:13:23   as well, insofar as the reason I was stuck and the reason I felt like I needed to postpone this feature or omit it from the

00:13:29   start is because of this week, sort of there was a, there was a there was a step in the middle that like, you know, it's

00:13:35   like I had the had the problem, I sort of knew what I wanted the solution to be. But in the middle, there was the step

00:13:40   that was like, you know, just like in my notes that are just written as like, do the magic, like do the, like, there's this

00:13:47   thing of what I would do, because ultimately, what I want is to be able to present the user with a clear list of the

00:13:53   areas that they've downloaded as offline. But they've been downloading maps kind of higgledy-piggledy however they want,

00:14:00   whenever they were moving around, you know, there's all kinds of different mechanisms by which they can download them.

00:14:05   And so I didn't want this to be this issue. And this is the thing that reason I was going down this road is I get very

00:14:11   frustrated with other apps, like even Apple Maps or Google Maps, one of those when you have offline map sets is you

00:14:17   go to a similar place multiple times. And you end up with these like weird overlapping rectangles of, you know, this trip,

00:14:24   I went to this place. And so I downloaded it over here, and then this one over there. And you end up with these multiple

00:14:29   map sets that sometimes over set overlap, sometimes don't overlap. And if you delete one, will it delete the other map

00:14:34   set, even if it overlaps or intersects, like, you end up with these really awkward questions that I just didn't like that

00:14:40   kind of UI, but I wanted the conceptual sort of version of, you know, do I want to download the maps, or delete the maps

00:14:48   that I've downloaded for this particular place. And do the magic part is like coming up with that list of places that you

00:14:55   have maps for because, you know, they aren't specifically the user is not choosing the places I need to do the magic to

00:15:02   come up with them. And so that was the end of the end was like the reason I put, you know, pushed off is because I didn't

00:15:08   know how to do the magic or I didn't wasn't sure what the magic would look like. And but in the end, I think I was

00:15:12   actually able to get there. And I mean, and functionally, what I do at a technical level now is, I look through your

00:15:18   offline mapping, you know, tile sets, and I run an algorithm that sort of cleverly groups them together into what seemed

00:15:26   to be, you know, related places, you know, geographically, and into clusters that you can then look at and delete. So if

00:15:34   you, you know, went to a trip in whatever you went to Yosemite Valley, and your first time you only stay down in the

00:15:39   valley, but then the next trip you went and climbed Half Dome. And so now you have this extra sort of set of maps that

00:15:44   extend out from your first set, those will become, you know, a single set, and that becomes your Yosemite set or, you

00:15:51   know, but if you only visited a place once or you have, you know, you did only explored a very small area, it'll just group

00:15:58   that together and say that that's a particular set. And like that was the end, the magical step that that I think was

00:16:05   transformative and making this into something that works, where I can give you that kind of grouped UI, easy to delete,

00:16:11   easy to manage, you know, make it very easy to just, you know, say, Oh, well, you know, I don't want these maps from

00:16:16   Yosemite, because I'm not going to be there anymore, you just hit delete, and it'll clear them all out, rather than you

00:16:20   having to manage all the multiple trips, you may have gone there or the different places, it's sort of this slightly

00:16:25   smarter grouping mechanism. And once I was able to do that, like working out technically how to do that magic, then I

00:16:33   had the, you know, the now I had the UI, I wanted, I could do it, I could do it in a very performant way I could, like,

00:16:38   there's all these things that, you know, were the hard part that I just needed that data. And I think so often, it was

00:16:44   also the sort of the confirmation that the version of downloading was very well received. And so I was confident that I

00:16:51   needed a solution that didn't require the user to choose and name and manage the areas themselves. Because that was the

00:16:59   thing that I was trying to stay away from. And it seemed like it worked. And it seems like it's really been very well

00:17:04   received. Because obviously, if it's if the end solution was that I needed to end up doing what Apple Maps and Google

00:17:08   Maps do, where you build these like named areas, and you have all these overlapping rectangles, and if I had to go down

00:17:14   that road, because that's what users ultimately really wanted and demanded, then like, the deleting problem is super

00:17:20   easy. In some ways, you just like delete the thing that the user, you know, tells you to delete. But in my case, that

00:17:26   wasn't the case. And so once that was confirmed by user experience, then I just needed to do the work to build an

00:17:31   algorithm to solve the UI problem that I was facing.

00:17:35   Jared Ranere: Yeah, and the UI that you came up with, like, I think what's what's great about like the the mechanic that

00:17:42   you found and implemented here is that when you see it, it looks totally obvious, like, of course, that's how this

00:17:48   should be done. And that's like, one of the great things about about good design is that that's like the the result of

00:17:55   good design always seems so obvious that no one quite appreciates the iteration and thought that went into it. Like,

00:18:04   because what you arrive at is like, Oh, of course, this is this is easy. Like, this makes total sense. This is the only way

00:18:11   it could possibly be done. It is that obvious. But it might have taken you quite a lot of iteration and time to get

00:18:17   there. But yeah, like, and I like, I like how you, you really are focusing on getting things working, getting things

00:18:26   shipped and getting things out there, even if it is not the most like, technically ideal solution at that moment,

00:18:33   because that's what indies have to do a lot of the time. I mean, that's what all companies have to do a lot of time,

00:18:38   honestly, but, you know, like, that's, that so often holds us back, like, we might optimize, you know, premature

00:18:45   optimization is the root of all delayed projects. We often try to optimize for things that, you know, for technical

00:18:53   purity or elegance at levels that it doesn't matter. And it's not to say that there are no levels that it does matter.

00:19:00   Like, you know, one of the major things I'm working on with the Overcast rewrite is performance when you have very

00:19:06   large podcast collections. The existing Overcast app that's been out there for 10 years is really not very

00:19:12   performant at all in certain areas once you have, if you have like a few hundred podcasts that you've ever listened to or

00:19:18   subscribed to. It, and that's something that like, when I was first making the app and designing all the data structures

00:19:25   and the concurrency model and everything, when I was first doing all that 10 years ago, I never considered somebody

00:19:30   might have 200 podcast subscriptions. I was like that, I was thinking maybe you'd have 20 or 10 or five, you know, not a

00:19:37   lot of people had hundreds of podcast subscriptions in, you know, 2014. But now many people actually have accumulated

00:19:46   that many. And so now the app is very, very slow. And so now I know which areas I had to optimize. And that's what I'm

00:19:54   doing with the rewrite. But there's other areas of the app where like, if I optimize something like crazy for something

00:20:01   like the display of a setting screen, nobody will ever care, no one will ever notice. It is not a good use of my time. And

00:20:10   even and again, going back to earlier, even the areas like for instance, if you are slow with with large collections, even

00:20:17   that, I really didn't need to do that for the first six or seven years of Overcast. Really, like, that's something that I was

00:20:26   able to ship something that was not necessarily incomplete, but certainly not ideal for large collection management. And it

00:20:33   did work fine and continues to work fine for many people. But it took until many years in before I had any any non

00:20:42   trivial number of customers who actually had large collections, and who actually and so where that would actually matter. So

00:20:49   it was fine for me to ship it in a simpler way with dumber, slower algorithms and simpler models inside the app. That was

00:20:57   fine 10 years ago. And now I can fix it now and I can improve it now with the rewrite. But I didn't really need to do all

00:21:05   that upfront back then. I mean, I wish I had in certain ways. But but you know, I couldn't have known that then. And then I

00:21:11   was focused on, let's get this app out there. And and I wrote the entire initial app in something like a year. And it it

00:21:19   now like the idea like I've been working on the rewrite now for so long, way longer than a year. So now the idea of that is

00:21:24   kind of kind of mind blowing, but be like I did learn back then. Or I learned now, looking back at what I did, like, that was

00:21:33   the right move back then to ship what I had back then with what I knew back then, even though it was incomplete in some ways,

00:21:40   there were many slow, slow, simple algorithms for certain things. But it worked. Yes. And there's, there's so many

00:21:47   opportunities for like, micro optimizations that we have today, that once you actually run them on a device, you realize this

00:21:54   does not matter at all. So you know, for instance, like, if you need to, you know, keep keep like, you know, an array versus a set,

00:22:02   and you want to see like, all right, I want to see if I've if this element already exists in the collection. That's way faster, in

00:22:09   most cases, if you use a set instead of an array. But unless you're dealing with large collections very frequently in some kind of,

00:22:15   you know, tight loop in your app, you probably won't notice that difference. And so if there's some other big advantage to that

00:22:22   thing being an array, instead of a set, when you have to test membership here and there, it's probably going to be fine. Like, you

00:22:28   know, and so and there are so many instances where we kind of get lost in the weeds with algorithmic purity and algorithmic

00:22:35   idea, ideology, almost really, for things that really don't matter very much, while maybe not having enough time as a result to

00:22:45   address some things that really do matter, like handling large collections.

00:22:48   Jared Ranere: Yeah, and I think there's something that's, I ran into this so many times when I was doing my like magic bit in the

00:22:53   middle, where my computer, like I did have a bachelor's degree in computer science. And so like, I'm, you know, I'm trained for

00:23:01   what I do, which I know is not everyone who's a developer, has that background, where they actually were sort of trained in the

00:23:08   sort of the theory of computer programming and algorithms and those kinds of things. And sometimes I feel like that background

00:23:15   comes back to bite me, because I have in the back of my mind that there's, you know, what I think about the old, you know, sort of

00:23:20   like the big O notation and...

00:23:23   David Tenenbaum, Jr. This is order N squared, I cannot possibly ship this.

00:23:25   Jared Ranere Exactly. And that was, this is the, that is the exact thought that I had when my first solution to my like grouping

00:23:32   algorithm for working out, you know, where are the areas that you have offline maps. And the first version I came up with was

00:23:38   this very naive, like, just compare the various points to all this, it's not like, you know, it's not quite every point to every

00:23:46   other point, but it's not that much far from that. It's a slightly clever version of that. But it's like, rather than having this

00:23:52   very, like I started in, you know, investigating these, all these algorithms you can do with this, you know, convex hull

00:23:58   creation of things that works out, and how does it work when the groups are combining and all like, it's got very complicated

00:24:03   very quickly. And I was like, oh, like, I only sort of understand this algorithm that I'm reading about. And if I only sort of

00:24:10   understand it, the chances of me implementing it successfully and correctly go down dramatically. So let's just start off by,

00:24:17   let's throw away the complexity and just do the super simple basic thing. And I have a very large offline map down, you know,

00:24:23   database with, you know, just thousands and thousands of square miles of mapping tiles. Let's see how fast it is to run. And I

00:24:31   build that very straightforward, simple version that does this, you know, this sort of simple grouping, and then the groups

00:24:35   combine if you have a point exists in multiple groups, and very straightforward, like the whole thing is maybe like 40 lines

00:24:42   of Swift, like very easy to understand, like straightforward algorithm. And I take it and I run it on an iPhone 10 R with my

00:24:50   full, you know, database. And the whole thing took, I think it was 0.2 seconds to run. And it's like, all right, that is, that is

00:24:58   good enough. Yeah, that is, that is too. And it's, especially because it's not an operation that the user is doing very often,

00:25:05   if at all. And that's on the oldest phone, essentially, that I support. If I run it on my, you know, my iPhone, whatever, I have

00:25:11   14, 15, whatever the most recent iPhone is, it's like,

00:25:15   There's so many we've lost track.

00:25:16   It is. And like I run it on that, it's, you know, it's rather than 0.2 seconds, like 0.02 seconds, like it's, it's essentially

00:25:24   instantaneous. And it's like, Oh, right, that this algorithm is totally fine. I don't need to make this more, you know, more

00:25:32   computationally pure and elegant and fancy. This version is fine. And that's amazing. And that's not to say that you should

00:25:38   never do the fancy algorithm like I have, you know, in my mapping engine, like the thing that actually is rendering the map

00:25:46   to the user, which is shown on the Apple Watch is shown on the iPhone showed in live activities, like there's all these places

00:25:51   that this mapping engine is used. I do a lot of the really tricky, complicated, you know, algorithm work, because that's

00:25:58   being updated, like once per second, and potentially on devices where battery life is really important. And so like, I need

00:26:04   that code to be super clever, to be super optimized to rather than, you know, any kind of waste or inefficiency, I want to get

00:26:12   out of it as much as I can so that it's super fast and important. Great, do it there. But it was interesting this time when I

00:26:18   started going down this, like, you know, I tend to do this thing where I'm starting to read, not like, you know, sort of

00:26:23   articles or Wikipedia posts or things about different algorithms and trying to decide which one makes the most sense. And in

00:26:28   the end, it's like, no, don't like just do the simple, obvious, basic thing that, you know, I can understand and then seems to

00:26:35   work great. And start there. And if that, you know, somehow that hadn't worked, if I'd run that on my massive offline

00:26:41   database, and it had, you know, taken 10 seconds to run, it's like, okay, well, that's not going to work, I'm going to need to

00:26:46   do something faster or better, or I need, you know, more magic or a different kind of magic in the middle. But it was

00:26:52   definitely a learning experience for me to like, just I shouldn't lean too heavily into those, you know, these courses I took,

00:26:58   whatever it was, like 25 years ago, at college, they were telling me, Oh, you know, if you anytime you have an n squared

00:27:03   algorithm, it's bad. It's like, no, it's probably fine. Like, even for reasonably large version, it depends on what n is. It

00:27:11   depends on how, like, even that, like, I maybe I'm doing 10,000 comparisons, or 100,000 comparisons. Like, maybe that's what

00:27:19   I'm doing. Like, it could be a relatively big number or a million comparisons, I don't even know. But the, the chips that my

00:27:24   app is running on can do a million comparisons in a fraction of a second. And so it's just not a problem that you need to

00:27:31   solve necessarily, unless it's an operation that is happening lots and lots of times, I wouldn't want to be inefficient

00:27:36   every second for 12 hours of a hike, that would be foolish. But if you're going to do it be slightly inefficient for two

00:27:44   tenths of a second, once every couple of weeks, that's probably fine. And that helps get the app out the door, it helps,

00:27:50   like me finish off this feature that I've been, you know, lingering around before and it means I can move on to, you know,

00:27:57   other features and, you know, focusing on things like the UI of the feature, which is way more important in many ways than

00:28:03   the, you know, the algorithmic purity of the way that I'm, you know, creating this data.

00:28:07   Jared Ranere: And rest assured, too, every single other app on your customers phones is going to be burning all that, like,

00:28:14   you know, wasted bandwidth, it's going to be burning that every single time they open the app, just like focusing, but like

00:28:19   reporting back to their analytics servers and running their own, like incredibly heavyweight everything operations that

00:28:24   they're doing to track every single possible thing you're doing and serve you ads, like, what you're doing is a drop in the

00:28:31   bucket. And I find like, it's helpful for me to, to actually like, you know, load up like I have, I have a couple of

00:28:38   overcast test accounts that I can log into that have hundreds of thousands of podcast episodes, like just huge

00:28:45   collections that, like, for the most part, I don't think any any user would actually have a collection that big. And I

00:28:50   can load it up in the old code where it just basically freezes and crashes. And I could load it up in the new code where

00:28:57   it's a little heavy, but it works. And I'm like, okay, now, like, now I've tried the extreme, like, that's the thing,

00:29:03   you try the extreme with something that you think is going to be too slow. And if the extreme case is usable, you're

00:29:09   probably okay. Especially like when you then go back to the common case, and it takes 0.2 seconds, like, it's fine,

00:29:14   you're gonna be fine. That's the theme of this episode is like, get it get it to work, it's probably fine, and move on, you

00:29:22   can always come back later.

00:29:24   Yes, and I think having that freedom to come back later is absolutely a key thing to being able to ship things in the

00:29:30   first place.

00:29:31   Thank you, everybody for listening, and we'll talk to you in two weeks. Bye.

00:29:35   [BLANK_AUDIO]