PodSearch

Developing Perspective

#119: Go Big or Ship?

 

00:00:00 ◼   ► Hello and welcome to Developing Perspective.

00:00:05 ◼   ► Developing Perspective is a podcast discussing news of note in iOS development, Apple, and the like.

00:00:07 ◼   ► I'm your host, David Smith. I'm an independent iOS and Mac developer based in Herndon, Virginia.

00:00:12 ◼   ► This is show number 119, and today is Friday, April 12th.

00:00:16 ◼   ► Developing Perspective is never longer than 15 minutes, so let's get started.

00:00:20 ◼   ► All right, I've got four quick topics to talk through today.

00:00:24 ◼   ► And first I was going to start off by talking a little bit about just kind of letting an opinion about the whole thing this week

00:00:26 ◼   ► the whole thing this week about app rejections,

00:00:28 ◼   ► the App Store policy being pulled,

00:00:30 ◼   ► and that kind of came out of the AppGratis,

00:00:34 ◼   ► I don't even know, debacle, whatever you want to call it,

00:00:36 ◼   ► scenario.

00:00:37 ◼   ► And if you haven't heard about it,

00:00:38 ◼   ► basically there was this app that was doing app promotion,

00:00:43 ◼   ► providing an alternate way to find apps

00:00:45 ◼   ► that you could pay to buy things.

00:00:48 ◼   ► I don't really understand at all exactly how their business

00:00:50 ◼   ► model worked.

00:00:51 ◼   ► But the reality is, the short version

00:00:53 ◼   ► is Apple decided to reject or pull the app from the store for violating two lines in

00:00:59 ◼   ► the app review guidelines.

00:01:00 ◼   ► And there was a bit of a back and forth about that.

00:01:02 ◼   ► Like, what does that mean?

00:01:03 ◼   ► It's like, here's this company with many people, a lot of funding, and all of a sudden their

00:01:06 ◼   ► business just disappears overnight.

00:01:07 ◼   ► Like, that's a little bit disconcerting, rough, especially if you're somebody who makes your

00:01:12 ◼   ► business and you're living in the store.

00:01:14 ◼   ► It just reminds me of, it's just one of those things of, if you want to work in this business,

00:01:22 ◼   ► If you want to make your living in the App Store, it is a simple reality and a truth

00:01:27 ◼   ► that that is just the nature of the beast.

00:01:29 ◼   ► And I've talked about this many times before, how I like that.

00:01:33 ◼   ► As much as it's disconcerting, as much as I think that there are problems and challenges

00:01:36 ◼   ► and there are things that Apple doesn't do right, I like that that's the case, because

00:01:40 ◼   ► I think in the broad strokes it improves the quality of the store.

00:01:43 ◼   ► That generally speaking, what Apple's goal is usually is to make the App Store experience

00:01:48 ◼   ► the best as it can possibly be for its customers. And that,

00:01:53 ◼   ► broadly speaking, it is a fair system for some definition of

00:01:57 ◼   ► fair. And so you just have to understand that if you do

00:02:01 ◼   ► anything that gets close to the line, you're you're gambling at

00:02:05 ◼   ► that point. It's not and you just have to go into it with

00:02:08 ◼   ► that. But that mentality and that mindset, I think, and

00:02:11 ◼   ► that's just kind of the way it is. It's like if there's a, you

00:02:13 ◼   ► know, it's like high risk, high reward, the closer you get to

00:02:15 ◼   ► that line. And it's just interesting because you can, it

00:02:18 ◼   ► It doesn't mean that you have to be totally paranoid about it, but it's just understanding

00:02:22 ◼   ► that that's what you're doing.

00:02:23 ◼   ► And the closer you get, if you read through the app review guidelines and there's a line

00:02:26 ◼   ► in there that's getting close to something that you're wanting to do or you think you

00:02:30 ◼   ► found kind of this angle or this niche, that's just the reality is that you're putting yourself

00:02:35 ◼   ► and your business in a place that could disappear overnight.

00:02:39 ◼   ► And that's just the way it is.

00:02:41 ◼   ► And I like that in that I think the end result is that it's a better store.

00:02:48 ◼   ► The individual cases and the people involved and all that kind of thing can be very difficult,

00:02:51 ◼   ► very tragic and very sad.

00:02:54 ◼   ► But it's just like staying away from those types of areas and those types of things is

00:02:59 ◼   ► one approach to take.

00:03:01 ◼   ► And then two is just to accept it, mark it up as a business risk and kind of go with

00:03:07 ◼   ► it.

00:03:08 ◼   ► And that's just kind of where you are.

00:03:10 ◼   ► It's one of those things that there is no, that doesn't make me, it's never happy when

00:03:15 ◼   ► these things happen.

00:03:16 ◼   ► happen all the time, or more often enough

00:03:19 ◼   ► that it certainly is a pervasive problem.

00:03:22 ◼   ► But the reality is, app rejection is just part

00:03:26 ◼   ► of having this kind of store experience.

00:03:29 ◼   ► And that's, on the plus side, I think is why

00:03:31 ◼   ► the app store is so successful, and there's a high degree

00:03:33 ◼   ► of user trust and those types of things.

00:03:36 ◼   ► You know, and you can get into, like in this case,

00:03:38 ◼   ► I think one of the policies is about creating

00:03:40 ◼   ► alternate app store experiences and about

00:03:43 ◼   ► incentivizing downloads and those types of things.

00:03:48 ◼   ► The goal is to make sure that the charts

00:03:51 ◼   ► and the store ranking and things are reflective

00:03:53 ◼   ► of the actual genuine user interest in applications

00:03:57 ◼   ► rather than in just who can write the biggest check,

00:04:02 ◼   ► which I think is a good thing.

00:04:07 ◼   ► The exact implementation, complicated.

00:04:08 ◼   ► But the goal and the spirit behind it, I think, makes sense.

00:04:08 ◼   ► And so that's kind of where I come down on those types of things.

00:04:11 ◼   ► But I just wanted to sort of put that out there.

00:04:15 ◼   ► Next thing I wanted to talk about is something more architectural, switching to much more

00:04:19 ◼   ► technical.

00:04:20 ◼   ► But it was something that I've been working on a lot in feed wrangler that I thought would

00:04:22 ◼   ► be an interesting thing to share, is an approach to building things that I found to be very,

00:04:27 ◼   ► very good in terms of performance and structure and sort of reliability maybe is the best

00:04:36 ◼   ► way to think about it.

00:04:37 ◼   ► And it's the ability to make your application as much as you can into discrete operations

00:04:44 ◼   ► that are rerunnable.

00:04:47 ◼   ► And this is something that I've been doing for a lot of, I feel there's a lot of operations

00:04:51 ◼   ► and things in feed wrangler where this is the case.

00:04:54 ◼   ► And as an example of something like this, it's rather than, for example, in feed wrangler

00:04:57 ◼   ► when you mark something as red, I could just make the server request to do that.

00:05:01 ◼   ► I could just say, you know, whatever, you know, call feed wrangler.net and say, you

00:05:05 ◼   ► know, mark as red.

00:05:06 ◼   ► And I can do it in a direct call based on,

00:05:09 ◼   ► you know, kicked off when the user hits that button.

00:05:12 ◼   ► However, if I do that, it creates all these kind

00:05:14 ◼   ► of problems and challenges down the road.

00:05:16 ◼   ► What if that request times out?

00:05:18 ◼   ► If there's a network connectivity problem?

00:05:20 ◼   ► If they go into a tunnel and it doesn't get through?

00:05:22 ◼   ► Now you have this weird state of how do you show that

00:05:24 ◼   ► to your user in a way that is,

00:05:26 ◼   ► that A, is reasonable and useful to them.

00:05:30 ◼   ► So obviously, if there's an error that happens,

00:05:33 ◼   ► maybe that error is actually only gonna happen

00:05:35 ◼   ► 30 seconds down the road.

00:05:36 ◼   ► And the users moved on.

00:05:37 ◼   ► The users started doing other things in the application.

00:05:40 ◼   ► And all of a sudden, you pop up a message saying, failed.

00:05:42 ◼   ► It's like, couldn't connect to server.

00:05:43 ◼   ► It's like, that could be totally unrelated.

00:05:45 ◼   ► And the server connectivity could actually be back now.

00:05:48 ◼   ► And so what I tend to do, what I've been heading towards,

00:05:51 ◼   ► is to structure most of my-- as much as I can in my application

00:05:54 ◼   ► on more of a queue basis.

00:05:56 ◼   ► And that's a queue, you know, Q-U-E-U-E.

00:05:59 ◼   ► That what I want to do is make it

00:06:02 ◼   ► so that I can just kind of rerun these operations.

00:06:04 ◼   ► So I had to sort of destruction my application in that way.

00:06:07 ◼   ► And so instead of doing that, when I have this read request,

00:06:11 ◼   ► I make an operation.

00:06:12 ◼   ► I put it on a queue, and then I try and run it.

00:06:15 ◼   ► And it tries to get the server.

00:06:16 ◼   ► If it doesn't work, then I'll try it again

00:06:19 ◼   ► at various timeouts and things.

00:06:22 ◼   ► And obviously, there's a lot of nuance

00:06:23 ◼   ► to getting that exactly right.

00:06:25 ◼   ► But in general, what I found is that makes

00:06:26 ◼   ► my app much more reliable and much more simple in many ways

00:06:29 ◼   ► to build, because I don't have to deal with quite as many error

00:06:33 ◼   ► cases.

00:06:33 ◼   ► There are still certain cases that you need to deal with and show user feedback and things.

00:06:37 ◼   ► You know, if there's just no connectivity and they're trying to do a lot of stuff, it's

00:06:40 ◼   ► like you need to show them something probably.

00:06:42 ◼   ► But generally speaking, it sort of is the app will kind of naturally work itself into

00:06:47 ◼   ► a state that is correct over time rather than having sort of constantly badgering the user

00:06:53 ◼   ► about that.

00:06:54 ◼   ► And so it's just something that I've been doing a lot.

00:06:55 ◼   ► And I do the same thing a lot on my website and on the web services side of it as well,

00:07:00 ◼   ► which I think I mentioned before.

00:07:01 ◼   ► but it works really well there, where rather than,

00:07:04 ◼   ► for example, when I'm going out and doing feed parsing

00:07:07 ◼   ► and feed aggregation, I'm running out my spiders

00:07:09 ◼   ► and they're going off and they're pulling in all,

00:07:11 ◼   ► you know, filling in thousands of feeds

00:07:12 ◼   ► and parsing them and processing them.

00:07:14 ◼   ► Each one of those requests to pull a feed

00:07:18 ◼   ► is created as its own distinct operation,

00:07:20 ◼   ► put in a queue, and then run.

00:07:22 ◼   ► And that means, if anything goes weird with it,

00:07:24 ◼   ► if anything gets stuck, it doesn't affect anybody else.

00:07:27 ◼   ► They all kind of go their natural way.

00:07:29 ◼   ► and if it fails, it can just be put back onto the queue

00:07:32 ◼   ► to be retried if I want or not.

00:07:34 ◼   ► And I found that that works really well

00:07:36 ◼   ► for reliability, for scaling.

00:07:38 ◼   ► And another great thing about queuing

00:07:40 ◼   ► is an approach and a structure.

00:07:42 ◼   ► Because all the operations are atomic,

00:07:44 ◼   ► you're designing your app to be parallelizable,

00:07:46 ◼   ► which is great, both on the server side and on the device,

00:07:50 ◼   ► that if you focus on making it parallelizable,

00:07:53 ◼   ► your performance can go up a lot.

00:07:55 ◼   ► So for example, with my making network requests,

00:08:02 ◼   ► these atomic operations that can be run essentially

00:08:04 ◼   ► in any order, as much as I-- to some approximation,

00:08:07 ◼   ► I can go and run three of them at a time.

00:08:09 ◼   ► And that's OK, because of the way that it's structured.

00:08:12 ◼   ► They're not dependent on each other.

00:08:13 ◼   ► They're not queuing up.

00:08:15 ◼   ► You can make things a lot more performant that way.

00:08:18 ◼   ► Next thing I wanted to talk about is something

00:08:20 ◼   ► that I've been struggling with a little bit in feed wrangler

00:08:22 ◼   ► that I thought was an interesting question.

00:08:25 ◼   ► And this is understanding perfection or understanding,

00:08:29 ◼   ► do you need to ship something perfect, wonderful, exactly

00:08:34 ◼   ► what you want it to be?

00:08:36 ◼   ► Or is it more important to ship?

00:08:38 ◼   ► And this is a complicated question.

00:08:39 ◼   ► This is something that I've been really wrestling with recently.

00:08:42 ◼   ► I think I mentioned in the last episode

00:08:43 ◼   ► that I'm trying to ship the iOS version of Feed Wrangler today.

00:08:46 ◼   ► It's Friday, and I'm trying to get it out

00:08:48 ◼   ► by the end of the week.

00:08:49 ◼   ► And that's entirely an artificial timeline

00:08:51 ◼   ► and pressure that I'm putting on myself.

00:08:54 ◼   ► And the goal of that, obviously, is like,

00:08:55 ◼   ► feed wrangler is kind of a unique situation

00:08:57 ◼   ► where it's specifically trying to target a market that

00:09:01 ◼   ► is time limited.

00:09:03 ◼   ► On July 1st, Google Reader is going to go away.

00:09:06 ◼   ► And so I'm trying to create a replacement for that,

00:09:10 ◼   ► unintentionally in some ways.

00:09:11 ◼   ► But the reality is I'm creating something

00:09:14 ◼   ► that will be a replacement for that for many people.

00:09:16 ◼   ► And so I want to get that out in enough time

00:09:19 ◼   ► to kind of make that migration.

00:09:20 ◼   ► And so I'm kind of putting myself

00:09:21 ◼   ► under somewhat of an artificial constraint to do that.

00:09:25 ◼   ► But it's a challenging thing to understand

00:09:29 ◼   ► what's good enough and where do you draw those lines?

00:09:31 ◼   ► Where do you decide?

00:09:34 ◼   ► And generally what I've been trying to do is

00:09:35 ◼   ► I'm taking the approach that,

00:09:38 ◼   ► I have a couple of parameters.

00:09:39 ◼   ► One, I don't ever really like the concept

00:09:41 ◼   ► of charging people money for anything

00:09:44 ◼   ► that I would label as beta software.

00:09:46 ◼   ► And I've seen this happen a couple of times.

00:09:47 ◼   ► You kind of hear people ship things,

00:09:49 ◼   ► it's like, oh, it's still in beta.

00:09:50 ◼   ► It always feels weird to me if you're charging for that,

00:09:52 ◼   ► because in my mind anyway, what beta means is

00:09:54 ◼   ► I know it's broken in some way.

00:09:58 ◼   ► And if I know it's broken in a way that's enough

00:10:01 ◼   ► that I'm really kind of calling it a beta,

00:10:02 ◼   ► that feels a little funny to then take money for that.

00:10:04 ◼   ► And so what I'd rather do is scale the application down

00:10:09 ◼   ► to a point that it's, I would say it's production ready,

00:10:13 ◼   ► charge for that, and then grow it out.

00:10:15 ◼   ► And that's generally, I think, the approach

00:10:16 ◼   ► that I've been taking with FeedWrangler,

00:10:18 ◼   ► and I think it generally works,

00:10:19 ◼   ► that rather than worrying about having,

00:10:21 ◼   ► I have this long list of features and things

00:10:23 ◼   ► that I'm working on and things that will come down the road,

00:10:25 ◼   ► or approaches or things that I can do

00:10:27 ◼   ► that will just come naturally down the road.

00:10:31 ◼   ► And I'm thinking rather than being too focused

00:10:33 ◼   ► on making sure they're all in there before I ship,

00:10:35 ◼   ► I'm saying, okay, I'm going to narrow that down,

00:10:38 ◼   ► polish, refine as much as I can,

00:10:40 ◼   ► make it really reliable, solid, and then ship that.

00:10:43 ◼   ► And know that I've got a lot of good fodder for 1.1, 1.2, 1.3.

00:10:49 ◼   ► And this is something I didn't check the weather that I think was really well received, where

00:10:52 ◼   ► if you get into this habit of, you know, once you've launched an app to ship updates pretty

00:10:56 ◼   ► quickly, I think it builds a lot of trust and endearment from your users, because it

00:11:01 ◼   ► feels like you're really engaged and you're really responsive to what they're saying,

00:11:04 ◼   ► to the problems they're having, and to fixing those things.

00:11:07 ◼   ► So that's kind of what I'm doing.

00:11:08 ◼   ► It's sort of like, rather than going big, I'm just trying to ship a solid kernel that

00:11:14 ◼   ► works exactly how I want it.

00:11:17 ◼   ► and then I'll add in some more bells and whistles

00:11:19 ◼   ► based on what users want.

00:11:21 ◼   ► And that also speaks to a little bit of the problem of

00:11:23 ◼   ► whenever you ship something,

00:11:26 ◼   ► no matter how many beta feedback you get,

00:11:29 ◼   ► your customers are gonna use your application

00:11:31 ◼   ► in ways that you never expected or imagined.

00:11:33 ◼   ► And that's a good thing.

00:11:34 ◼   ► It can create opportunities and drive it in directions

00:11:37 ◼   ► that you may not necessarily have expected,

00:11:39 ◼   ► and that can often be really, really helpful

00:11:41 ◼   ► for deriving the product.

00:11:42 ◼   ► And so you can end up spending time on features

00:11:44 ◼   ► that no one will use.

00:11:45 ◼   ► Or, on the flip side, alternatively better,

