Under the Radar

262: Managing Change


00:00:00   Welcome to Under the Radar, a show about independent iOS app development.

00:00:04   I'm Marco Arment.

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

00:00:09   So this week we wanted to talk about managing some changes that we're doing that feel risky

00:00:17   because they involve changing long established behaviors or UI characteristics or code even in our apps.

00:00:28   apps and it can be tricky. When you're first starting out making something new, you have

00:00:33   no users, you have no traffic, you have no data, and so you can kind of change whatever

00:00:39   you want all the time. I remember back in the Overcast 1.0 beta, there was so much change

00:00:46   during that beta period and huge changes to the way the app worked, to how it looked,

00:00:51   to even what the features were, how the features worked, like massive changes during that period

00:00:56   because there was no legacy, there was no data, the user base was like 50 people, it

00:01:02   was a very relatively small thing.

00:01:06   And so I was able to iterate quickly.

00:01:09   As time has gone on, I mean that was eight years ago, I have been less and less able

00:01:14   to make those big changes.

00:01:16   And there's been lots of reasons for that.

00:01:18   Part of it has been just my workload and my life, I've had less time to do really big

00:01:25   coding blocks. A bigger part is just that the app has gotten really well established.

00:01:30   You know, I'm very fortunate that the app has a lot of users, I manage a lot of volume

00:01:35   of usage and of user data, and I have, you know, if anything I change, I hit a bunch

00:01:42   of one-star reviews and a bunch of five-star reviews. And a bunch of people saying, "Why

00:01:47   don't you just make it a setting?" So anyway.

00:01:50   Why don't you just?

00:01:52   That phrase, nothing that's ever followed,

00:01:54   why don't you just, has ever actually been constructive,

00:01:56   I think.

00:01:58   - Any comment that begins with why don't you just

00:02:00   instantly says you don't understand the problem.

00:02:02   - Yes, it is.

00:02:03   Everything is more complicated than you imagine it to be.

00:02:05   - Exactly, exactly.

00:02:07   But anyways, so I've recently undertaken

00:02:09   a few of these changes over the last couple of weeks,

00:02:12   kind of unplanned, but that's kinda how I work,

00:02:14   and you're tackling some big ones as well.

00:02:17   So first, I wanna hear,

00:02:19   What is the large change management

00:02:22   that you're doing recently?

00:02:23   - Yeah, so in this version five update of Podometer++

00:02:27   that I've been working on for the last few months,

00:02:29   which I think, hopefully, fingers crossed,

00:02:31   I will be submitting early next week,

00:02:33   which I am thrilled by.

00:02:35   - Nice.

00:02:35   - It's essentially rebuilding the entire app

00:02:40   from almost the ground up,

00:02:42   from maybe the second floor up.

00:02:44   I'm leaving some old Objective-C

00:02:48   layer stuff, but everything else is a complete rebuild to essentially modernize the app,

00:02:54   to add a bunch of new features, to do a lot of big, essentially put myself in a position

00:02:58   to actually move the app forward rather than feeling like I'm trapped in the past, which

00:03:03   is how I've been feeling for a long time.

00:03:06   But it's like so much of this is this weird, this terrifying feeling of, so I have something

00:03:13   in the App Store right now that works.

00:03:15   It's like battle tested.

00:03:16   It's proven.

00:03:17   there for, you know, almost a decade now, in some form, and it is very stable. And I'm

00:03:23   going to essentially rip it out and replace it, which I think is the right call in this

00:03:28   situation. Like, I think I can't maintain an Objective C UI kit app going forward into

00:03:33   the future. Like it is just at a certain point, I'm going to have to migrate it. And I may

00:03:37   as well do that now that, you know, the APIs are mature, but most people are running the

00:03:42   latest operating systems, all the good things that are like reasons it's a good idea. But

00:03:45   it's like I'm fundamentally changing the thing that is so vital to my business. And

00:03:51   so that change is just terrifying. I mean, I've gone through this a few times where

00:03:56   I've made changes like this, and I think in the back of my mind I always have that

00:04:00   feeling of "You don't want to kill the golden goose," like the nursery rhyme about

00:04:06   that, where it's that sense of there's this thing that's working, and if I make

00:04:10   a change, this thing could just go away. And that's really problematic that in theory, you hope that

00:04:17   it's just like, "Oh, you get 25-star reviews, 21-star reviews, it all balances out, and it kind

00:04:24   of moves forward as though nothing has changed." Or in the best case, maybe you get a different

00:04:31   ratio of those, that it's like 25-star reviews and five one-star reviews. Most people like it,

00:04:36   it, the few people don't like it, whatever. But no matter what, there's always that risk of it's like

00:04:41   50 one-star reviews and no positive reviews. All the work has sort of gone poorly and terribly and

00:04:48   everything falls apart and your professional life is over. That's the risk that's always in the

00:04:56   back of my head when I'm going through these kind of big fundamental changes. And it never gets

00:05:01   easier. Like, I've done this many times now. I've gone through many things, and it's much

00:05:06   easier, I will say, back in the day when my apps had hundreds of users. It was much easier

00:05:11   to manage than in a situation now where I think we're both in a position where our apps

00:05:15   have large enough audiences that you make a change. Even if 1% of those people don't

00:05:20   like it, that's a lot of people. That's a number of people who could both make your life

00:05:24   difficult in terms of reviews in the App Store or all kinds of other places, or just in general,

00:05:30   Like, it's an absolute number.

00:05:31   It's a lot of people that might get really annoyed and disappointed.

00:05:35   And I don't want to disappoint anybody.

00:05:37   I like someone who likes my app now.

00:05:38   I want them to keep liking my app.

00:05:40   I don't want that to change.

00:05:42   So it's a dangerous thing to do, and so I always feel really nervous and tricky about

00:05:46   actually going and doing it.

00:05:48   Yeah, that's exactly what I've been facing, even the numbers you threw out, like the 1

00:05:53   percent.

00:05:54   So, one of the big risks that I took recently is, about a week ago, I ended support—and

00:06:04   I said I was going to do it on Mastodon, like I said, ahead of time, but not everybody follows

00:06:08   me on Mastodon, obviously.

00:06:09   So I ended support for some really old versions of my sync API that runs on my servers.

00:06:16   And this was in part—this was mostly because I'm in the middle of this giant migration

00:06:21   that's another huge change that I'm managing

00:06:24   and that I'm very stressed about.

00:06:26   So basically, as I've talked about many times before,

00:06:28   I'll be brief, because this is a brief show.

00:06:30   I've been doing server migrations and server tweaks

00:06:33   to basically scale the business better,

00:06:36   to lighten the server load, to make sync faster

00:06:38   and more reliable, and to lower my server costs,

00:06:41   'cause my costs just keep going up and up

00:06:43   and they're getting really crazy.

00:06:45   So anyway, it's been very, very stressful,

00:06:48   but I'm actually making pretty good progress

00:06:49   of kind of moving everything into this new, a newly architected handful of classes and

00:06:57   functions in the back end, where I'm consolidating all of the access to these two massive high

00:07:02   traffic tables, the subscriptions and the episode progress tables basically, consolidating

00:07:08   the access to those two tables all now through this one unified class that has the ability

00:07:14   to read and write that in two different ways. One of them is the new way that I'm trying

00:07:18   to migrate to where it's going to be way smaller, way easier to host, and give you more flexibility

00:07:23   in how it's hosted in the future.

00:07:25   Like, I could, you know, the new class has the ability to do things like instead of hosting

00:07:29   it on local MySQL servers, I could host it like on a managed database service, you know,

00:07:34   where then I don't have to deal with a lot of this stuff and scaling becomes easier,

00:07:38   performance becomes better, cost might be better in certain ways, I don't have to deal

00:07:41   with backups and replication and sync and everything else.

00:07:44   So moving at all towards this new system.

00:07:46   So this has involved rewriting and refactoring

00:07:49   tons of the server code.

00:07:51   Because it turns out, when you run a podcast app,

00:07:54   Sync Servers, a lot of code involves reading and writing

00:07:57   to the tables that deal with what podcasts you are subscribed

00:07:59   to, what your settings are, and what your progress and status

00:08:03   of every episode is.

00:08:06   So anyway, massive changes here.

00:08:09   And in the process of doing all of that, which, again, that

00:08:12   alone has been terrifying.

00:08:15   But also very, so far it's been very fulfilling

00:08:19   in that by doing this I've been able to make some things

00:08:21   more efficient already, even before I've started

00:08:23   using the new table structure.

00:08:25   I've been making a lot of things more efficient

00:08:27   with the old table structure and everything.

00:08:29   But as part of doing this, the way I've managed

00:08:33   my API versioning over time is I basically just copy

00:08:38   the controller, the API controller.

00:08:40   I have like API one, API two, API three.

00:08:43   Whenever I do a major API version change where the method by which the app syncs to the servers

00:08:48   has to change in a big way, I just copy, I make a new API controller, and I make the

00:08:53   whole protocol in that, and then I just have the old one around, just running untouched.

00:08:59   Now as I'm making all these changes to the low-level data storage and how it's accessed

00:09:05   and everything else, these are pretty large changes to the code, and so I had to make

00:09:11   a difficult choice.

00:09:12   either just keep the most modern API files up to date and refactor those to use the new

00:09:20   code, or go back and refactor all of the old ones also. And I chose not to do that for

00:09:27   a few reasons. The biggest of which is that the old ones are all... the ones I was hoping

00:09:35   to not have to update were the ones that serve versions of iOS that the app hasn't worked

00:09:41   on in about a year or more.

00:09:44   And so this is basically everything before iOS 15.

00:09:47   And when I looked at my usage, it actually is,

00:09:50   it's not nothing, it's about 1%.

00:09:54   It's kind of funny actually.

00:09:55   I have about 0.7% on iOS 14,

00:09:59   about 0.3% on iOS 12,

00:10:03   and almost nobody on iOS 13.

00:10:06   I have almost as many people on iOS 17 as I do on iOS 13.

00:10:11   iOS 17 is in doubt yet.

00:10:12   (laughs)

00:10:14   So, iOS 13, yes, it was a disaster.

00:10:18   Apparently everyone else thought so as well.

00:10:20   So it seems like the people who are holding onto iOS 14,

00:10:25   'cause 15 and 14 run on the same devices,

00:10:27   I think from what I've gathered is mostly jailbreaks,

00:10:30   'cause jailbreaks I think are still on iOS 14 only.

00:10:33   I don't really follow that world,

00:10:34   but that's what I've been told.

00:10:35   And also people who are just like,

00:10:39   who are just kind of scared to update

00:10:40   because they have maybe an older device

00:10:42   and they don't want their device to slow down.

00:10:43   And they've had bad experiences in the past with that.

00:10:45   And so like, well, you know, I have,

00:10:47   like, you know, somebody wrote me the day with an iPhone 11.

00:10:49   And that, they considered too old to run iOS 15.

00:10:52   They were holding it to 14.

00:10:54   You know, that's what happens.

00:10:56   Your user base, people develop these habits

00:10:58   with bad experiences in the past

00:10:59   and they refuse to update anyway.

00:11:01   And iOS 12 makes some sense because the devices

00:11:04   that are on 12 can't go past that.

00:11:05   like they are not compatible with 13, 14, and 15.

00:11:08   But all in total, this total is about 1% of my user base.

00:11:11   And I made the decision to actually cut that off,

00:11:16   because it was so much work on the server side.

00:11:20   Basically, my workload during this migration

00:11:22   would have approximately tripled.

00:11:25   And furthermore, I no longer maintain old devices

00:11:29   that can test those old API versions.

00:11:31   Because after a while of my app not working on an OS,

00:11:35   I decommissioned those test devices.

00:11:37   So I don't even think I have a device that's

00:11:39   running iOS 14 anymore.

00:11:41   I have an old one that can run iOS 12.

