CHUCK:
I have to say, this show’s intro music I think is my favorite of all the shows.
JAIM:
Which one is this? Sing it? [Laughter] Unless you sing it.
CHUCK:
[Sings melody]
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York and L.A. bid on iOS developers, providing them with salary and equity upfront. The average iOS developer gets an average of 5-15 introductory offers and an average salary offer of $130,000/year. Users can either accept an offer and go right into interviewing with a company or deny them without any continuing obligations. It’s totally free for users, and when you're hired they also give you a $2,000 signing bonus as a thank you for using them. But if you use the iPhreaks link, you’ll get a $4,000 bonus onset. Finally, if you're not looking for a job but know someone who is, you can refer them on Hired and get a $1,337 bonus as thanks after the job. Go sign up at Hired.com/iphreaks]
[This episode of iPhreaks is brought to you, in part, by Postcards. Postcards is the simplest way to allow you to feedback from right inside your application. With just a simple gesture, anyone testing your app can send you a Postcard containing a screenshot of the app and some notes. It’s a great way to handle bug reports and feature requests from your clients. It takes 5 minutes to set up, and the first five postcards each month are free. Get started today by visiting www.postcard.es]
[This episode is brought to you by Code School. Code School offers interactive online courses in Ruby, JavaScript, HTML, CSS and iOS. Their courses are fun and interesting and include exercises for the student. To level up your development skills, go to freelancersshow.com/codeschool]
CHUCK:
Hey everybody and welcome to episode 79 of the iPhreaks Show. This week on our panel we have Alondo Brewington.
ALONDO:
Hello, from North Carolina.
CHUCK:
Jaim Zuber.
JAIM:
It’s 1pm in the afternoon. If you’re thinking that guy sounds like he’s still wearing his pj’s, you’d be right.
CHUCK:
Isn't 1pm in the afternoon redundant?
JAIM:
Ah, man. [Chuckling]
CHUCK:
We also have Pete Hodgson.
PETE:
Hello from Sutro Tower.
CHUCK:
Alright. I’m Charles Max Wood from DevChat.tv. Before we get started, I know that there’s some crossover with technologies between the different shows, and so I’m going to announce this here even though it’s a JavaScript event.
I’m pulling together a remote JavaScript conference. It’s going to be two weeks in the evening, that way people can basically DVR the television shows that they watch and watch the conference instead and get that development without having to talk to their boss trying to get the time off, or pay a whole bunch of money to travel and then pay a whole bunch of money for a conference ticket.
Because there’s no venue, it should be pretty cheap. I’ll have the site up by the time this goes live so you can go check it out at jsremoteconf.com, but I thought I’d put it out there since I’m looking also at doing a similar event for iOS. I’ll let you know when I’m doing that too, but for the meantime, go check that out for me.
Alright, so we’re into the show. We’re going to be talking about communication patterns in iOS. Jaim, I guess, is our resident expert so why don’t you kind of get us started. Where should we start in discussing this?
JAIM:
Sure. This is a topic that I did some talks on this year. We do a lot of talks about MVC, different patterns, how you design your app, and we talked about it last week a little bit.
One thing that people don’t really talk about is how do we communicate with these different objects that we’re creating? We’re breaking down view controllers, make them skinny like Jay Thrash helped us with last week, but how do we communicate? How do we get this object to do what we want it to do?
There are three or four base patters. You’ve got, say, the delegate pattern, which is pretty basic. You’ve been working with iOS for about 30 minutes before you run into your first delegate, if you’re doing anything with a table view, but there are a lot of different approaches. You can use a Notification Center – KVO is very powerful for that. If you want to get crazy, you can use blocks as well. Those are probably the four basic ones.
CHUCK:
Interesting. Do we want to talk about what all of those different things mean?
JAIM:
Sure. We can start with the delegate pattern – that’s the basic Apple-approved way of communicating with things. You create a delegate, you parse your self into the delegate, and you wait for it to call back to you. That’s something that everyone knows how to do if you’ve done any Apple stuff. It’s baked into the framework; it’s an old pattern. I think it’s in the Gang of Four book. It works pretty well for a lot of things. If you have one thing yet to keep track of, it works great.
PETE:
I think it’s called something different in the Design Patterns book, in the Gang of Four book.
ALONDO:
I think it’s the observer pattern in the Gang of Four book.
PETE:
Yeah, maybe. I think it’s like –.
ALONDO:
I’m sorry, [inaudible 04:53].
PETE:
Yeah, it’s like one of those patterns that you can use the same mechanism in different contexts and it has a different name. The way I think about it is it’s just defining an interface with something and giving someone an implementation of that interface, but that’s just the mechanism of it rather than the spirit of why you’re doing that thing, I guess. Yeah, anyway. Sorry.
CHUCK:
So the observer pattern to me usually centers around events, and so the idea is that when you change an object, it fires a change event and something else is listening to it and that does stuff. Is that more or less how delegates work, or is it explicit in the other direction where you have a hook or something that you define on the object that then notifies or calls into somewhere else?
JAIM:
I think we’re kind of mixing our concepts here a little bit. The delegate pattern – I don’t think that’s the observer pattern. As a lot of them pointed out, the Notification Center, if we’re talking about observers – that’s what we’re talking about. In the Notification Center, basically the object will send a notification that they don’t really care about who receives it; they’re just sending it. Each other objects can subscribe to different notifications, so the objects themselves don’t really have to know anything about each other – any [inaudible 06:09] classes or protocols, interfaces, that type of stuff.
PETE:
Yeah, to me, the big difference between the delegate pattern and – now that I think about it, all of the other ways of communicating or abstracting over just like a straight method call or a straight message parsing is delegates are the only ones that are kind of typed. They’re the only ones where you have a thing that has a type in it, or at least a dock [clear 06:35] type in the implemented protocol, and then you pass that thing around.
Everything else – your blocks and KVO and all the rest of it – you tend to be working on the level of individual methods. But with a delegate, you’re defining basically a cluster of methods that you implement and then you pass around to someone else. Or am I getting my naming mixed up again?
ALONDO:
No, I think you’re right. The biggest thing for me – and Jaim, you’re right – the first think I was introduced when I started iOS development of course was that delegate patterns invisible in the first day. I was working on a table view app.
My initial sort of rule of thumb was if it was a one-to-one relationship where I had one object that was depending on or delegating actions to another – and I’m using the word in the definition – using delegation where in terms of notification they tend to use it in cases where there are multiple interested parties in something happening, or could be, potentially. I would a notification when an event occurs, but tend to stick with delegation when there’s only one object that I need to respond to an event occurrence. And I assigned that at that object – I make the delegate to that protocol.
PETE:
That’s true but sometimes it’s not 1:1, right? Sometimes you can have – now I’m going to show my getting confused naming again. If I have a method that’s responding that’s bound to an action, for example – I guess, that’s not delegation, is it? That’s something else. But as you kind of say, if you look at the classic delegate thing that everyone knows is the UITableView delegate. When you implement that to all of the delegate’s protocols, you always take the subject of the message as the first – the sender of the message is almost always the first parameter. You have tableView:heightForRowAtIndexPath or whatever.
1: many, but it’s the opposite way around to the 1:many you would have with notifications.
JAIM:
Yeah, it’s a good point. I mean, how many times do we have to subclass the table view to get it to do what we want? Not very often, but we can always create another delegate that handles a different behavior that we want to do. In that case, it’s a very powerful pattern. You can create one base thing and let other things do the heavy work for you.
But as a lot have pointed out, there’s kind of a drawback to it in that you basically have one delegate at a time. You don’t really create multiple delegates for your table view, so if you’re creating some other class that has delegates and you want to have more than one, I’ve seen people create arrays of delegates, which you can do. It’ll just fire off to each on in its array, so it’s possible to do, but it’s kind of bulky. But that’s where things like the Notification Center make more sense because it’s kind of baked in and you don’t have to do the little things like managing arrays for that type of thing.
CHUCK:
And that’s the power of the observer pattern when you’re talking about the notifications center – it tells everybody that something happened, and then the ones that are interested then go and do whatever work they have to do, whereas with the delegate, it’s an explicit relationship in this just one way.
PETE:
That’s the other interesting – I mean, like with all things in software, this is about tradeoffs. One of the things you sacrifice when you move to this multiple consumers model is you can’t do request response anymore, so you can’t call – with a delegate, I can say tableView:heightForRowAtIndexPath and I’ll get an answer back from my one delegate. If I want an answer back from something, it needs to be a thing that I’m asking, right? But if we’re doing notifications, the one where you kind of fire and forget a thing, then I don’t have a way of asking something else, a question, and getting an answer back. Which I guess is why you see these tradeoffs and why sometimes we would use a delegate, for example, for table views and in other places we would use notifications for something that’s more one way, fire and forget notifications of things, rather than deferring some logic to something else so that we can ask it questions and get answers back.
CHUCK:
You mentioned delegates – and I think we kind of get the idea there. What were some of the other ones you mentioned? You said KVO, which is key-value object?
Key-value observing.
CHUCK:
Observing? Okay.
JAIM:
And this gives you a lot of the benefits of the observer pattern you get with the Notification Center, where you don’t really have to create explicit contracts for your things to behave to, so you’re not really creating classes but you’re just listing the things that are happening.
If you have a model with something that happens – and I can’t think of any model that you can listen to a property on there. If that property changes, then you can register a callback that will get notified when this happens.
ALONDO:
We had a recent discussion about this pattern with some of my co-workers and it was brought up that this was a kind that they tend to shy away from. I’ve only used it once in the past, and it was basically to manage scrolling in multiple directions for a particular view that allowed the user to scroll basically like paging as well as vertical scrolling. I was using KVO to monitor when the scroll view was changing so that I could sort of keep everything in balance, because there were multiple panels that needed to stay in sync, so they only use the scroll together.
I was having trouble thinking of another case where I would use it; I mean, using a pattern once every four years is not a lot. But they were concerned about pitfalls and I was curious if you’ve encountered any or if you have any rules of thumb of when you would use KVO or when you would stay away from it.
JAIM:
[Inaudible 12:17] scrolling is an ideal place where KVO works, because you don’t really have control of what’s happening inside the scroll view to fire off a notification that it’s being scrolled. And if you’re using a delegate – the delegate is actually derived from scroll view, I believe, so you have one delegate that is actually doing that, so if you want to listen to the different changes in scroll state, you can observe what’s happening without throwing everything in in your table view delegate.
12:
44] says scroll view existed way before we did, but you can observe things that are happening, so that’s a textbook example of a good way to use it.
The drawbacks are it’s clunky. The syntax for it is pretty weird; if you have more than one thing you’re listening to for that object, all your KVO stuff comes through one method – observeValueForKeyPath. If you’ve got more than one things you’re listening to, you’re doing like if/else – you’re just checking string pairs, and that gets pretty large methods. That’s the drawback to that.
Also, a drawback to KVO – it’s very powerful, but it’s easy to create weird bugs if you don’t clean up after yourself, you don’t remove your observing. Sometimes, if an object stays around too long, you can get multiple observations – you get weird bugs, so you have to remember to clean up after yourself.
This is also a problem with the Notification Center. If you add a notification, say, in your viewDidLoad, you also need to be very careful to remove our observer in the alloc. If you don’t do that, very bad things are going to happen. You’d have these crazy bugs that only happen every once in a while the second time you come to this view controller, so it’s very important to clean up after yourself with Notification Center and with KVO.
ALONDO:
That’s a great point. I ran into an issue once when I was adding an observer for an event – adding an observer using notification and I started getting all of the notifications because I didn’t properly format the addObserver call. It was found out that my code was responding to all types of events that I wasn’t even aware were happening in the system.
JAIM:
Yeah, if you’re subscribed to system events, you need to make sure you’re getting the ones that you want and if you’re only interested in events from one object, you can also filter and parse in the object that you want to listen to. That’s also very useful. But it’s very easy to get yourself into a stage where you have tons of different notifications that you’re getting more than you want.
ALONDO:
Yeah, in fact, when I code I tend to actually write two methods that I keep pretty standard. One is the setup notification then remove notification, and just call that in my viewDidLoad, and any notifications I need to do there are set up in one method and any notification I need to be removed of course are all – or just removing itself as an observer removed in that removeNotification call. It makes it a little bit easier when I’m setting things up to not forget to set up the individual removal at the end at some point in that [inaudible 15:13] as you mentioned.
JAIM:
Yup. A useful trick that you alluded to is if you call removeObserver and parse self, you’ll drop all your notifications. So it’s a quick thing if you’ve subscribed to a bunch of different ones, maybe you created some notifications in code that you don’t really have, all of the [inaudible 15:29] you can stop listening to all of them if you just remove yourself – removeObserver:self.
PETE:
You mentioned with KVO, the super clunky API. I feel like someone on a previous episode was talking about some kind of open source options that are out there to make it easier to deal with KVO, but I can’t remember what the name of the library was. Do you guys remember that?
JAIM:
Sounds familiar – I can’t remember what it is [chuckles]. I mean, I mentioned there’s a lot of ways you can make things easier; we’ve got a dynamic language with Objective-C in Runtime, so this type of thing is definitely impossible to clean up. The tools Apple gives you are pretty limited.
PETE:
Yeah, it’s just a really, really horrible API. This Mike Ashe has a thing called Mike Ash KVO – MAKVO – Notification Center from 2008, but I don’t know if there’s one now. It’s irritating me; I can’t remember what the – oh, bubble wrap! No, never mind. I’m going to figure it out halfway through this and come back to it.
JAIM:
I feel a pick coming on [chuckling]. I’m calling it right now.
PETE:
It’s my pick, it’s my pick.
He’s going to find it.
PETE:
The thing that I’ve always thought would be a good – I guess I’m in the same boat that I’ve never really used KVO much because it’s, to be honest, a little bit intimidating. The place that I’ve always thought it would be potentially a good fit is to do kind of view models in the MVVM sense where you have an object that’s kind of a logical representation of your UI, and then you just modify that PONSO – that Plain Old NSObject.
From your controller, you just modify that guy in order to make changes to the UI and then you’d use KVO to somehow bind changes to that objet to actual changes in UIViews. It seems like that’s a nice approach, but it also is a divergence from the standard, Cocoa way of doing things, and maybe that’s why I haven’t heard of people doing that. Seems like a good idea to me though.
JAIM:
So you have one class with all your outlets and your actions, which interchange with the view, and you have a PONSO class that listens for those changes when they happen and they update, and from there you kind of do things with it?
PETE:
Yeah, exactly. Essentially that view model – maybe view model isn’t the right word; maybe it’s a presenter or something. I always get all of these MV* patterns mixed up.
You’d have a one kind of object that acts as the interface to the UI layer, essentially. It uses KVO to – how would that work? I guess it would use the standard kind of binding to actions and all that stuff to react to interactions with the UI from the user, and then the flip side is it would have properties on it which you could modify from non-UI code in order to affect changes in the UI.
I’m not sure if that KVO would make sense there, because then something would have to be observing the changes to that view model. I guess the controller could be watching for changes in the view model and then the controller would update the UI? I don’t know. Maybe it’s the reason no one’s done it [chuckles].
JAIM:
MVVM – it’s a thing in iOS; people are doing it. Over the past year, people have been talking about it quite a bit. I haven’t seen a lot of code that I encounter as a very common pattern, but it’s at least been talked about. I imagine people are doing stuff in [inaudible 19:00] with it.
CHUCK:
So we’ve talked about delegates and we talked about KVO – you said there was a third and fourth. One was blocks and the other was something else.
ALONDO:
We put [inaudible 19:10] as well.
JAIM:
Yup. The first three I think were delegate pattern, observer and NSNotificationCenter in KVO – those are three. There’s a fourth way of communicating with different objects, and that’s just using blocks – more of an asynchronous style where you parse in something that you want to happen when this event occurs and let it call it. The method doesn’t know anything about the stuff that it’s causing to happen, but it’s just calls your block. If this block is not nil, call it and whatever happens, happens. It’s a very powerful pattern.
ALONDO:
There’s some more [inaudible 19:42] in addition as well, right? I mean, blocks were available as of what? 5 or 6?
JAIM:
I think 4? Very early in 4, and no one used them in iOS 4. I think. I’m sure no one actually used them, but I think they were available [chuckling].
ALONDO:
We’ve definitely started making a move to a lot of code replacing. In many cases, delegate callbacks to use it with blocks to make a good code more readable. As you’re looking at code, you can actually tell what’s going to happen, for when it’s scrolled down, so it’s where I could delegate sections, delegate [inaudible 20:15] and determining, when this thing returns, what is this going to do?
PETE:
I think the other thing that this is maybe another communication thing that isn’t on the list that we started with is just directly kind of giving someone a selector and having someone invoke that selector on you. It’s kind of like the generic one method version of the delegate; it’s just like, “here’s a selector.” I mean, that’s how you bind to UI actions, right? Under the covers, as I understand it – and I could be under the covers when you turn your nib into actual Objective-C objects for all of that binding stuff that you have to do with the clicky-draggy in interface builder. Essentially you’re just passing selectors to the view and saying, “Hey, when this event occurs, call this selector.”
That kind of stuff, to me, is very – the stuff where I’ve done that stuff manually and passed selectors around, I’d much rather pass a delegate around because it’s a lot more flexible. Like you say, the code that handles the callback is right there when you’re wiring things up rather than it being some set method further down in the class.
JAIM:
So what are some other good use cases for blocks? We’ve talked about after a network operation – if this thing succeeded, do this; [inaudible 21:27], this thing failed. What are some other good examples of when to use blocks?
ALONDO:
I’ve actually done it when invoking a class and I’ve got multiple courses of action, for instance. When I’ve done an edit form, I actually parse in a block for safe cancel and delete, and so then I actually have setting on that object the execution it needs to be done when someone taps either of those buttons. That’s one of the situations where I’ve used it recently.
PETE:
I feel like a lot of times, with more modern Objective-C, you use blocks where before you would’ve defined a custom delegate. Rather than making a custom subclass that has the save, edit and delete stuff on it, instead you just have a generic class and you make it polymorphic by actually just providing the different functionality with blocks, rather than messing around with a ton of subclasses.
ALONDO:
Exactly.
Yeah, I like that. So you’ve got your saveViewController, which may do things like validation and things like that, but when it comes to actually saving, it doesn’t care if you’ve saved it to the file system, going to iCloud, or hitting a web service. You can find that in define that in the block that you’re passing in and if requirements change, the view controller itself doesn’t have to change.
PETE:
Yeah, if you’ve got – I guess we already talked about the network example, but the full blocks, if we were doing a network call, then we would’ve had the delegate that defines “this is what I want you to do when the call completes; this is what I want you to do if the call fails; maybe this is what I want you to do as each piece of data comes in” and you’d have to define a subclass for each of those, even if all they really wanted to customize was what to do when it succeeds. You’re happy to get the default behavior when it fails, and you don’t care about the lower level notification stuff. You just want to – essentially you just want to subclass that one method for your custom behavior. In the past, you would have to subclass it and done a bunch of annoying housekeeping to pass in the context that you need for when you handle the success.
When this network call succeeds, I want to do something with some other object. Before blocks, you would’ve had to have created the subclass past that context into the thing when you create it and then pass that instance to the thing that’s doing the actual networking. The really nice thing, I
think, about blocks is – well, one of the reasons we really like them is a) they’re super ad hoc and you can just throw it in there without having to do a bunch of ceremony and b) you get Clojure, so you can refer to stuff that’s at the point that you’re invoking the call at the point that the network call comes back. You get this asynchronous – I think that’s the big use case for blocks is when you’ve got asynchronous behavior where you need stuff that was around when you started the behavior or started the thing to be available to you when you’ve finished the thing. Before you had blocks, you’d have to mess around with parsing, explicitly managing that context and moving it in and out with different classes, and now you can just close over it and hope the automatic reference counting doesn’t give you memory leak.
ALONDO:
Absolutely. My only minor gripe with that early on was I used to see a pattern a lot where the block callback would contain it on success/failure blocks, and I’m not a big fan of that. The success is a Boolean – it was successful or not. I can actually handle everything inside with a single block, any of those cases. I prefer to do it that way anyway.
PETE:
It’s interesting if you’re a JavaScript programmer, then you’re kind of talking about the node style versus some other style. It’s like, “Yeah, do you have one callback with some kind of flag in there, or do you have two callbacks and move the logic around between the two?
ALONDO:
Yeah, and just because in a lot of cases there’s cleanup that needs to be done and I tend to do –.
PETE:
Yeah, it’s common, right? Most of the stuff you want to do is the same whether it’s a success or failure.
ALONDO:
Absolutely.
PETE:
I think one of the things that we talked about a long time ago when we were talking about
AFNetworking, a pattern I really like not in code I’m writing but in the APIs for libraries I’m consuming is the option to use whether a delegate or a block. Essentially, the block version just creates a – there’s kind of a generic delegate implementer where you just give it the blocks or you can actually subclass stuff. And then you get to pick as a consumer of that API, as a client of that library, I get to choose whether to use blocks or delegates, depending on the context. It’s really annoying when you have to do that planning yourself in your client code to turn a delegate-based API into a block-based API or vice versa. I really like the option of having both.
ALONDO:
That’s a great point.
JAIM:
As an API developer, I just threw up a little bit in my mouth, having to do both [laughter].
PETE:
But that’s the thing, right? You’re one person doing it versus every single consumer doing it.
JAIM:
Every single consumer doing things twice – two different ways being able to do it.
PETE:
Oh, I see what you’re saying.
JAIM:
Twice the thing that can go wrong that you have to test.
PETE:
I get it yeah, but that’s the point, right? You can do it as the person who’s maintaining that kind of system. You have a lot more understanding of the moving parts, and it’s a lot easier for you to get it right than it is for someone else to get it right. And if someone else gets it wrong, they’ll blame the library, not their crappy code. If someone else doesn’t understand how, if you define callback x then you should also define callback y, they’ll just go ahead and screw it up and then say that there’s a bug in your library because you’re using it wrong.
JAIM:
I agree as an API consumer – choice is good. We should always do it my way [chuckling].
PETE:
I guess there’s that argument about convention over configuration and how far could you go down a rigid path that you can’t change at all versus giving someone enough rope to hang themselves with. Perhaps a higher-level API that’s the common kind of use case and is very straightforward to use, but then it’s implemented in terms of some lower-level API that someone can pop the hood and use directly if they want to do something wacky in custom. And then they know at least that they’re doing low-level stuff, so they need to pay more attention to what they’re doing.
JAIM:
That makes sense. One thing you touched a bit upon while talking about blocks is how much ceremony you have to do to create a solution. I think that’s a good indicator of what approach you want to do.
If you’re coming from C++ Java land, blocks are like voodoo. Notifications center – what is that? So
if you come from that world, which I did for a long time, you have to create a class for everything you want to do. It doesn’t matter if you have to create a class, subclass, do something with it and you’re used to that.
On the plus side, you get some compiler checks from that, so if you do something wrong, the compiler will catch it. If you come from a more dynamic world view or history, creating a notification, that might make more sense; it’s just a block where you don’t do a lot of ceremony to create what you’re doing.
But the downside is, your compiler’s not going to catch you if you misspell your notification or you sent the wrong one; you have nothing to catch your fall for it, unless you’re actually writing tests or catching a runtime. So a lot of it comes down to what are you most comfortable with, what do you like.
PETE:
That’s a really interesting observation. I think that kind of – I really agree with that, and I think that summarizes the different world view of people who are more on the dynamic side of things versus static. It’s just like, ceremony but type safety or more compiler-checking, versus the freedom to do stuff whichever way you want, but the freedom to also shoot yourself in the foot in a very subtle way that you only discovered it in runtime [chuckling].
JAIM:
Yeah, I think of a compiler as a bunch of unit tests you get for free. They don’t actually tell you if your program works or not, but if your basic [inaudible 28:53]
ALONDO:
[Inaudible 28:56]
PETE:
We talked very briefly about Notification Center. I’ve always been scared of Notification Center because it sounds like a bunch of global stuff and I’m always really scared of global stuff. Is that an unfair characterization? Should I give Notification Center a better shot or is it as scary as it sounds to me?
JAIM:
What do you mean by global stuff?
PETE:
The way I view Notification Centers is essentially it’s this big, global message bus and anyone can pump stuff onto it or pull stuff off of it, and so you don’t really have any way of looking at your code and understanding who might be sending messages and who might be receiving messages. But maybe that’s just the way that I have seen people using it and there are ways to use it more responsibly than that.
JAIM:
I think that’s a fair characterization. If you just throw stuff everywhere, you may not have any sense to understand what’s happening. But in practice, I’ve found it very powerful. I can communicate with different objects just by creating a notification, so I found it to be very useful, and so I wouldn’t be too scared of it. It’s a solid pattern. It’s of the observer pattern, so we know when it works well, when it doesn’t work well.
If you do get worried about being on the same Notification Center as everyone else, I believe you can create your own sub one for more customized stuff. I’ve never really had to do that in practice, but it’s possible.
ALONDO:
I’ve found it quite powerful and useful; I’ve not had the need to use anything other than default Notification Center. I was actually looking for – someone told me, one of the tools that I use for view debugging actually will allow you to monitor – Spark Inspector will allow you to monitor notifications as well, if I’m not mistaken. If you use it as a tool for view debugging, I guess that may be a pick, and you can use it as well to sort of monitor, you can see what notifications are being posted or observed by objects.
JAIM:
Another thing we haven’t fully talked about is testing code. If you’re a person that does write unit tests, how does being able to write tests affect your choice for these different patterns? Do you guys have any opinions?
ALONDO:
That is an excellent question! I have actually started in the past week a deep dive into starting to use testing, and I haven’t gotten to a point where it’s actually affected my choice of design pattern or communication pattern yet. I do think that’s probably an excellent topic for another show.
CHUCK:
Do you typically wind up mocking out or stubbing out the delegate or KVO or Notification Center or whatever? Or do you actually do some integration tests with them?
JAIM:
With delegates, that’s pretty straightforward. It’s just code, so if you wanted to throw a mocking framework on there, you can do that or stub something out, so that’s pretty straightforward.
With Notification Center, it’s a little less clear on how to do it. It turns out it’s really not that difficult; if you set a notification, it happens in-line. It’s not something like goes off and happens at a different time; it actually happens in-line. Whatever thread you’re on, it will do the notification, the observer, the method will happen and the same thing so you can notify when it happens.
If you’re using OCMock, they have ways where you can notify that notifications happened – things like that – so you can write tests around this notification occurred and also verify that this happened when I sent this notification. Who’s the guy who wrote the unit testing iOS book?
Graham –?
ALONDO:
Graham Lee?
JAIM:
Graham Lee, yeah. He talks a little bit about testing, kind of the notification patterns. He had a
pretty good chapter on that.
PETE:
I think with the testability of things, it comes down to whether you’re testing something you have – basically it comes down to can you do inversion of control? Can you change what something is talking to during testing so that you can isolate it? That’s why people who do a lot of testing like dependency injections, because rather than if someone inside – rather than in the guts of a class something [inaudible 32:48] up a new class, if someone does that, then you can’t inject something in between those two things because the one thing is directly invoking an instance as the other thing, so you don’t have a seam in which to insert testability.
You can use the same kind of lens to look at how testable these different approaches are. A delegate, for example, is very easy to inject because, like you said, all we need to do is just create a fake version of the delegate and just make sure it’s interacted with correctly.
Same thing with blocks – you can just give the thing a block that keeps track of whether it’s being called or not, but it ends up –. Blocks is just more housekeeping, because you have to ironically – blocks, in general, tend to mean less housekeeping and less ceremony, but in terms of testability, they end up being more work because you end up having to do a bunch of custom stuff in your test code to keep track of whether the blog has been invoked or not.
JAIM:
Yeah, especially if you have to check parameters. You’re looking for this value [crosstalk 33:45] – yeah, that’s a really good kind of a pain. If it’s a value type, then it’s another thing of pain.
Mocking frameworks with blocks can be a pain, but it turns out, if you just want to subclass the class like old-school Java TDD, then a lot of the code becomes fairly easy to test. You can just put a method that checks what you want to check, so if you do the old-school kind of subclass and test –.
PETE:
Yeah, like the test-specific subclass thing?
JAIM:
Yup.
PETE:
I feel like Notification Center would be tricky to test. I can’t put my finger on why, but the action at a distance kind of feeling makes me suspect that it would be a little bit tricky to verify whether it’s being used correctly or not.
JAIM:
Yeah, it seems like it is because it’s this nebulous, Apple-provided framework that we don’t fully understand. But practice – it’s pretty simple to check if this notification occurred, and you can also do things like subclass and listen for another notification instead of flag, pass your test that way.
So in practice, it’s pretty simple. Notification Center is actually pretty easy to test. KVO, I have no clue. I think you’re probably just looking for the side effects and hoping they happen as you want.
PETE:
Yeah, I think KVO would actually be really hard, because if you wanted to simulate an object changing and then verify things happened, I guess you would just parse in the object and then tickle it from your test and change it in your test and then check that stuff happened. I suspect you’d have to do a bunch of housekeeping in each test to kind of parse it in the right way, and then [inaudible 35:15] things, and then mess with in, and then check if the thing’s changed the right way. It feels like that would be quite tricky to simulate all of the different scenarios in the KVO.
JAIM:
Yeah, you’re calling observeValueForKeyPath with all the different things, and just making sure that what you’re calling is what you’re going to be getting from the system, and hoping you get right.
CHUCK:
Does the testability of an approach affect your willingness to use it?
PETE:
It does, for me.
JAIM:
Yeah, if you’re looking at the lifetime of a software product, [inaudible 35:40] test that has a lot of value, especially if the [inaudible 35:24] could be wrong for a long time. It’s a factor in it; I mean, if you can create super clean code, it’s a little bit harder to test that’s [inaudible 35:49]. You can sacrifice a little testability, but in general, it’s definitely something I consider.
PETE:
I think, for me, as much or maybe even more so than the actual testability of it, experiences has shown for me that if something’s easier to test, it generally is just easier to work with. Things that are loosely coupled and highly cohesive tend to be easier to work with and easier to test, so generally I’m looking for stuff that’s easy to test because it tends to be easier to work with in general, and therefore easier to maintain and extend over time and all the rest of the stuff that you’re doing.
JAIM:
Yeah, I think it’s a truism that I heard a few years ago and I found it to be very true: something that’s easy to test is easy to change.
CHUCK:
That is true – or at least mostly true. I can’t think of an instance where it’s not, but it seems like there’s got to be maybe one crazy case where that’s not the case.
JAIM:
Chuck, it is 100% true in every case [chuckling]. Keep repeating that.
PETE:
I can definitely remember times when it’s not the case, but unfortunately I can’t remember the example as to why it’s not the case. Actually, ironically, I think having spent more time in functional languages recently, and this is a world that we are hurling towards with Swift – there tends to be less of a correlation at that because you tend to have more internal stuff that’s not really testable, but you don’t really need to test it because it just works. I would always feel a bit nervous saying that because I’ve spent so much of my life telling other people that they’re wrong when they say that [chuckling]. But yeah, I don’t know. Those are starting to be the cases that I’m seeing – very pure kind of functional code tends to not lend itself to testing very well, but it also appears to not need as much testing.
JAIM:
So what makes it not easy to test? When I think of functional code, when you’re passing some values and you get a response, it turns it into some different value [inaudible 37:41] would be a pretty easier test from the outer shell layer.
PETE:
Yes, that’s exactly it. It’s easy to test it from the outer shell layer. The public parts of it are very easy to test. I think the big difference is – I’m still trying to wrap my head around it, but I think the big difference is with functional code, you tend to use Clojure as the way to relate things together, and those with object-oriented code, you use different classes and the classes communicate with each other, or different objects, different instances, and they communicate with each other.
38:
23] instance of the object with functional code, because you’re using Clojures. A lot of times that internal stuff isn’t available for you to get; it’s just hidden inside of a larger function, and so that means that you end up doing a lot more integration tests, and a lot less low-level, isolated unit tests. Which is weird for me because I come from the mockest kind of school where I really like isolating each little thing that I’m working with and kind of testing it in isolation, and then doing some integration on top, whereas with functional programming, I’ll find myself most of the time just testing the high-level integrated piece, and I can’t get to the low-level stuff to test it.
JAIM:
Okay, that’s interesting. You brought up another subject that we didn’t touch at all – Swift. Is the Swift language going to change our approach for these communication patters?
PETE:
I strongly suspect that we will use a lot more blocks than we do today.
JAIM:
I agree. I think objective-C blocks and tax is not really that friendly. I’ve got a pick coming up based on that. You guys have probably figured it out, but I forget every time. I could do a block and I’m like “Wait a minute” can we do the care or tear parenthesis [inaudible 39:32] – I don’t know; I always forget. So I think that’s one thing. I think blocks have become a lot easier a lot less.
ALONDO:
Well for people that are coming from a more functional language, I’m curious, what other patterns can we expect to be able to use with Swift? We’re so familiar with some of these other ones having worked with Objective-C for a while, but I’m not really familiar with some of the patterns that are more prevalent in functional programming.
PETE:
I think the big one – and I’m not totally sure if this counts as a topic of communication patters, but the big thing that you see in functional versus OO and then definitely for Swift is pattern matching rather than polymorphism. Or pattern matching is the means for polymorphism.
Today in Objective-C, if we want something, two things that look the same from the outside but behave differently internally, then we use subclassing or we implement a protocol. That’s how delegates work, right? Every table view delegate looks like a table view delegate, but it behaves differently depending on what the subclass is.
With functional lounges that have pattern matching like Swift does, you end up using pattern matching as your switching mechanism rather than dynamic dispatch. I think that that’s one big shift that we will probably see in five years’ time or something, is using pattern matching as the mechanism for deciding what to do rather than subclassing. I’m not totally sure how that relates to the kind of stuff we’re talking about with handling network calls or registering custom callbacks and things like that.
JAIM:
That makes sense. I think KVO is going to be less useful, because that relies on NSObject, which I don’t think we have in Swift. Does anyone know for sure before I [crosstalk 41:13]?
PETE:
That’s interesting. I think it’s available, but by default – oh I don’t know. I’m not going to make an idiot of myself in public. That’s kind of funny though, to think that’s an entire mechanism that just isn’t really going to be available to us anymore.
CHUCK:
I wouldn’t be shocked if it’s available but maybe the way that the language is structured would encourage us to use a different means of doing things.
JAIM:
Yeah, in Objective-C, almost everything is NSObject. With Swift, that’s probably not the case where everything is going to be NSObject.
CHUCK:
Or it may be neatly wrapped around it and given a little bit different interface. I’d be interested to know this, but I don’t know for sure.
PETE:
Well, luckily I’m a full Stack Overflow developer [chuckling]. I searched on Sack Overflow, I scrolled down to the answer, skipped the question, skipped the first answer which didn’t have enough upvotes and it says yes and no. That’s the answer.
ALONDO:
Nice [chuckles].
CHUCK:
I feel better and worse.
JAIM:
Alright. Who wants to feel smart by reading the answers from Stack Overflow? From slezick.
CHUCK:
Thanks slezick.
PETE:
[Chuckles] Basically, I think the answer is – you’re right Jaim – you can still do KVO on Objective-C objects, but Swift doesn’t have anything built in because Swift objects don’t derive from NSObject.
But there is some other mechanism.
JAIM:
That’s good to know. So we can still do that.
PETE:
We didn’t really talk about this mechanism that I don’t think I’ve really seen in the wild much because it’s quite low-level of just directly invoking a selector, was directly sending message via – I’m totally spacing on what the method is.
ALONDO:
Target-action?
PETE:
Yeah, all of that stuff.
ALONDO:
I’ve not actually used that in the wild; I’ve not even encountered it very much in code. I mean, there are a few instances where I’ve actually performed selector or testing a selector through an object, for the most part we use the other main patterns, notification delegations and then more recently, blocks.
PETE:
So the one time that I’ve done this is really, really dynamic code where I’m doing dynamic dispatch based on something that came over the wire from a network call. I wrote this library that essentially it’s remote procedure invocation where you send a chunk of JSON to your iPhone app and it will invoke a method based on the shape of that JSON. For stuff like that, you have to use that super, super dynamic kind of perform selector stuff, but it is seriously clunky to use. The API makes KVO look good.
JAIM:
Yeah, definitely. So it’s definitely possible to pass around selectors – it’s a [inaudible 43:52] but the cell, you do the AddSelector and you type your method signature. This is something you pass around and you can invoke on any object; it may crash, but you can do a lot of things with it, so that’s another option that I don’t see as much lately but if I look at older code, I see that a lot more frequently. I mean, the older way to do button presses was to pass it in a selector.
PETE:
I think that is still the way it works under the covers, is it not?
JAIM:
It probably is.
PETE:
I’ve done that where when I don’t want to use nibs for whatever reason – and this was a while ago that I lasted this, building the view hierarchy totally by hand and wiring up all the actions by hand, you’re essentially passing a selector to the UI control and saying, “Hey, call this when this happens.” And then internally, in that UI control presumably internally, is at some point calling performSelector with the thing that you passed in.
JAIM:
I agree with you but I have no idea. I think you’re right [chuckling].
PETE:
Yeah, and the other way it might be working, and I might just be talking out of – something is using the dispatch hierarchy doodad thingy – event bubbling, whatever it’s called in iOS.
JAIM:
Responder chain.
PETE:
Thank you. That thing.
CHUCK:
Doodad bubbling, I like it. Well is there any other thing that we should talk about before we get to the picks? We’ve been at this for about an hour.
JAIM:
I think it’s a good base; I think we’re alright.
CHUCK:
Alright. Well then let’s go ahead and do some picks! Pete, do you want to start us off with picks?
PETE:
Yeah, I’ve only got one pick this week. Maybe I’ve got two. Pick number one is a Yegge Rant. There’s this guy, Steve Yegge – if you haven’t heard of him, he’s a very smart, thoughtful guy who tends to write these very long, rambling rants about the state of the world in software development. He used to do it a lot more in the early 2000s.
Jaim’s comment about the static – if you come from a statically-typed background versus a dynamically-typed background reminded me of this rant that he wrote a long time ago where basically he describes software engineering as having its own political axes, ranging from conservative to liberal. Essentially, he says that conservative’s kind of the equivalent of political conservatives in the software world, like statically-typed languages, and the equivalent of liberal people in the software world like dynamic languages. If you’re like me, you will start reading this and be very skeptical and think it’s just a really contrived argument, but actually the more I read it, the more I was like, “Maybe he’s got a point.”
It’s a very long read; it could be a short book, but I think it’s a worthwhile thing to read. He’s got a fun kind of irreverent writing style. I have no idea what the title of this rant is, but I’ll just call it the Yegge Rant. I’ve talked long enough so I guess that’s my one pick for today.
CHUCK:
Cool. Alondo, what are your picks?
ALONDO:
I have three, actually. One, because I’d started working last week trying to get my head around and practice test-driven development, there’s a really good post on Jon Reid’s Quality Coding site on using AppCode, which is another tool that I’ve been trying to use more recently for better TDD. And actually you see sort of how it has a lot of the advantages AppCode has over Xcode in using TDD and as far as in [inaudible 47:05] and quick and shortcuts.
In addition to that, Spark Inspector was a tool that I mentioned while we were talking that does allow you to view notifications. I’ve used it on occasion for view debugging more than anything else, and I still find it more useful than the view debugging that we now have in Xcode.
And then finally, an oldie that I really did enjoy. I think someone mentioned earlier a thought that I had, reminding me of this article that Matt Gemmell wrote on API design some time ago. There are still some really good nuggets in there as well, and I do go back and look at it occasionally. I find it helpful when writing even locally-consumed APIs, so I’m including that one as my third and final pick.
CHUCK:
Awesome. Jaim, what are your picks?
JAIM:
I’m going to have two picks. I mentioned a little bit that I always forget block syntax, so I’ve got a site that you can check out anytime you need to figure out how do I declare a block in Objective-C? [Inaudible 47:56] variable, property, method parameter. It’s called goshdarnblocksyntax.com, and there’s a NSFW version, which I’m sure smart readers can deduce, which I tend to type because I’m forgetting how to [inaudible 48:09] my voids, but yeah, it’s a great resource. How do I pass a block as an argument to a method call? Here it is, one page – goshdarnblocksyntax.com.
The second one, I went for a training this weekend for the Technovation challenge, which is encouraging young women, teens up to early adults to build mobile apps, and they’ve got a real – I don’t remember the name of the language, but it’s similar to Scratch where you just drag things along then you can create loops and do logic and things like that. Technovation challenge runs on some weird phone – I’m not sure if you have heard of it – Android? I’m not sure, but it’s invented by MIT. The App Innovator is what they’re using. It allows people to drag things onto a screen and actually show up on an actual phone, an android phone, and so they can create their package and send it to their friends and so it’s really cool. To get young women coding, developing apps – Technovation challenge. I believe it’s yearly and it’s starting up soon. They always need mentors, so check it out and there’s probably something happening close to you.
PETE:
+1 on that. I know I always +1 your picks, but we’ve done a [inaudible 49:11] Thoughtworkers have been mentors for this, and it sounds like a really fun program, and very satisfying to do so. I recommend getting involved.
CHUCK:
Alright. I’ve got one pick. I keep thinking that I picked this last week but I don’t think I did. I’ve been reading this book The Legacy Journey by Dave Ramsey, and it’s a book about his view on wealth, specifically as he reads it from the bible. If the Christian thing is not your thing, then this may not be the book for you, but it has profoundly impacted me both on a financial level – the way I think about things – and the faith level, as far as the way I think about specific things. I really enjoyed it; I
actually cried while I listened to it a couple of times. I found many of the principles in there are very inspiring, so I’m definitely going to pick that.
I just want to throw out as a reminder that I am going to be doing the JS Remote Conference. It’s going to be at the beginning of February, so go check it out at JSRemoteConf.com. That’s it, those are my picks.
JAIM:
Very cool!
CHUCK:
Alright, well I don’t think we have any announcements, so we’ll wrap up the show and we’ll catch you all next week.
[This episode is sponsored by MadGlory. You've been building software for a long time and sometimes it gets a little overwhelming. Work piles up, hiring sucks and it's hard to get projects out the door. Check out MadGlory. They're a small shop with experience shipping big products. They're smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter @MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit cachefly.com to learn more]
[Would you like to join a conversation with the iPhreaks and their guests? Want to support the show? We have a forum that allows you to join the conversation and support the show at the same time. You can sign up at iphreaksshow.com/forum]