00:11:48 ◼   ► to spend that time polishing things that you think,

00:11:51 ◼   ► that you know people will use that are core functionality,

00:11:54 ◼   ► and then building the extra things

00:11:55 ◼   ► based on what people really want,

00:11:56 ◼   ► what are the needs people have.

00:11:58 ◼   ► And then when you give it to them, people feel great,

00:12:00 ◼   ► because they feel like they just got a bonus,

00:12:01 ◼   ► that they got something in addition,

00:12:02 ◼   ► it's like they bought X and they just got X plus Y,

00:12:05 ◼   ► which is kinda cool.

00:12:07 ◼   ► All right, and the last thing I wanted to talk about

00:12:09 ◼   ► is just a quick mention of some changes that Linode did.

00:12:12 ◼   ► This week, I think I've mentioned many times,

00:12:14 ◼   ► I'm a big Linode fan,

00:12:15 ◼   ► where I host almost all my stuff.

00:12:17 ◼   ► And it's kind of fascinating to me

00:12:18 ◼   ► how web services just continues the march towards cheaper

00:12:23 ◼   ► and better, just keeps going.

00:12:25 ◼   ► And it's kind of remarkable to me,

00:12:27 ◼   ► where I was looking at it this week.

00:12:29 ◼   ► They've done this whole series of different upgrades

00:12:31 ◼   ► and changes to their servers.

00:12:33 ◼   ► And the most recent one they announced

00:12:35 ◼   ► is that they're changing the way that-- their memory pricing,

00:12:37 ◼   ► basically.

00:12:38 ◼   ► And they doubled the memory for the same price,

00:12:41 ◼   ► essentially, for all of their machines,

00:12:44 ◼   ► that you can rent.

00:12:46 ◼   ► And the kind of crazy part for that for me

00:12:48 ◼   ► is that essentially what they did is in one blog post,

00:12:52 ◼   ► they halved my hosting costs for almost all of what I do.

00:12:56 ◼   ► For example, right now my recipe book is about $300 a month

00:13:00 ◼   ► is what I pay for the service that I have there.

00:13:02 ◼   ► And it'll go to $160 after I migrate over

00:13:05 ◼   ► to the new structure because for me, the majority of what I do

00:13:08 ◼   ► is memory bound rather than CPU, network, bandwidth, storage,

00:13:12 ◼   ► those types of binds.

00:13:13 ◼   ► And so if they were giving double the memory

00:13:16 ◼   ► for the same price, for almost all my things,

00:13:20 ◼   ► I can just bump down one tier, migrate over to that,

00:13:23 ◼   ► and have exactly the same machine that works perfectly

00:13:25 ◼   ► and does exactly what I want, but for half the cost.

00:13:28 ◼   ► Obviously, for some people, it would make sense.

00:13:30 ◼   ► They'd rather just have twice the memory,

00:13:31 ◼   ► and that'd be great.

00:13:33 ◼   ► But for what I do, most of it, the memory

00:13:35 ◼   ► is the limiting factor, but it's in a way

00:13:37 ◼   ► that I want to still have multiple machines.

00:13:39 ◼   ► So the limiting factor for the number of requests

00:13:42 ◼   ► that a lot of my web services can handle

00:13:45 ◼   ► is fairly memory oriented for a lot of what I do,

00:13:48 ◼   ► but I still want to have multiple machines for redundancy

00:13:50 ◼   ► and for latency and those types of things.

00:13:52 ◼   ► So it's just kind of one of those fascinating things

00:13:54 ◼   ► how web services are just more and more

00:13:57 ◼   ► heading in that direction.

00:13:58 ◼   ► And it creates this delightful pressure and competitiveness

00:14:02 ◼   ► among hosting providers that I just think is really cool.

00:14:04 ◼   ► So anyway, that's it for today's show.

00:14:06 ◼   ► Hopefully I'll be shipping Feed Wrangler this afternoon.

00:14:08 ◼   ► So wish me luck for that.

00:14:10 ◼   ► And hopefully, again, launching probably in about two weeks.

00:14:14 ◼   ► So I'm looking forward to that, and I'll

00:14:15 ◼   ► have a lot to say on the show.

00:14:17 ◼   ► If you have any comments, just let me know on Twitter.

00:14:19 ◼   ► Underscore David Smith there.

00:14:20 ◼   ► On AppNet, I'm David Smith.

00:14:22 ◼   ► And otherwise, have a great weekend.

00:14:23 ◼   ► Happy coding, and I will talk to you later.