00:11:43   I can maybe test that, but the API that runs iOS 14,

00:11:46   I can't even test that myself.

00:11:48   And so I'm not going to rewrite this huge part of my API

00:11:51   file for a very small percentage of the user base

00:11:54   that I can't even test against.

00:11:55   And then I have to maintain indefinitely into the future.

00:11:57   So I decided-- it was a tough decision.

00:11:59   The last time I did this, it was probably three or four years

00:12:02   ago at least.

00:12:03   But I did cut off support.

00:12:04   And I've heard from those people.

00:12:06   Because 1% of a big number is a big number.

00:12:09   And so I have heard from them.

00:12:11   And I knew I would.

00:12:13   And I felt bad.

00:12:14   And I've tried to explain to them as nicely as I could,

00:12:16   here's the situation.

00:12:18   And for the most part, most people were like, well, OK.

00:12:21   Thanks anyway.

00:12:22   A few people were really mad, but what can you do?

00:12:25   And ultimately, this is what I had

00:12:27   to do to make the app better.

00:12:30   When I look at what I'm moving towards,

00:12:32   the world I'm moving towards by doing all these things.

00:12:35   Not only am I going to save server costs, which is something that I care about, but

00:12:38   my users don't.

00:12:40   But also, I'm making things less likely to break in the future, much more resilient.

00:12:46   But the big thing that my users will actually care about is that there have been a number

00:12:50   of really good features that I haven't been able to do because of the way my old sync

00:12:54   system worked.

00:12:55   And there have been a few really big annoying sync bugs that I haven't been able to fix

00:13:00   because of the way the old system worked.

00:13:02   And so, soon, once I'm on this new system,

00:13:06   I will be able to do some really nice features

00:13:09   that have been the number one requested features

00:13:11   for a long time.

00:13:12   I can finally start to do those,

00:13:14   because the sync system will support them.

00:13:16   And that's something that the old system could never do.

00:13:18   So, this is, I feel like, the decision you have to make

00:13:22   when you're managing these big changes

00:13:24   and taking these big risks is like,

00:13:26   yes, you are gonna upset some people.

00:13:28   That's inevitable when you change anything

00:13:30   that people are using. But you have to look at the bigger picture. Like, well, overall,

00:13:34   am I going to please more people than I upset? Is this going to allow me to get new customers

00:13:40   and retain my existing customers better? And unfortunately, those things often require

00:13:47   losing some other people. And I wish it didn't have to, but that's the reality. You can't

00:13:52   please everyone all the time.

00:13:54   Yeah. And I think there's an element of being, as long as you're being thoughtful about it,

00:13:59   don't just make change for change's sake and be pulling the rug out from other people

00:14:02   just because. It's slightly easier. But if there's a good reason, I think that is

00:14:09   an important thing that is very difficult to feel good about. But I think increasingly

00:14:14   I'm in that mindset of understanding that those small single-digit percentage numbers

00:14:21   of users, trying to cater to them is just going to ultimately make the product worse

00:14:29   and is going to make the experience of the 98% of other people have a worse experience,

00:14:35   rather than, you know, and that is way more important. That is such a disproportionately

00:14:41   valuable thing. And there's no strategy that you can take that is going to eliminate issues

00:14:45   with that kind of very long tail situation.

00:14:50   I ran into this recently, this one,

00:14:54   the stat just blew my mind where I was doing

00:14:55   the dark sky APIs going away,

00:14:58   and so I was doing some work with migrating away from it.

00:15:00   And my dark sky API calls were higher

00:15:04   after working through the migration stuff

00:15:07   than I expected them to be.

00:15:10   And I eventually worked this out,

00:15:11   that there was a bug in the very first version

00:15:11   version of Widgetsmith, the very first one on day one that was making way more Dark Sky

00:15:17   calls than it actually should and was happening for everybody, whether or not you had a membership.

00:15:22   So there's still 1% of my user base running that very first version of the app. And it's

00:15:27   like they've never updated the app in two and a half years. And okay, weather for them

00:15:33   is just going to stop working at some point because Dark Sky is going to go away. And

00:15:36   It was just one of those thoughts of like, "Yeah, those people, I can't help them.

00:15:42   There's nothing that I can do to that person who is in a situation where two and a half

00:15:46   years later, they downloaded one version of the app and they have never updated it since.

00:15:51   That's a choice they're making or a situation they're in, whatever the reason for that.

00:15:57   That is not where I should put my effort.

00:15:58   I should put my effort into the 98% of people who are running a version that I released

00:16:03   in the last six months.

00:16:05   That is a group, a cohort that I can work for,

00:16:09   make their life better, make my life better,

00:16:13   and put effort into in a way that is actually useful.

00:16:17   - We are brought to you this episode by Indeed.

00:16:19   When it comes to hiring, you need to trust your gut,

00:16:21   but what if you could give your gut some help?

00:16:24   When you want to find the top talent fast, you need Indeed.

00:16:27   Indeed is the hiring platform.

00:16:29   You can attract, interview, and hire all in one place.

00:16:33   Don't spend hours on multiple job sites

00:16:35   looking for candidates with the right skills

00:16:36   when you can do it all with Indeed.

00:16:38   Find top talent fast with Indeed's suite

00:16:40   of powerful hiring tools like Indeed Instant Match,

00:16:43   Assessments, and Virtual Interviews.

00:16:45   And if you hate waiting, Indeed's US data

00:16:47   shows over 80% of Indeed employers find quality candidates

00:16:51   whose resume on Indeed matches their job description

00:16:53   the moment they sponsor a job.

00:16:55   Instant Match really is incredible.

00:16:57   As soon as you sponsor a post,

00:17:00   you'll get that short list of quality candidates.

00:17:02   You can invite them to apply right away.

00:17:04   Join more than 3 million businesses worldwide using Indeed to hire great talent fast.

00:17:10   Indeed knows that when you're doing everything for your company, you can't afford to overspend

00:17:14   on hiring.

00:17:15   Visit Indeed.com/undertheradar to start hiring now.

00:17:20   That's Indeed spelled I-N-D-E-E-D dot com slash undertheradar.

00:17:26   Indeed.com/undertheradar.

00:17:29   Terms and conditions apply.

00:17:30   Cost per application pricing not available for everyone.

00:17:33   to hire, you need Indeed.

00:17:35   Our thanks to Indeed for the support of this show

00:17:37   and all of Relay FM.

00:17:39   Yeah, so I was, you know, speaking of other changes

00:17:43   that you can't please everybody,

00:17:45   I also made a couple other changes recently in my UI.

00:17:48   I issued a couple of app updates,

00:17:50   trying to solve some long-standing problems

00:17:52   and trying to give people a few little new features

00:17:54   while I work on some bigger behind-the-scenes stuff.

00:17:56   You know, you mentioned you're doing

00:17:57   this big pedometer rewrite.

00:17:59   You know, you kinda started from the second floor up.

00:18:02   I'm trying to do the same thing with Overcast.

00:18:04   And this is another reason why I am doing all the sync engine

00:18:07   work, is that I'm modernizing the back end

00:18:12   and adding all this support for new features,

00:18:14   while at the same time rewriting the entire data layer

00:18:17   in Overcast very slowly as part of my grand rewrite plans

00:18:21   that hopefully getting everything to Swift UI

00:18:23   and Swift and async stuff and Blackbird and everything else.

00:18:28   And so I'm also rewriting the sync protocol

00:18:32   that this new sync layer will sync to the servers with,

00:18:36   trying to optimize, making things as lightweight as possible

00:18:39   on the client.

00:18:39   Because there are certain things right now,

00:18:41   like if you're an Overcast user and you

00:18:43   have a lot of podcast subscriptions,

00:18:46   sync is a very heavy operation for you.

00:18:48   Because every time it syncs, it collects

00:18:52   all episodes of all podcasts you're subscribed to,

00:18:54   and kind of sends all their e-tags to the server to say,

