Developing Perspective

#103: Coding Sins.


00:00:00   Hello, and welcome to Developing Perspective.

00:00:03   Developing Perspective is a podcast discussing news of note in iOS development, Apple, and

00:00:07   the like.

00:00:08   I'm your host, David Smith.

00:00:09   I'm an independent iOS and Mac developer based in Heron, Virginia.

00:00:12   This is show number 103.

00:00:15   Today is Tuesday, January 8th.

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

00:00:20   All right, so the topic I'm going to be talking about today, it relates to some, I guess you

00:00:24   could call it best practice, some lessons learned, some things like that.

00:00:28   And this is coming out of a great series of articles that I've linked in the show notes

00:00:32   that got started by a post by Ash Furrow talking about the seven deadly sins of a modern objective

00:00:38   sea.

00:00:39   And there was a great follow up to that written by Brett Simmons on Inessential talking about

00:00:45   some of those and adding into some of his own.

00:00:47   And there just are a lot of really good things to kind of talk about.

00:00:50   And this is, if you haven't already sort of caught on, this is going to be a fairly technical

00:00:54   This is a technical episode talking about fairly low level

00:00:57   things that an iOS developer or a Mac developer

00:01:01   would want to be aware of, would want to think about,

00:01:03   and would want to wrap their arms around.

00:01:07   This isn't one of my higher level, more hand-wavy ones.

00:01:10   So first I'm going to start off by talking about where it all

00:01:13   started, which is Ash Furrow's post,

00:01:15   The Seven Deadly Sins of the Modern Objective-C.

00:01:18   And the first one he talks about,

00:01:19   which I very much agree with, is it's

00:01:22   very dangerous to have one big nib file or zip file.

00:01:27   And really what you're trying to avoid there

00:01:29   is you're trying to avoid the situation where A, there's

00:01:33   the performance hit of having this massive view hierarchy all

00:01:37   put into a nib, because you have to load all of that dynamically

00:01:41   or at once when it loads.

00:01:43   And there's ways you can get around it in storyboarding.

00:01:46   But it's very dangerous to have too much of interface

00:01:49   in one nib file.

00:01:50   You can load multiple nibs.

00:01:52   And this is actually an example of something

00:01:53   that I do in Check the Weather, for example, where

00:01:57   the actual layout is all done with all

00:02:01   the different components or different nibs,

00:02:03   I guess is what I'm trying to get at.

00:02:05   The top, the left, right, and bottom

00:02:07   are all individual nibs, as well as the main dashboard,

00:02:10   if you're familiar with the app or if you can go look it up.

00:02:13   But they're all loaded independently,

00:02:15   rather than putting it into one big nib file

00:02:17   and then just moving views around.

00:02:18   And a lot of that is for the performance reason.

00:02:20   I don't load the side panels until the first time

00:02:22   the user wants to do it.

00:02:23   And it's something that I think in general

00:02:25   is something that you really want to make sure

00:02:28   that you avoid.

00:02:29   And it's good practice and good cleanliness

00:02:31   too to separate as much as you can things

00:02:34   into different concerns.

00:02:36   The next thing I want to talk about, which is his number two,

00:02:39   is not using dot syntax consistently.

00:02:42   A lot of people go back and forth about dot syntax

00:02:45   and whether it's the right thing to do.

00:02:47   Usually what it comes down to is where your background is.

00:02:51   If you're a long time Objective C programmer who

00:02:53   has been doing it since before the dot syntax was introduced,

00:02:56   you are probably anti it.

00:02:58   If you're coming from a language like Java, where it's

00:03:01   essentially that's the way that you would think about it,

00:03:04   you're probably more apt to use it.

00:03:05   Generally, I think the best thing he's saying here

00:03:07   is make sure you're using it consistently.

00:03:09   I think dot syntax works really well.

00:03:11   And the way I tend to use it is I

00:03:13   tend to use it pretty much exclusively for properties.

00:03:16   That's pretty much the only-- and essentially,

00:03:19   it's properties accessing internal IVRs.

00:03:21   I never use dot syntax when calling a method,

00:03:24   or even though you could.

00:03:25   I've seen an interesting thing recently.

00:03:27   Someone was talking about how they've

00:03:28   started using it for methods without side effects, which

00:03:33   I'm not so sure I'm convinced on either.

00:03:36   Because then you start getting into, well,

00:03:37   how do you define a side effect?

00:03:38   How do you know if it has a side effect?

00:03:40   An example of that would be calling, for example,

00:03:42   dot class on something.

00:03:44   So it sort of condenses it.

00:03:46   But any time you're using something, you have to make sure you use it consistently.

00:03:49   I think that's the more important thing.

00:03:53   The rest of his things, there's not a lot that I necessarily wanted to get into that

00:03:56   I didn't have as strong opinions about.

00:03:58   But I wanted to move over into Brett Simmons' response, which I think had a ton of really

00:04:03   good ones.

00:04:04   And his blog post is titled, "Coder's in the Hands of an Angry God," which is obviously

00:04:12   a follow-up to Seven Deadly Sins of the Modern Objective-C. And I think the thing that he

00:04:16   said that really caught my attention and something that I've been thinking about but never really

00:04:21   got into, one of the things Ash mentioned is that he says we don't do enough automated

00:04:25   testing. And I think that's maybe true. I come from a Rails background where that was

00:04:30   a much bigger thing. But in Objective-C, I've never found a really good way to do it. And

00:04:34   it's really hard and it's really annoying and there's not great tools for it. And a

00:04:37   lot of people say, "Well, you know, you just need to work on it." And that would encourage

00:04:41   tool makers, and so on.

00:04:43   But the reality is, automated testing doesn't necessarily,

00:04:47   it only pays off in very narrow areas in applications,

00:04:52   especially because a lot of it's UI based,

00:04:54   and all these types of problems that are tricky.

00:04:57   There's a lot of asynchronous code,

00:04:59   especially since GCD was introduced in iOS 4,

00:05:02   there's a lot of things that make it really tricky

00:05:05   to do good test coverage.

00:05:06   But I think Brett's response is, I think,

00:05:08   very, very reasonable, and something that I've been

00:05:11   I'm looking for-- and I think this is a great way--

00:05:14   is instead of that, to start introducing more NS asserts

00:05:18   into my code.

00:05:19   If you're not familiar with it, basically, NS assert

00:05:21   is you say NS assert, and then you pass in two parameters.

00:05:25   You pass in an expression who should

00:05:28   result to a Boolean and a description, basically.

00:05:32   And if that Boolean ever evaluates to false,

00:05:38   I think it is.

00:05:41   Yeah, I think it's false.

00:05:44   The assertion will blow up, and your app will stop.

00:05:48   And you'll be told, this assertion,

00:05:51   the thing that you said should always be true,

00:05:54   is in fact not.

00:05:55   And the reality of what that does

00:05:57   is it lets you put these checks into your code that'll catch

00:06:01   problems much more quickly.

00:06:03   And I think he has a great example.

00:06:06   NS assert not NS thread as main thread is what he's testing for.

00:06:11   And so it's a great way to put that into some code

00:06:13   that you know should only ever be called in the background.

00:06:16   And so if it is called on the main thread,

00:06:18   you want that app, you want it to be very aware.

00:06:24   So when you're testing, you're going to catch that.

00:06:26   Now, the other thing that's tricky with NS assert

00:06:29   is in theory, it should be fine to leave in there for production

00:06:33   once you've deployed it, but it always

00:06:34   makes me a little nervous when I'm putting in something

00:06:37   in my code that I know will crash rather than putting

00:06:40   the app into a funny state.

00:06:42   That's always a kind of tricky thing.

00:06:43   In theory, if you're writing good assertions,

00:06:44   it shouldn't matter.

00:06:45   But that's the only part that I'm always a little uneasy about.

00:06:48   But generally speaking, that just

00:06:49   means you have to be very careful and thoughtful about how

00:06:52   you use them rather than going-- sort of just putting them

00:06:54   in willy-nilly.

00:06:56   The next areas that I wanted to talk about

00:06:58   is something that he actually has-- Brent actually

00:07:00   had a whole blog post about, which

00:07:02   is talking about the UITableViewCell is not a controller.

00:07:05   There's been a whole series of things

00:07:07   that he talked about this.

00:07:08   But the big thing that I think he mentioned here

00:07:11   that I thought was really clever or is important

00:07:14   is that to try as much as we can to make sure

00:07:17   that our UITableViewCells don't know very much about the model

00:07:22   they're displaying.

00:07:23   For them not to turn into the controller,

00:07:25   for them to not be doing a lot of the stuff that

00:07:28   should really be outside of them.

00:07:30   A UITableViewCell should really just be a display.

