124 iPS Siesta with Paul Cantrell
Show Notes
01:19 - Paul Cantrell Introduction
01:41 - Siesta
07:31 - Is Siesta a specialized tool?
09:06 - Defining REST
10:35 - How Siesta Works
20:26 - Why use Siesta?
27:57 - Conversion
32:44 - Handling Requests
34:09 - Observers
35:51 - Checking
41:44 - Storing Resources, Caching
45:11 - Readability
Picks
Siesta README (Jaim)
Standing Up (Chuck)
SmartCells Anti-Fatigue Comfort Mat (Chuck)
Lifehacker Ikea Standing Desk (Chuck)
Periscope (Chuck)
Katch (Chuck)
The Complete Guide to the Alexander Technique (Paul)
Alexandros Salazar: The Ghost of Swift Bugs Future (Paul)
99% Invisible Episode #52: Galloping Gertie (Paul)
Proofs and Refutations: The Logic of Mathematical Discovery by Imre Lakatos (Paul)
Standing Up (Chuck)
SmartCells Anti-Fatigue Comfort Mat (Chuck)
Lifehacker Ikea Standing Desk (Chuck)
Periscope (Chuck)
Katch (Chuck)
The Complete Guide to the Alexander Technique (Paul)
Alexandros Salazar: The Ghost of Swift Bugs Future (Paul)
99% Invisible Episode #52: Galloping Gertie (Paul)
Proofs and Refutations: The Logic of Mathematical Discovery by Imre Lakatos (Paul)
Transcript
PAUL:
I have listened to this show a few times. I noticed that you're not too strict about sticking to the exact topic at hand.
JAIM:
Yeah. I used to have a blow horn that would flag you if you're off topic. [Chuckles]
[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 instead. 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]
CHUCK:
Hey everybody and welcome to episode 124 of the iPhreaks Show. This week on our panel we have Jaim Zuber.
JAIM:
Hello, from Minneapolis!
CHUCK:
I’m Charles Max Wood from Devchat.tv and this week we have a special guest, Paul Cantrell.
PAUL:
Hello!
CHUCK:
Did I say that right?
PAUL:
Cantrell.
CHUCK:
Cantrell.
PAUL:
Yeah, that’s enough.
CHUCK:
Do you want to introduce yourself?
PAUL:
Sure. I am an indie developer doing most of my work with really outstanding folks at Bust Out Solutions and I also teach part-time at Macalester College, and do a bunch of musical things which Google can tell you about if you're interested.
JAIM:
Google can tell you about Paul’s music. [Laughter] Was that different? Okay, sorry.
CHUCK:
So we brought you on today to talk about Siesta. Do you want to give us a brief introduction to that?
PAUL:
Sure! On several different Bust Out projects, I’ve been using a helper code that I found myself just copying forward between projects which [inaudible] it was time to make it a library and I suggested to Jeff who runs Bust Out that we should really open source it. And community minded person, he set aside a little funding for me to take the time and do that. So this is code that I wrote out of necessity on a few different iOS projects, and I was just using bare NSURLSession networking. It was the stuff that I found needed just using the native APIs and it was an abstraction that paid off in surprising ways beyond the context in which I eventually needed.
It takes somewhat different approach from other REST or networking libraries in that its corp abstraction that it focuses on is not individual requests but individual resources. So I’m calling it a resource-centric networking framework as opposed to the more familiar request-centric.
What I mean by that is that if you use NSURLSession or Alamofire or AFNetworking or RestKit or any of it – familiar libraries. All of it start with a request. You say, “Let’s kick off a networking operation and let me know when it’s done and then I’ll figure out what to do with it.” And there are a lot of different flavors of that but they all – when you really think about what they're doing, they all boil down to basically being asynchronous procedure calls – remote procedure calls. It’s all just glorified RPC. We’re treating the server as something that we send a request to and a response is tied to a request. And so now you're probably thinking ‘yes, that’s http; how else would it possibly work?’
So the problem that drove me to something different was actually – it was a tiny little problem that first helped me with this insight but sometimes it’s the small projects that lead to the biggest insights.
I had an app where there was just one piece of information from one request that mostly corresponded to one screen in the app, but it also affected what things show up in the main menu and little bits of it showed up in an entirely separate view controller somewhere else. And I thought, “This is stupid and I’d be stashing this information somewhere.” And I once again will be writing the bit of glue code that I think we all find ourselves writing on just about every network project where we say, “Oh, I need to get my requests; it’s a little bit decoupled from my view controllers.” I’ll make some sort of Singleton or request manager or model container of some kind that just coordinates this requests and hangs on to the result between screens. And I thought, “This will not be that hard to generalize.”
So what I did instead is just made a simple little cash that saves the parsed responses to http requests, keyed off of the URL and I can just ask for data by URL and if it exists, great, I get it back. Easily done. I then quickly realized that this is where things get interesting. All this time we spend – we focused on caching just the actual data that comes from a request and that’s not really enough information to make a good user interface. I want to know what’s the latest data, was there an error and I need rich error information, not just absent or something like that. And I also want to know – is it loading? I want to show at the very least some kind of spinner or something. And those pieces of information are tightly coupled. They change together; the loading indicator shows up and then it disappears and either an error message or new data takes its place. And it was that moment when I said, “Wait a minute, okay, there’s this thing – there’s a RESTful resource.”
There’s a bunch of information about it which loosely falls into the categories of request and progress data that I have for it and error information about it. If I grouped that together, then all sorts of code instantly becomes much easier to write, and problems that I thought were one of things quickly fall away. When I saw that happening, that’ when is started copying it between projects and realized that yeah, there should be an open source project.
So that’s why I’m bringing it out to the world and it’s now very new; it’s been public for weeks, really. The code is old; internally, this is a ‘In Paul Cantrell’s life’ and Bust Out’s life. This is a 2.1 release. But I’m not calling it 1.0 yet, I want other people to just kick the tires, use it with their approaches to writing apps and hear from other people about what roadblocks they hit, what bugs they hit if any and get some more people giving more perspectives on it before I call it a public 1.0. Test the project in a nutshell.
CHUCK:
So did the name Siesta come from REST?
PAUL:
Of course [chuckles] and I quickly discovered that there are several other REST frameworks in other languages that do completely unrelated things that are also called Siesta but I live with it.
[Crosstalk] Hammock but there were several frameworks that were too close to that.
CHUCK:
I was just hoping that we would get a nap today when I looked at the schedule.
PAUL:
Ugh, wouldn’t that be nice. I have a one year old son; tell me about it. [Chuckles]
JAIM:
Halfway through the show, we’d just be quiet for about 10 minutes.
CHUCK:
That’s right.
JAIM:
And what [inaudible] to our listeners, be quiet, too.
CHUCK:
Dear listener – close your eyes.
PAUL:
And if anybody bothers you about napping at work, you just say, “No, I’m learning very important information about iOS.”
JAIM:
That’s right.
PAUL:
“Please don’t bother.”
CHUCK:
So is this a more specialized tool then than other http libraries?
PAUL:
I’d say it is. It’s certainly not a general purpose networking library. It does cover what I think is the bulk of common cases when you're consuming a RESTful API. And by restful I mean that it organizes itself in terms of resources that have URIs that have identifiers. And so I wouldn’t try to make this work with a SOAP API. It haven’t helped you if you're using one. [Laughter] It’s going to be Heaven because I won't help you with that.
CHUCK:
XTML is a four letter word.
PAUL:
And XTML is not the worst of SOAP.
CHUCK:
That’s true.
PAUL:
It’s focused very narrowly on the problem of ‘I have resources’; I want to load them and update them. And I want those actions to be decoupled from the lifecycles off UI elements or different parts of the app. I just want this body of information that I get from the API to be available when I need it.
CHUCK:
I have to say though that I have built plenty of REST PIs. Most of the work I do is web – I’m starting to get into more of the arena of basically – you can get the full details on what I’m working on now if you go listen to the Entreprogrammers podcast or the episode of the Freelancers’ Show that comes out next week. But basically, I’m working on things like setup boxes and Apple TVs and stuff. But I built plenty of REST endpoints; I’m sure I’m going to be doing plenty more of that as part of this work. But so many people define REST so differently. And not all of them really – they organize themselves that way, but they almost, rather than having a resource that you post to or use different http methods to hit them a different ways in order to interact with them in different ways. I’ve seen it where you have different endpoints actually do the interactions in different ways.
You have an edit endpoint and an update endpoint and a create endpoint.
So all of those who work with Siesta –.
PAUL:
To some extent. And it’s a good point that people mean different things by REST. I mean different things by REST, then – what’s his name – the REST author Roy Fielding has his very persnickety notion of what REST involves. And it’s another tangent, but I – personally I think that [inaudible] is just unmitigated pattern lankery. I don’t think it’s a particularly useful construct for most APIs in terms of how they're used.
So what do I mean when I say REST? What it really comes down to, it is that there are end points for which get is a special operation in that get is read only and the results of a get I would like to keep around so that I can use them to keep populating user interface or doing things. So if get has a special caching status, then Siesta 2 can work with it. And I’d say it works more elegantly if end points tend to be nouns and not verbs, but that’s not a strict requirement.
CHUCK:
So one other thing that I’ve seen is I’ve seen people write libraries around REST or some definition of REST. It sounds like your definition of rest is a little bit more restrictive maybe than Roy Fielding’s but –.
PAUL:
I’d say it’s much less restrictive.
CHUCK:
Okay.
PAUL:
It is very, very specific.
CHUCK:
I haven’t read the paper so I’m only making assumptions.
PAUL:
Nobody has.
CHUCK:
[Chuckles] I know some people who have and then they say ‘but we’re doing this’.
PAUL:
Complaining about the people not reading the paper online. Yup, that’s me.
JAIM:
Most people haven’t actually read the paper or read any articles from anyone who [inaudible] who’s actually write the paper. We’re like three degrees from actual Fielding’s thesis.
CHUCK:
Right, but the way that you described it were get is a special operation, it’s read-only, access only and then maybe post or put or patch or delete, do different other things to the same resource.
I’ve seen people take that approach, and they write almost an ORM later over the top. And so it takes the information, it gets back, it serializes it into an object. It makes some assumptions about the way all that stuff works. And then when you have to update it, then it does a put or a patch depending on which is appropriate.
PAUL:
Right. And Siesta’s more flexible than the sort of thing you described. What you just said sounds, for example, a bit like RestKit – does that seem fair?
CHUCK:
I haven’t used RestKit; I’ll have to look at that.
PAUL:
I haven’t a lot. I think that RestKit may be try to solve too many problems at once and that’s something I’m trying not to do with Siesta. So Siesta doesn’t make any particular presumptions about the relationship between data that’s in a get and data that’s in a put or post. It doesn’t make any assumptions about the relationships between endpoints and it also does not – empathically does not try to hide http or do any kind of model mapping. That’s up to you; you have your approach; just go with it. Siesta has conveniences for common types, JSON and text and images and that’s as far as it goes.
What it does make a special assumption about is it distinguishes between requesting and loading. Request means I send an http request and I get a response. It’s that RPC model I was talking about. Load is an abstraction over that that says, “I make a request – it’s usually a get – and I hang on to the results of that request in a local, observable cache.” And the key really is that the cache is observable so the shift when you go from request-centric to resource-centric with thinking about things is that UI or logic that depends on a particular endpoint. Stop subserving individual requests and start subserving the resource.
And when you start observing the resource, there will probably be nothing there. The resource says, “Hello, I have no data; I’m empty.” You can then say to the resource, “Please load yourself if necessary.” That’s an inexpensive call, there’s some configurable throttling so you can just do that all the time. On view will appear in a timer 50 times a second – it doesn’t matter. And if new data ever appears for any reason, you get notified about it. And the sound as I describe it in the abstract, it sounds so innocent. Maybe a concrete example of how it simplified things would help make it clear how beneficial it can be.
Consider the case where you have a view that how some resource and some other resource that’s dependent on the first one. So for example, a user and all of their posts; so to populate that view, I first have to request the user, and then I have to request post for that user. And let’s say furthermore that the second resource is the posts. Let’s say that that’s an endpoint that I need the results of the first end point to find – that’s a fairly common thing. For example I might search a user by name and I need their ID before I could get post for that [inaudible]. Are you following so far?
CHUCK:
Uh-hm.
PAUL:
So think about how you write that code; you write a request for the user by name, then when you get a response, you kick off a second request for the associated posts and when that response comes, you just play them which looks beautiful and works beautifully in the happy path. And as soon as you start having to deal with errors somewhere along the way, recovery, retries or especially anything timing related like the user initiating a second search while the results of the first one are coming back, then all of a sudden you're just in this world of different possible [inaudible] bugs that seems stupid when you find them but you never thought of. Why is this? Because this UI can be in so many states; just enumerate them. No data for either yet; I have data for user, I have data for new user and old user post. I have data for user and error for old user’s post. I have error for the new user and I still have data for the old posts. What do you do in every one of these?
So what happens when you switch to observing a resource is that instead of having individual requests and responses to them, triggering other things, that’s where the problem is is these asynchronous callbacks – you don’t know when a response is going to come back in. And when it does, you have to figure out the proper delta between the response you just got based on the response you got; the proper data between the current state and the new state. Having something that just tracks the state of the universe and then you write your code to update based on the latest information, things become much simpler.
I can write one little bit of code that says – say I have two variables on my view controller; one is current user resource and one is current user’s post resource. I can have a bit of code that’s just update everything, copy fields out of the user, populate a table view out of the posts.
In most cases, completely repopulating the UI is not even that expensive. Usually, I can just be stupid about it. If anything changed, copy all the information in. I then – if the user of the app initiates a new search – search for, say, a new user by name, I just update both resources. I say, “Okay, now I’m no longer interested in the previous user and the previous post. I’m interested in this new user and their new post.” And at that point if a response comes in that’s out of date, that’s for the old user’s posts. I’ll never even receive it; I’m not observing that thing anymore.
I’ve defined the set of information that I’m interested in and I don’t have to worry about asynchronous callbacks coming in that I need to ignore because the UI has moved on. It is a style of programming that – it feels almost like reactive programming but without the tremendous overhead of having to move your whole app to that model. I think it’s a very interesting model; there’s a lot of promise there.
Going reactive is a big change; going Siesta is a pretty incremental change. But you get some of the benefit in that instead of worrying about these little deltas that arrive asynchronously, that is responses to requests; instead of worrying about little asynchronous deltas, you worry about what is the current state of the world and how do is how that? And there’s just this set of always true mappings that ae unidirectional from current state to current UI.
JAIM:
Okay, so if I’m trying to load a search for a [inaudible] user and the user changes its mind, we’re switching in a different user, I’m able to do both or is this a [inaudible] one user for that resource?
PAUL:
Each resource corresponds to a URL. So what you would do is switch the resource that you're observing. There’s user A and there’s user B. I start out pointing my UI at user A; user B comes in, now I’m observing user B instead. The usually pattern for this with Siesta – and Swift makes this so nice. The usual pattern for this is to have a will set and a did set. Will set stops observing and did set starts observing.
And Siesta works such that your observer callback gets pinged as soon as you start observing a new thing. So when I say, “Start observing this new user instead,” if I already have data for them, they just suddenly appear. If I have to initiate a request, well I’ll get that updated data whenever it arrives. But there’s a separate resource for each use and I just point myself at a different one to observe it. [Crosstalk] Dos that clarify it?
JAIM:
So you have two users, they're going to have different URLs; generally different by their ID. So you’ll have two different resources you could respond to but you just pass them the URL and that’s how you identify it as the user.
PAUL:
Uh-hm.
JAIM:
Okay.
PAUL:
And URL doesn’t include query string. So this is where the RESTful presumption sneaks in, which is simply that /user/123 represents a unique thing.
JAIM:
Think of level zero of the Fielding’s REST is critty URLs. I should know – let’s not try – that’s not right at all. [Chuckles] Query strings are definitely of value for critty, unique URL, but go ahead.
Sorry.
PAUL:
That’s about where Siesta stops actually. There is this assumption that you don’t have one, say, /accespoint URL that you post all different kinds of commands to. At that point, you're going to have a hard time making Siesta look like that. But I don’t think that most APIs are that obnoxious.
It’s not now, maybe 20 years ago. It’s rare that I encounter one that bad today.
JAIM:
Okay, so if you're encountering a developer who loves his RestKit or AFNetworking or plain as NSURLSession, what’s your elevator pitch for why to do Siesta?
PAUL:
My first response is, for Heaven’s sake if it works stick with it. I’m not making my living by selling this and if you have an approach you like, if it works, it’s right. What can I say. If you have doubts about your current approach, here’s maybe what the problems you might not realize that you're having look like, maybe you find yourself always writing a little glue layer that does some kind of caching of lots of responses that isn’t just the NSURL cache but holding on to lots of model objects. And you find yourself encountering bugs related to that thing being out of sync. Or maybe you find yourself encountering bugs related to callbacks coming in at the wrong time or in the wrong order.
Maybe you find yourself writing a lot of code to deal cleanly with errors. One of the benefits of Siesta is that it makes all errors look the same. So if the request was malformed or there was a transport error, or the server returned an error code or there was a parsing problem, those all come back in one place and look like one kind of thing with details available if you need them.
An example of not realizing that you have the problem is on the Siesta read me. If you take a look, I highlight AFNetworking’s remote image loading extension. Are you familiar with that?
JAIM:
Yes. And it lets you basically attach a URL to UI image view and the image view will load the image at that URL and display it when it’s available.
It takes an extraordinary amount of code to do this well. It’s easy to do it poorly. I could initiate a request every time the URL is set but that has obvious drawbacks, redundant requests. If I’m scrolling through a table view and a hundred images flash by, I’ll trigger a hundred network requests. It’s terrible. So there’s a bunch of logic, if you read that extension in AFNetworking. There’s a bunch of logic there that caches parse images and flushes them if some of them – if they're using too much memory, if there’s low memory event – and cancels the one that move out of view and initiates requests only if one isn’t already locally cached. And that whole massive – I don’t know, it’s several hundred lines of code. It’s good code but it’s just large. It takes a dozen lines in Siesta.
It’s just easy because the caching’s already there. You can just say, “Oh, there’s a URL of an image; just load that if you need to and give it to me whenever it changes.” And it’s quite a striking difference especially because Siesta wasn’t even particularly designed with that in mind; it was designed for breaking with APIs not static resources. But all of this code that AFNetworking authors is found that necessary to write just becomes immaterial. In fact the Siesta version is even a little bit robust because the caching behind it is more robust. So that’s the closest thing I have to an elevator pitch is that you may be solving the problem – same problems over and over without even realizing it. Take a look at the before and after in that comparison and see if it rings any bells in your code.
JAIM:
Most apps that you write are going to have some view controller that it has to get some data, some resource, and other parts of the app depend on that and you pulled a list of a number of approaches earlier on how to deal with that. You’ve got some connection manager and you store it somehow, you cache it. And you have been doing this and most apps have their own way of doing it. It’s more of a general approach that you can use for a large subset of apps.
PAUL:
Uh-hm.
JAIM:
Say I’ve got this resource, okay cache it. Someone else can just use Siesta and a lot of the resources there.
PAUL:
And get notifications when it changes. So one of the things that would seem scary to roll to your own app if you're doing this by hand but becomes basically free with Siesta is if one view controller causes a request to happen, and another view controller also appears that also happens to need that same data, it can piggy back on the request that already happened. So say I go to my user profile page and there’s get/users, and then while that’s happening on a slightly slow network connection, the user goes back to the homepage and jumps to their post timeline which also happens to show the current user’s avatar and username.
If that get users request is still happening, then the new view can just say, “Yes, I’m also interested in the result of that whenever it comes back.” If the result has already come back, that second view doesn’t need to initiate a new request. So there’s this sensibly paced set of request coming and going that is now all of a sudden decoupled from the life cycle of all of the UI elements that might have triggered those requests or are being twisted in their results. And that decoupling is where the benefit happens.
JAIM:
Yeah, I can see that. Yu have two view controllers that could request a user object. You have two separate things of your user clients where – [inaudible] you don’t really know that you’ve called it in a way for something to get back, it’s all done asynchronously. So [inaudible] the two requests and manage them. That’s kind of a hassle so Siesta panels that.
So you deal with the resource of user – if it has it, load it; if it doesn’t have it, okay, let me know when it comes in. and Siesta handles the glue which otherwise you’d have to manage on your own.
I can see that’s useful.
PAUL:
The common approach that I have seen for this is that you have some user state or user manager, Singleton or shared object. And it hold both the reference to the current user and a method that is like refresh user, load user. And it tries to do all of these itself. It tries to say, “If there’s already a request in progress, don’t start another one,” and then people just use, say, KVO to observe the user property of this user manager. And the thing about this problem is that it seems really easy to solve in the abstract every single time we start an app. And every single time, it just grows and grows. It becomes this little tangled mess of bulky code. It seems easy because the happy path is so easy. If everything happens in the expected order and doesn’t fail, and –.
JAIM:
And my simulator on WiFi; my code runs great.
PAUL:
Yeah, exactly. If I do the expected operations and they all completed immediately and everything works, no problem. It’s easy code to write. As soon as you have to deal with unexpected state [inaudible] changes or dealing gracefully with transitions in and out of ;there was an error’ or ‘okay, there isn’t an error anymore’ – as soon as you start dealing with all of that t just becomes a tremendous headache.
So Siesta’s goal is just to peel off that one problem, and it tries very hard to stay out of the way of the rest of your app. Siesta doesn’t have its own networking implementation; it uses NSURLSession by default but you can just inject the actual interface between Siesta and low level networking is pretty small. And Siesta also does not try to figure out how to do JSON to model mapping. It just stays a mile away from that problem because it’s complicated and there are a lot of different ways of doing it.
So Siesta tries to focus on this one layer of caching and coordinating when requests happens and how results are propagated and stays out of the way of the rest.
JAIM:
So how do you tell Siesta to convert the [inaudible] pack from the server into a user? How does that happen?
PAUL:
There’s a few ways. [Crosstalk] One – yeah well. Magic model lotto. [Crosstalk] Yes, yes, which has both its advantages and complexities. I make this sound like it’s a big deal; Siesta’s small, it’s actually less code than Alamofire last time I checked, by a few dozen lines. And it’s five or six times smaller than RestKit. It’s not a big thing.
How do you deal with models? The first way is that you just do it yourself. You cache parse JSON and if your models are little lightweight things that are cheap to create, I just create them on a flyer whenever you update your UI, grab the JSON, make your little lightweight model and update everything. That’s one approach. A second approach is –.
JAIM:
Do you get the JSON from Siesta?
PAUL:
Yes.
JAIM:
Okay, so you can just say, “Siesta, give me the JSON; I’ll map it.”
PAUL:
Exactly. But you have some other options. Another option is just use the JSON which I actually think is an underrated approach.
It’s interesting; so I do a lot of iOS work, I also do a lot of Rails work and rub shoulders with a lot of JavaScript work, and if anything I’d say that iOS developers reflexively model everything a little too eagerly. Whereas in the JavaScript culture, people think that they reusing models and aren’t; they're still just empty data which turns straight from the server. But there’s not one size that fits all.
Many apps – if an app is mostly read-only, small, doesn’t have a lot of client side logic, and basically needs to copy a bunch of strings and formatted dates from a JSON object into the UI, I’m a fan of at least considering just passing that dictionary around. I’m not saying that’s always a good idea but certainly there are apps where it’s so low impact to do that and takes so little code that I think it’s better than trying to build up a whole model layer.
So that’s approach number two, which is a tangent but I just say consider that in your app. Maybe it’s okay to pass dictionaries around – no, okay, as soon as you have logic validation, large number of developers, as soon as keys getting out of sync becomes a concern then, yeah, maybe make them the model object. But just make sure that you’re actually solving a problem when you add a model layer to your app.
The third approach is that Siesta has a configurable transformer pipeline which is basically a series of transformations that can be applied to all responses or to responses matching a certain URL pattern. And what that would let you do is say, this URL, when you get it, yes run it through the standard transformers – if it’s JSON parse, it is JSON. And then as a last step, run it through this little transformation that turns it into one of my model objects. And that takes a little more configuration at that point; using Siesta becomes slightly more heavy weight. You have to actually declare the mappings between URL patterns and models. But at that point when Siesta says, “Hey, here’s some new data,” what you get back is a model object.
CHUCK:
Yeah, the thing that occurs to me, this reminds me of a library in Ruby called Faraday.
PAUL:
I am familiar with Faraday.
CHUCK:
So it’s not – Faraday isn’t specifically designed for REST. It is legitimately just an HTTP request library and you can make any kind of request you want. But yeah, you have these transformations libraries – your middleware – that essentially sits on top of it and you can stack as much of addition need on there to transform the responses or the requests to be formed into whatever you need them to be.
PAUL:
That’s exactly right. And the transformer pipeline in Siesta looks a lot like the middleware in Faraday. And it’s also, I should say, it’s one of the areas that is still an active development. Before we get to 1.0, I don’t think it’s quite as easy as it should be to mask map a bunch of models, and so for the 1.0 beta 3, I’m looking at ways of simplifying that, just reducing the programmer burden a little bit, and documenting it better.
CHUCK:
Yeah, and I’m sure that as more people use it, it becomes easier to know exactly where you can improve that.
PAUL:
That’s exactly right, and I really encourage people; I would just love feedback form anyone who just kicks the tires and hits a road block. Sure, hit it to the curb but when you hit that road block, please let me know what it was that hankled you up because there’s really no way to know what a framework needs until more than one team has used it, and right now this is mostly a single team framework.
CHUCK:
So do you usually see this as something that backs a data model? So it’s kind of a network access layer for it? Or is it the other way around where your view controller or view are going to make a
call to Siesta to get back the data or data type or data source that they're expecting?
PAUL:
Either. And I really do try to support both models. Siesta tries not to concern itself with who initiates requests or who observes the results of them. So in the simplest approach, maybe you don’t have a model layer or you have a very lightweight model layer and you have fat view controllers; fat view controllers are the observers; they observe things from Siesta. And they just pull data straight out of the Siesta resource when they receive updates.
At the other end of the continuum, maybe you have a very sophisticated model layer. Maybe, in fact, your model layer becomes the Siesta observer and it says, “Okay, when changes come in, I integrate the new JSON or the new response with some grand view of the world I have. And then what the heck, I propagate changes out through reactive Cocoa and there’s ten layers of complexity there and it goes through my grand MVVM screen as well.
Siesta shouldn’t get in the way of either of those and if it does, then it has a design problem. It’s designed to not have opinions about that particular question.
CHUCK:
So you use the term ‘observer’, so is this sort off pulling endpoints or does it only check or sync when you tell it to?
PAUL:
It only checks when you tell it to. The observer in Siesta, you observe a resource and if anything causes the state of that resource to change, then it’s a push based thing.
CHUCK:
Okay.
PAUL:
Observers get notified. There’s the question of, “When do servers get called?” They get called if the state of a resource changed. It’s just a higher level thing that’s very similar to KVO and its basic mechanics.
There’s also the question of when does he had to actually try to refresh a resource from the server? And that’s something that’s very much up to each individual app. I’d say there’s two common approaches I find myself using. So yes, it’s very much up to each individual app. I’d say there’s two common approaches I find using. So yes, it provides a load method which just forces a request right now, redundant or not. And it also provides a load if needed method. So you can configure both globally and per resource, a staleness parameter that says, “Look, users – if it’s up to date within 30 seconds, I don’t care. Just return the latest data.” And load if needed will respect that. It says, “Okay, if I don’t have data or if the data’s old, then trigger a request.
If I have data that’s not considered stale and just returned it immediately – and I just say by the way, there’s supposed to be HTTP headers that control how long response data is valid for, I have rarely encountered an API that sets those headers reasonably or in a way that has anything to do with what the app needs.
CHUCK:
Yeah.
JAIM:
How are you checking that a resource has change? Do you download it again and just verifying it? Is there – get a [inaudible].
PAUL:
Load it for me that’s first checked is local and it’s fast, it’s nanoseconds fast.
CHUCK:
Right, so if it goes, “Oh, I know this from 25 seconds ago. That’s new enough. I got the answer; here you go.” [Crosstalk] That’s wicked fast.
PAUL:
Yeah, it’s less expensive. It’s as expensive as DOS’s current time call. And what that means is that for example, if you wanted to have a polling-based application that updates a resource every 60 seconds, well, configure the time out for that resource, the staleness parameter to be 60 seconds. And then heck, set up an NSTimer and call load if needed 10 times a second. It won’t slow your app down. It’s a really cheap call but when you hit that 60 second threshold, then boom. An NA IP 10 times a seconds is excessive but the point is load if needed is an extremely cheap call most of the time until you hit the staleness threshold.
At that point, Siesta has this wonderful advantage of having a parsed version of a resource right there and it respects e-tags. So if it already has a local copy and that local copy has an e-tag, then Siesta can respect the 304 and not just say ‘hey, no change’ but it’ll actually give you the same parsed object back yet again, which means that if you're lucky enough to be working with an API that actually understands 304’s which is certainly not always the case, then yes it touches the network but you get extremely fast responses to a check that results in no change to data.
And then the third case of course is that the server says, “Yup, there’s new data”. At that point whenever view response comes in, Siesta parses it on a background thread, it serves a DC background cue that does all of the DC realizations. And when the new data comes in, it updates the resource and notifies all of the observers on the main thread that, “Hey, this resource has a new data.”
JAIM:
Okay, so Siesta does some logic with the kind of server with their e-tag or check in the responses to make sure that we’re not literally loading down that resource a number of times.
PAUL:
Right.
JAIM:
Okay.
PAUL:
It look inside the HTTP exactly as much as is appropriate to the problem it’s solving. So there are just a few pieces of information that actually have to do with when we need the update state and when we can afford that, and the rest of Siesta passes through.
I should also mention, if you're used to working or got frustrated with some higher level framework, Siesta exposes all of the request and response headers and it’s up to you to do whatever your API needs. If you have some authentication scheme, or there’s some special header that actually affects what the model looks like, it’s available to you.
Siesta tries very hard not to hide those things; that’s the responsibility of some other layer of your application.
JAIM:
Yes, that’s a good approach. I like frameworks that keep things simple and let people see what’s actually happening. The more you try to hide something, the more you run to an edge case where your abstraction just doesn’t work, which I’ve run into with RestKit. I knew what I wanted to do but I couldn’t figure out how to wire it up correctly and the documentation wasn’t that great, but as long as I know what’s happening because – [inaudible] what’s happening under the hood, I just need a little help sometimes. I don’t want to write all that code. I like the approach and I appreciate that.
PAUL:
But it certainly aims to be – actually I don’t know if any of you know Radek who blogs nicely on Swift – suggested to me that I really should call it a library and not a framework, which is a fuzzy distinction to me but I liked what he meant by that which is this isn’t a grand answer to everything. It peels off one layer, it’s focused on a specific problem. And it does a lot of footwork related to that problem but finally it’s just about dealing with when do we request things, what do we do with the responses and how do we propagate them back to the people who are interested in them? That’s it. That’s the scope of Siesta. It’s not trying to do too many things at once.
The problem of bad abstraction is one that we deal with a lot. I know recently. You had Sam Giddins on this show talking about the limits of modularity which I thought was a nice interview. Listening to that interview, I had a thing that kept going to my head was just, yeah, sometimes modularizing really does amount to just drawing a line through your code and it’s a bad line. You try how to break a piece of code into two pieces, well those two pieces kind of have to make sense each one of them on their own. A good abstraction doesn’t just mean reduced dependency, it doesn’t just mean I put the code in separate files or separate libraries. It means that I’ve taken something that’s complex and reduced it to something that’s conceptually simpler. I’ve come up with some metaphor for thinking about the problem that makes my code easier to write than it was without that metaphor.
For example, if I say ‘list’ to you, you know what a list is or an array. You know what that is; I don’t have to explain it. You don’t have to know exactly how it’s implemented. You can hide details of consecutive memory, locations or link list or blah, blah, blah – a list or an array, there’s things; they have an order.
There’s a bunch of them. I can add and remove and get a count. And there’s a concept that I can’t get my head around that allows me to not think about a bunch of implementation details and I’d like Siesta to get to that point where you can really think about just – there’s a resource. It has a state. I can ask for that state to be updated and I can observe changes to it without having to think quite so hard about exactly when request are triggered and how they get cued and how responses are handled and blah, blah, blah.
JAIM:
I didn’t ask before – how do you store these resources? Are they – is it a memory? Do you cache in to disk [inaudible]?
PAUL:
You can; there’s a little empty interface in the project for caching things to disk because I had needed that on one project. Let me speak to the in memory thing first. By default, Siesta caches fully parsed responses in memory. And the advantage of that – this is one of the big advantages of we’re just using NSURLCache is, for example, n that remote image view, if you’re flipping through a table view very fast and you have three or four different icons that are remotely loaded, you can just observe those three or four image resources and not worry about calling load if needed a lot, calling at observer and remove observer a lot using Siesta to provide the image to you. It’s cached the parsed image already. Getting a cache resource is designed to be very, very fast.
So in memory, it stores cached things and then it has a little intelligence so that in default, it hold everything but if there’s a low memory event, all of the cached references become weak references. If your code is still using one of those images, it doesn’t disappear from the cache but everything that’s currently unused just vanishes and then will be re-requested again as needed.
And then there’s also the option, if you want to cache things to disk, the use case for that is making your app startup as if it were already launched very quickly. But that’s not a core use case for the 1.0 release and I’ve just left the interface there. In the future release, I might provide some reasonable defaults implementation of it but not for now.
JAIM:
Very cool. Yeah, I’m looking forward to trying this out if they get to solve the problem that most of our apps have. Have you run into any cases where BDD is too specific for doing with a library like this?
PAUL:
How do you mean ‘too specific’?
JAIM:
Like the problems that you’ve solve in with this particular app, you're fighting the library versus it’s helping you which can be the problem with frameworks. Like, “I want to do this thing it wasn’t designed to do.” Have you gotten into it?
PAUL:
Yes, that is the problem with frameworks. I haven’t, though I have the advantage of being the author and simply knowing when it’s inappropriate I will say this – since generalizing this code, I haven’t run into a RESTful API where it wasn’t helpful. That said, it’s not appropriate for all kinds of networking if you're doing some kind of socket based thing. If it’s not HTTP, clearly not the appropriate thing.
If you're doing large background downloads to files or something like that, maybe online updates, that’s not Siesta’s domain. Of course the nice thing about it is that you can always just drop down a layer; it doesn’t stop you from using other network frameworks. But no, I haven’t run into a case yet where clearly it was the wrong thing for interacting with an API and I’m interested to see that case when it comes up. That’ll tell me a lot about what the framework needs or what it should excuse itself from being.
JAIM:
Yeah, I think it’s a reasonable approach for most of the apps that get bills. They can handle every little custom thing but it shouldn’t.
PAUL:
Np, and it does aim to cover the 80% case well and not get in the way of the other 20. Staying out of the way is a high priority. Should say the other – the high priority I have for this is something I learned from venturing in to the Ruby world and then coming back to the more C-like world of iOS is the readability of code really matters; conciseness matters. And the Siesta API has more conveniences than it strictly needs, but in places where I felt client code was a little too verbose or a little hard to read, I added things to the API just to improve readability. That’s been a priority for this framework.
On the iOS side, I see things – in general, I think the culture is weaving in that direction a lot with Swift which I’m really pleased to see. Objective-C is such a verbose language we almost – we get conditioned to just seeing so many characters on the screen that we sometimes forget to aim for readability even when it’s achievable in Objective-C. But using a language that is a little more concise and perhaps a little more flexible lends itself to a wider array of programming techniques.
I see people coming back to the readability question with Swift and I’m really glad to see that taking hold in the iOS world more than it has.
JAIM:
Yes, it’s been a problem for a long time – Objective-C. All characters on every line is the standard code standard and I never got that. I can read it now a little bit.
PAUL:
It’s a hard language to format well no matter how is it you slice it.
JAIM:
White space are the enemy.
PAUL:
Yeah. [Laughter] White space is a beautiful thing. I really got a handle on my thinking about this issue reading Edward Tufte who talks about the Data-Ink Ratio that is how much information is conveyed per thing on the page that my eye has to process. And there was a day – I think it was probably early 2000’s – just looking and envisioning information, this lightbulb went on and I thought, “Wait a minute, code is information design.” When we write code we are doing information design for ourselves and for other humans. We have to make sense of this thing. If it weren’t information design, then we would just write everything in machine code and be done with it because computers don’t care. But readability matters because it helps us think about things and if you're not familiar with Tufte’s books, for example read his quite compelling argument that both space shuttle disasters were, in large part, due to bad PowerPoint slides.
In both cases, people at NASA had the necessary information in order to make the decision – the correct decision – not to launch. That information was poorly presented because it was buried in bullet points in a bad slide, and the decision makes didn’t digest that information and made the wrong call.
So yeah, communication matters; how we present information matters and that applies to code. It applies to formatting, it applies to style choices and it applies to API choices, too.
JAIM:
And also, bullet points can kill.
PAUL:
Yes. [Chuckles] They aren’t called bullet points for nothing.
JAIM:
True. Oh, I didn’t get that.
PAUL:
And bad information design has real world consequences. Not much code out there is actually as critical as space shuttle decisions but bad information design causes bugs. If you can’t understand it, then you can’t make it correct. I’m sorry, but no matter how smart you are, your code is only as good as your comprehension of it. That’s something that we’ve – working with Objective-C we learned to sneer at that idea that – but it is an important idea.
JAIM:
I agree.
CHUCK:
Anything else we should dive into before we go to picks?
PAUL:
I could chat all afternoon but perhaps we should wrap it up here just for the sake of listeners’ ears, right?
CHUCK:
Yes, unless there’s something else important about Siesta that we didn’t talk about.
PAUL:
I encourage people to read the docs and to tell me what’s important about it that I’m missing. Again, this is – on the one hand, it’s production quality code. There are apps on the app store already that use it, but I’m just not going to stop calling it beta until I have some good feedback from lots of different people.
I would love to hear your thoughts, the results of your experiments. Even simple things like pull requests for typos in the docs are very welcome at this point. So kick the tires, let me know what you think. I’m eager to hear from you.
CHUCK:
Alright, well let’s go ahead and get to the picks. Jaim, do you have some picks for us?
JAIM:
Man, I don’t have any picks today. Everything is just okay. I will say I do appreciate the ReadMe of Siesta [inaudible].
PAUL:
Thanks.
JAIM:
You can also [inaudible] and I read it and I actually chuckled to the center. It’s an entertaining read and it does give a good comparison about frameworks, like we have [inaudible] before. A lot of good info in there. So that’s my pick. How often do you get a ReadMe pick? [Laughter] Never, right?
CHUCK:
I’ve got a pick. I’m trying to find here on my Amazon orders, but I have a really nice anti-fatigue mat that I use. So just to back up a little bit – here it is. It’s SmartCells Anti-Fatigue Comfort Mat for home or office! It’s 24 inches or 36 inches – I don’t remember which one I got.
But anyway, I’m going to pick standing up. Yesterday, when I recorded Ruby Rogues, I stood up for the entire episode. My legs were pretty well worn out yesterday after I was done but I feel like it’s important to get out, move and spend some time standing up. And there have been a ton of studies that show that’s pretty important.
On Monday, I actually went golfing with my father-in-law. He came up and he dragged me up to the golf course, kicking and screaming. I really didn’t want to – okay, so I had to get time. And yeah, it just really drove home to me how much better I felt when I was done. As supposed to how run down I’ve been feeling before then because I just haven’t been making it a priority to get out and move. So I’m going to pick that; I’m going to pick this anti-fatigue mat.
And then I’ve also got a standing desk. And I know I’ve mentioned it on the show before but it’s just the – it’s the Lifehacker Ikea jabber. In fact, if you do a Google search for lifehacker standing desk, it’s 25 bucks for all the parts and then I had a couple of woodscrews that I use to put the shelf up and it works great. It’s nice to just get up and be able to stand while I work. So I’m actually trying to get to the point where I can stand and anytime I’m on a call with anybody because most of the calls I do anymore over Skype. And so I’m going to move my webcam over there and I’m going to move my other stuff over there. And that includes the podcast so I’m actually going to move my boom mic and stuff over there. So my mic – boom and my mic over there.
9:
30 in the morning, mountain time, everyday you can figure out what time it is for you if you want to jump on. But if you get to Periscope app, follow me on Periscope then you can do that. Or if you're following me on Twitter, you could just click the link and watch it on the web. But on the web you can’t send hearts and you can’t send messages, so if you want to reply to what I’m saying either by tapping the screen and then I get a bunch of hearts that show up or you can actually reply the network.
And then my other pick related to that is there is a system that Katch.me, and that’s catch with a ‘k’. And that actually then downloads the Periscope calls so the people can play them back later because Periscope, the way that it works is after you do the Periscope video, the video’s available for 24 hours and then it disappears. But katch actually catches them and then I can post them on a blog or a podcast, etc. I can also download the videos and so that’s what I’m doing. I’m going to put those on to a podcast feed and then if you are absolutely insane and want to hear me everyday for five to twenty minutes, the longest call I did was for about 20 minutes and then you can do that. But I’m just going to do an audio journal or video journal and just talk through some of the stuff I’m thinking about.
So obviously not everything is going to come to [inaudible] but a lot of the stuff I’m talking about is just stuff that I’m thinking about. And I’ve had some good feedback on it so far so we’ll see how that goes. I don’t actually have the videos posted anywhere yet but I will let people know where to get that stuff.
And finally the last deal with is that I am also considering putting out a weekly newsletter where I just give some thoughts – general advice for programmers. So it can be anything from how to learn stuff to stuff you should be learning, to career advice to ways to be more productive, ways to find a better work-life balance, all kinds of stuff like that, probably some things about freelancing. So if you're interested in any of that then keep an eye out on Devchat.tv. I’ll probably have the [inaudible] form up later this week. So those are all my picks.
Some of those are stuff that we’re doing and some of those are the tools that I’m using to do them but I feel like the context is important when I’m talking about some of the stuff. Hopefully that helps you out.
Paul, what are your picks?
PAUL:
It wasn’t one of my picks but piggy backing on what you’ve said, I also would just put in a good word for standing desks and in particular, I’ve just found it wonderful to have a setup where I can switch between sitting and standing regularly throughout the day. I don’t find either position particularly comfortable for extended periods, but just being able to change it up periodically has done me a lot of good.
And also put in a good word for the Alexander technique. It’s the only posture-related program of any kind that has ever made any sense to me and I actually found it surprisingly useful. It’s very popular with musicians but I would recommend it to programmers.
My picks –.
CHUCK:
What is it, the Alexander technique?
PAUL:
The Alexander technique – it’s a general technique that’s taught by a lot of individual instructors in various places. Google it; there’s probably somebody who does it near you. And it’s very little of ‘stand this way, do that, do that’ advice that I got about posture. It’s much more just practicing being relaxed and learning to pay attention to what that feels like and then giving you almost neuroscience hack for changing habits that cost you to be uncomfortable and tense.
It was developed in the 19th century but it’s weird; it feels like it was developed by people who had fMRI’s of the brain. A lot of it is about just figuring out how to change your attention so that you can notice that you're doing something terrible to your back. It’s weirdly effective, so a good word for that.
The picks – first, I just want to point out a blog post called The Ghost of Swift Bugs Future by Alexandros Salazar. It’s a very particular point but one that I think is a bit surprising and certainly a dangerous pitfall about the way protocol extensions work in Swift 2 that the method, the functions in a protocol extension can be either dynamically or statically dispatched and they don’t look any different. It depends on whether it’s specified in the protocol that the method extends. So if you just heard that and thought, “Oh my God, what?” then read this post. And if you just heard that and said, “What? What does that even mean?” then definitely read this post.
It’s certainly, as he said, the ghost of bug future and I disagree with him; I think it’s a design flaw in Swift. I think it’s something that they’re going to have to revisit in the future release because it’s so potentially just catastrophically confusing.
Second pick, I love the podcast 99% Invisible. I’ll just say if you haven’t heard it before, I would point out to software engineers the episodes on Galloping Gertie which is the story of these Seattle to Colmeneros bridge that collapsed due to bad engineering. And the way they covered this bridge collapse is wonderful for programmers because so much of it is about how we talk ourselves into bad decisions and how we move forward with bad decisions even long pass the point when we should know that our decision was terrible. It just – what does it feel like to be wrong and how does wrongness persist, and how does our human fallibility translate into engineering failures.
It’s a lovely little ten minute piece and it begins with one of my favorite quotes of all time which I will leave you to discover. If you like it, then you could do worst that to just listen to the entire run of the show. There is about 160 or 70 episodes and about 99% of them is outstanding.
The third pick is just a favorite book of mine called Proofs and Refutations for the truly geeky out there. It’s a book about mathematical philosophy but I also think it has a lot of relevance for programmers. It’s – surprisingly, because it’s math philosophy. How dry could it be? It is not only short but funny. It’s a little imaginary play in a classroom in which the professor presents a proof and then the class discovers counterexamples to the thing that they thought they just proved. And so the whole book is an examination of what mathematical truth is and how we really know things and how we know what words mean, how we map concepts to abstractions.
At first it seems like it’s just about mathematics but by the end I think it has a lot to say about software, about how we constantly try to come up with better concepts and try to refine the concepts that we have by building software using them. And by building software, we discover what’s wrong with the concepts that we’ve developed so far.
And so there’s this dialogue between notion and implementation that’s just an endless cycle of sharpening and improvement. And even thought the book was written in the sixties, it still speaks to how good software gets written today. And I should say also it does not require any kind of deep math. You need to understand junior high school geometry. That’s about the only requirement.
So for the adventurers, I’d recommend that one as well. Those are my picks.
CHUCK:
Awesome.
JAIM:
Cool.
CHUCK:
Alright, well if people want to find out more about Siesta or about Paul, what do they do?
PAUL:
If you want to find more about Siesta, we have a fancy website, Bust Out Solutions has some really stellar designers who – honestly, that’s one of my favorite things about working with this consulting; it’s just they give really nice signs to implement and if anybody’s implemented a bad knows how nice it is to implement a good one. So one of our designers just threw a little bit of light styling on the Siesta page and there’s user guide and pretty colors that you can read through.
If you want to find out more about me, my website is innig.net. Most of the stuff on there is about software – excuse me, it’s about music and not software, but if you enjoy music check it out. I’m also a concert pianist of modest ability. And you can follow me on Twitter @inthehands. You can follow Bust Out Solutions @teambustout.
CHUCK:
Alright, we’ll go ahead and wrap up the show. Thanks again for coming, Paul!
PAUL:
Thank you for having me.
CHUCK:
Alright, we’ll catch everybody next week.
[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]
124 iPS Siesta with Paul Cantrell
0:00
Playback Speed: