#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: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: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: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
◼
►
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: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: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: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: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: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.