00:18:57   hey, have any of these changed?

00:18:58   And that's on every single sync request.

00:19:00   And so as your collection grows, that's a very heavy operation.

00:19:04   So that's one of the things I'm migrating away from,

00:19:07   trying to make things scale better for both

00:19:09   the client and the servers.

00:19:11   But anyway, in the meantime, while I'm

00:19:13   doing all that, which is going to show basically

00:19:15   nothing to my customers for months and months and months,

00:19:18   I'm trying to do small features in the app that

00:19:20   will kind of give people just signs that I'm still alive

00:19:24   and still working on this app while I do the bigger

00:19:26   stuff behind the scenes.

00:19:27   And so I added some highly requested menu options

00:19:31   for playlist management and stuff.

00:19:33   I also wanted to try to tackle some longstanding issues

00:19:38   that people had with both the new interface

00:19:39   and with the interface in general.

00:19:41   And by the new interface, I mean the one I launched

00:19:43   like two years ago.

00:19:44   It's been a while.

00:19:45   - Something like that, yeah.

00:19:46   - Yeah, but anyway.

00:19:47   So one of the issues with the new interface is that

00:19:52   I changed for the first time in the app's history,

00:19:55   I changed what was shown on the home screen,

00:19:58   like what podcasts are shown there.

00:20:00   And it used to be just a stack of like,

00:20:02   quote, unplayed podcasts and then everything else.

00:20:06   And I found as a user of the app,

00:20:08   it was hard to find stuff.

00:20:10   'Cause I would skim past one of the sections maybe

00:20:12   and not realize that the podcast was in the other section,

00:20:15   you know, whatever.

00:20:16   And that was a common thing,

00:20:16   people complained about it all the time.

00:20:17   So in the quote, new interface,

00:20:20   I changed it to be like these tabs.

00:20:22   This was like, it was like unplayed, active,

00:20:25   and archive.

00:20:26   And these tabs, ever since I launched it,

00:20:30   I've gotten a bunch of feedback on them,

00:20:32   some of which likes them, most of which was like,

00:20:34   can I just please get a list that just has

00:20:36   all of the podcasts in it?

00:20:39   And I eventually wanted that myself, too,

00:20:41   because I was hitting the same problem with the new layout.

00:20:43   I was like, well, if I don't know

00:20:45   whether a podcast is unplayed or active or inactive,

00:20:49   I don't know which one of these tabs to look for it in.

00:20:51   And so I was often either using search

00:20:53   to get around this limitation, or I would check all three lists and that feels terrible.

00:20:58   And so I'm like, you know what, people want an all tab.

00:21:02   So I just added an all tab and I got rid of the archive tab because it confused a lot

00:21:06   of people and everything that was in the archive tab would now be in the all tab amongst everything

00:21:11   else.

00:21:12   So I thought, this is what people actually have been really asking for for the most part,

00:21:17   let me try this.

00:21:19   And I tested it with the beta group for a little while and everyone was fine with it

00:21:22   for the most part, so I was like,

00:21:23   "All right, that sounds good."

00:21:24   And then, I also, you know, the concept of unplayed

00:21:28   in Overcast has never made sense,

00:21:31   because what unplayed has always meant in Overcast

00:21:35   is not yet deleted, which is different from unplayed.

00:21:39   You could have an episode that is played,

00:21:42   you couldn't in 1.0, but fairly soon afterwards

00:21:46   in the apps life cycle, I added the ability

00:21:48   to have an episode that was played,

00:21:50   but that you didn't delete yet.

00:21:51   And so there were all these labels in the app said unplayed,

00:21:56   but then you could literally have a played episode

00:21:58   right below that header.

00:22:00   And so it made no sense.

00:22:02   And that's another thing I've heard about forever.

00:22:04   And so I decided, you know what,

00:22:05   let me address this issue finally too.

00:22:08   Now I will actually change the logic

00:22:10   so that played episodes won't show up

00:22:12   in the unplayed sections.

00:22:14   And I shipped that out as 2023.1.

00:22:17   Everyone hated it.