00:07:33   It shouldn't really care too much about what it's displaying.

00:07:37   This is something I know I've run into myself, where

00:07:39   it's often easy to think, well, I'll just do a custom TableView

00:07:42   Cell.

00:07:42   I'll pass in my model object.

00:07:43   And then the cell will take care of displaying that.

00:07:47   And then I've gotten bitten by that.

00:07:49   An example of that is where in my audiobooks app,

00:07:53   I display a lot of books.

00:07:54   So I have a custom TableViewCell for displaying a book,

00:07:56   a title, an author, a type, those types of things.

00:07:59   And most of the time, it's all coming out of my core data

00:08:02   object is what I'm displaying.

00:08:04   It's my book object.

00:08:06   But there's an area where I display popular books.

00:08:08   And those are actually coming out of a JSON blob,

00:08:10   and so they're actually a dictionary.

00:08:12   And so it's kind of awkward where I was originally

00:08:16   doing some hard coding to be pulling directly

00:08:18   from a book, NS managed object.

00:08:21   And suddenly, it's like, that doesn't really work.

00:08:23   And I have to re-architect and change it.

00:08:25   And I think what he's saying here

00:08:26   is very true where you just want to make sure

00:08:29   that your UITableView cells are as sort of dumb as to what

00:08:33   they're displaying as possible.

00:08:35   And you can do that in a couple of different ways,

00:08:37   but what you never want to do is really

00:08:39   create a tight coupling between your model and a UITableView

00:08:42   cell.

00:08:43   You want to put something in between there

00:08:44   that gives you much more flexibility down the road.

00:08:48   Other things he talks about that I think are really good--

00:08:50   not turning on hosy level warnings

00:08:53   or not treating warnings as errors.

00:08:55   These are just kind of obvious things

00:08:57   where the LLVM especially is an amazing compiler.

00:09:01   And if you're doing things that-- LLVM can tell you

00:09:05   tons of problems with your code well before you actually

00:09:08   would need to, or far earlier than you'd notice them.

00:09:12   And so anything that it tells you is probably--

00:09:15   it's like, this is a warning.

00:09:17   This is something you may or may not want to do.

00:09:19   It's probably something you don't want to do.

00:09:21   It's just in general-- and I would say--

00:09:23   I've been doing this for a long time,

00:09:24   but the compiler is still 10 times smarter than I am.

00:09:27   So be careful about that.

00:09:28   And same thing with static analyzer.

00:09:29   Make sure every static analyzer issue you address.

00:09:32   The static analyzer is very smart.

00:09:34   It's catching really low-level problems

00:09:37   that you'd almost certainly not be able to, at least not

00:09:40   right away.

00:09:41   He talks about making sure you're looking at the crash

00:09:43   logs in iTunes Connect.

00:09:45   I recently found this to be really helpful.

00:09:47   I think since IOS 5, when iCloud was introduced,

00:09:50   and I believe crash reports are now sent automatically,

00:09:53   rather than having to be done via iTunes Sync.

00:09:55   There's tons of them usually.

00:09:57   They're really helpful.

00:09:58   I've been able to track down lots of little problems with that.

00:10:01   And any time I do an update, the first thing I do--

00:10:05   or the last thing I do, the first thing

00:10:07   of the actual submission process is I go in and make sure

00:10:09   that I've addressed all of those.

00:10:11   I pull up Refresh the Report List in iTunes Connect.

00:10:13   It's really helpful.

00:10:14   You don't have to do your own crash reporting or any kind

00:10:16   of mechanism like that.

00:10:17   It's just all baked into iTunes Connect and very helpful.

00:10:21   Another thing is putting things in .h files that

00:10:24   shouldn't be public.

00:10:25   And this is something that I used to do a lot

00:10:27   and have recently been trying really hard to fight against.

00:10:29   And I think it's really helped to really clean up my code.

00:10:32   It is basically-- it's a little tricky in the way

00:10:35   that Objective-C does structures things,

00:10:38   because you don't have the same level of-- if you're coming

00:10:41   from a Java background where you had the four levels of publicity,

00:10:45   basically, was it public, protected, private, and class,

00:10:50   something like that.

00:10:51   It's been a long time since I did good Java.

00:10:53   So, but anyway, what you really want to do is,

00:10:55   especially if you're going to be putting properties

00:10:57   or things for a class that no one else should be aware of,

00:11:00   put them as a class extension in the .m file.

00:11:02   Don't put them in the .h file.

00:11:04   The .h file should be as simple and straightforward

00:11:05   as possible, because you have to remember,

00:11:07   the person who's going to be having to work out

00:11:09   how this class works is probably going to be you.

00:11:11   And as smart as you think you are,

00:11:13   your future self is likely not as smart as you.

00:11:16   So be careful about that.

00:11:18   Other things that he says that I think are really good

00:11:20   is making sure you use pragma mark, which

00:11:22   is just a great way to structure and organize your code.

00:11:25   And the last one I want to talk about

00:11:26   is using instruments for performance testing and memory

00:11:29   analysis.

00:11:30   And I think this has become especially helpful and important

00:11:33   as the platform has improved and developed over time.

00:11:40   There's a lot of these things where

00:11:42   the things that are going to be able to differentiate

00:11:44   your application is going to be speed and performance

00:11:47   and reliability in a way that-- even

00:11:50   it's like a weather app, right?

00:11:52   I was building an app that was competing in a space that

00:11:54   was incredibly competitive.

00:11:56   I mean, there is a whole category with thousands

00:11:58   of apps that do this.

00:11:59   How do you differentiate yourself?

00:12:00   And one of the things you have to do

00:12:02   there is to work hard on performance

00:12:04   and those types of things.

00:12:05   I spent huge amounts of time in instruments

00:12:07   doing-- looking at where are the slow parts of my app?

00:12:10   How can I improve that?

00:12:12   Looking for hiccups and bugs, looking for memory load

00:12:14   over time.

00:12:15   All these kinds of problems that you

00:12:17   can improve your application in a way

00:12:20   that the user may not necessarily

00:12:21   notice in a way that is tangible.

00:12:23   It's not like having an impressive graphic design

00:12:26   or something where people are going to see it directly.

00:12:29   But I think people will notice, and it's kind of that latent,

00:12:31   this is a good app.

00:12:32   It's fast.

00:12:33   It's performant.

00:12:34   And you, of course, want to also be doing your performance

00:12:36   testing on slow devices.

00:12:38   I think right now, my typical baseline

00:12:40   is the iPhone 4, which I think gives me

00:12:43   a pretty good coverage.

00:12:45   It's not-- the 3GS I'll sometimes use,

00:12:48   But it's not as much of something that I use these days, just mostly because it's a relatively

00:12:55   small percentage of users, in my case, that use that.

00:12:59   I'm bringing up the stats.

00:13:01   It's about 6% of my users are using 3GSs, which is a pretty low number.

00:13:07   Whereas compared to the iPhone 4, it's about 35%.

00:13:11   And if you go iPhone 4 and up, it's 94%.

00:13:16   So if I can use the iPhone 4 as a basis,

00:13:18   I think it gets pretty good coverage,

00:13:19   even though the 3GS technically supports iOS 6

00:13:22   and all those kinds of things.

00:13:23   But that's typically what I've been

00:13:24   doing as a performance base.

00:13:25   And it seems to work pretty well,

00:13:27   especially because the 4 was the first of the A processors.

00:13:30   I think it was the A4 inside of it,

00:13:32   which gives you a really strong baseline to be working from.

00:13:36   You can do a lot.

00:13:38   If you're trying to get 60 frames a second animations

00:13:40   and things, that's something that is usually

00:13:43   possible on an iPhone 4 in some places on the 3GS.

00:13:45   You just can't do it.

00:13:46   Um, so anyway, those are just some of these thoughts.

00:13:49   I said, these are great links in the show notes for you to go through and just read

00:13:52   through and think about the reason I'm doing it now is again, it's just kind of

00:13:56   this, as we're, you're starting into the new year and you're starting to think

00:13:59   about new projects, new ways to do things.

00:14:01   These are just some things to be thinking about and to kind of make sure that

00:14:04   you're evaluating yourself of, you know, am I making writing as quality coded?

00:14:09   I could be, are there things I could be doing that are better and things that I

00:14:11   could be doing that are more useful to my future self?

00:14:15   So, anyway, that's it for today's show.

00:14:18   As always, if you have questions, comments, concerns, or complaints, I'm on Twitter @_DavidSmith,

00:14:22   I'm on AppNet @DavidSmith.

00:14:25   You can email me, david@david-smith.org, if you have questions about the show.

00:14:29   Otherwise, I hope you have a good week, happy coding, and I'll talk to you on Thursday.

00:14:32   Bye.