00:22:18   (laughs)

00:22:21   Well, if you're one of the people who didn't, I'm sorry.

00:22:23   But in this case, you're like a 1%er,

00:22:25   like the previous discussion.

00:22:26   So it's like everyone else hated it.

00:22:29   I heard from so many people, I can't find my episodes now,

00:22:32   where did they go, you broke the way things work.

00:22:33   And I realized the reality is,

00:22:37   oh, and also everyone said they missed the archive section.

00:22:39   That was fun too.

00:22:40   But everyone loved the new all section,

00:22:41   but they still missed archive, and I broke that.

00:22:43   So I broke these two big things for people

00:22:45   because they were used to it the other way.

00:22:46   And I realized, okay, I was correct that something needed to change.

00:22:52   I was hearing from people, something needs to change in these two areas.

00:22:55   Unplayed doesn't make sense, and I can't find where podcasts are, and I want an alt-tab.

00:23:00   So I fairly quickly issued a 2023.2 update that addressed those problems in two different

00:23:07   ways.

00:23:08   So I realized the unplayed thing, people actually had gotten used to the way it worked, and

00:23:13   I was used to the way it worked, and I couldn't find stuff after it was played either.

00:23:15   And so I realized that it wasn't that the behavior was wrong,

00:23:20   the terminology was just wrong.

00:23:22   So I just changed the word unplayed to current,

00:23:25   which there is no good single word that I can find

00:23:28   that describes the status of episodes.

00:23:30   Current is not the best,

00:23:31   but I couldn't think of a better one.

00:23:33   If I can in the future, I'll change it again.

00:23:35   And so I just changed everything back,

00:23:37   all right, it works the way,

00:23:38   the behavior will go back to the way it was before.

00:23:41   I was just changing the label

00:23:43   so that the label now matches the behavior

00:23:45   rather than changing the behavior to match the label.

00:23:48   And that was the right move.

00:23:50   Now everyone's fine, no one's mad,

00:23:51   well now like two people are mad

00:23:53   'cause they like the change I made,

00:23:54   but everyone else was fine, okay.

00:23:57   And then with the all versus archive

00:23:59   versus unplayed slash current slash active,

00:24:02   I realized what I want,

00:24:04   and I think I should trust what I want

00:24:05   because I made this app for myself for the most part,

00:24:08   and so people who have come to this app

00:24:10   usually are people who want things

00:24:12   the way I want them for the most part

00:24:14   because otherwise they wouldn't have stuck with my app.

00:24:17   And what I wanted, I wanted the all list.

00:24:21   I also wanted an archive list.

00:24:23   And the old active list I never used.

00:24:25   So I just changed that section

00:24:27   to now just be current, all, and archived.

00:24:31   That seems to be satisfying more people on the whole.

00:24:36   And it's not perfect, and honestly,

00:24:38   once I, when I do the big Swift UI rewrite,

00:24:41   my plan is to actually make that customizable

00:24:43   so that you can have whatever sections you want there.

00:24:45   And I'll give you three or four or five different possibilities,

00:24:48   and you can slot them in wherever you want.

00:24:50   Because that's much, much easier to do in Swift UI

00:24:53   than it is in my current massive UI table view or UI collection

00:24:57   view hack thing.

00:25:01   That's very difficult for me to do now,

00:25:03   but that will be very easy for me to do in the future.

00:25:05   And so my plan is this will all become customizable,

00:25:08   among other things in the app.

00:25:10   But in the meantime, I've settled on something

00:25:12   that I think works better for more people in the old system.

00:25:15   And these were all huge risks,

00:25:17   that changing long-standing things in the app.

00:25:19   But I'm happy that I got here,

00:25:22   and I did have to anger some people and lose some people

00:25:25   and get some one-star reviews along the way,

00:25:28   as you do with any change,

00:25:29   but overall, I think this is better for more people.

00:25:32   - Yeah, and I think there's definitely some couple lessons

00:25:35   in that story you just told,

00:25:38   where it's that sense of, I think,

00:25:40   It's important to realize that changes you're making are not typically irreversible. That

00:25:49   if you make a change, like that fear that I was talking about at the beginning of the

00:25:52   episode of this overwhelming sense of dread that I'm going to just destroy everything

00:25:56   and it's all going to just go down in flames, it's possible, pretty unlikely. Most changes,

00:26:02   if it turns out you got it the wrong way around, like which side was the 1%, if you got that

00:26:09   It's like, you can undo it. It's fine. You can go in and undo what you change, just

00:26:14   roll back, whatever that's going to look like for you. Usually that's possible. So

00:26:19   don't be so precious with these changes and think that, "Oh no, if I do this, I can

00:26:25   never go back." I mean, I ran into a funny one with pedometer recently where when you

00:26:29   reach your goal in pedometer, there's confetti that comes down from the top of the screen.

00:26:33   So it's been in there for a long time. People love it.

00:26:35   I love it. It's delightful.

00:26:37   loves it. I started getting beta feedback from people who were saying that the new confetti,

00:26:41   which I wrote written in SwiftUI, wasn't as fun as the old confetti. And at first, the

00:26:49   first person who said that, it's like, "Oh, whatever." And then it's like, I started getting

00:26:51   many people who were in the beta who were saying this to me, and I was like, "Oh, no.

00:26:55   I'm not going to mess with people's confetti. I'm going to undo this change." And so now

00:26:58   it is just the old CA, like CA emitter view, UI kit confetti, just in a UI view representable

00:27:07   inside of SwiftUI. It's like, "I am not messing with that." I don't want people

00:27:10   to be like, "Oh, the new confetti's sad." It's like, "No, I do not want to be on

00:27:15   the wrong side of that change." So I just undid it. It's fine.

00:27:18   And I think there's a wisdom in that, of being flexible. Pushing your app forward,

00:27:23   making sure that you find ways to make it better, and if it turns out you pushed slightly

00:27:28   too far, it's like, "Ease back. Back it up, change it." Ideally, you find this

00:27:32   out when you're doing some kind of beta test rather than, you know, when the 99% of people

00:27:38   who are grumpy is 99% of a few hundred people, it's much easier to manage than if it's 99%

00:27:44   of the entire user base. But still, when that happens, just ease up, back up, change it,

00:27:49   and you'll be fine.

00:27:51   Yeah. Yeah. For me, to undo my unread logic change, it was literally just going into my

00:28:00   version control and just finding that one commit that had those changes and just undoing

00:28:05   it and then changing all the labels to say current instead of un-rattling it was super

00:28:08   easy.

00:28:09   You know, it's harder when you're doing a massive re-write or a huge re-design, that's

00:28:14   way harder to roll back and in most cases you're better off not rolling it back and

00:28:19   just kind of making tweaks to be more successful rather than undoing months of work.

00:28:25   But the fast stuff you can undo pretty quickly and it's not that big of a deal and it's

00:28:29   worth experimenting with.

00:28:30   Yeah, and I think just or moreover is just being open to that is I think the most like what that looks like technically like is

00:28:36   Gonna widely vary and like rolling back isn't necessarily the right thing always sometimes

00:28:40   It's gonna be finding a new middle ground listening to what you know sometimes when people are upset about a change

00:28:46   It isn't that it changed. It's that you're exposing

00:28:48   Some assumption they were making about the app or some workflow that you were completely oblivious to

00:28:54   That is now being surfaced because of a change you made and it's like listen is like step number one

00:29:00   and all these things.

00:29:01   It's like, listen, try and understand what it is,

00:29:03   and then make the change.

00:29:04   And continue to move the app better.

00:29:06   Don't get anchored in the past,

00:29:07   and instead just keep making it better,

00:29:09   both for yourself and for your users.

00:29:11   - Yeah, and don't just make everything a setting.

00:29:13   - Yeah, that's right.

00:29:14   - Thanks for listening, everybody,

00:29:15   and we will talk to you in two weeks.

00:29:17   - Bye.

00:29:18   [ Silence ]