DAVID: You don’t actually have to accept call requests. We just use them later for when we’re unemployed and we just start going through the past guests going, “Do you guys know anybody that’s hiring?”
DAVID: Or wait, is that just me?
JAMES: Is that how you do it?
DAVID: Because if it’s just me, I have some business to take care of before we start. Michele?
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to RubyRogues.com/NewRelic.]
[Does your application need to send emails? Did you know that 20% of all email doesn’t even get delivered to the inbox? SendGrid can help you get your message delivered every time. Go to RubyRogues.com/SendGrid, sign up for free and tell them thanks.]
CHUCK: Hey everybody and welcome to episode 147 of the Ruby Rogues Podcast. This week on our panel, we have David Brady.
DAVID: Surprise! Thought you got rid of me, didn’t you?
CHUCK: James Edward Gray.
JAMES: No, we hoped we had.
CHUCK: I’m Charles Max Wood from DevChat.TV. And this week, we have a special guest and that’s Michele Titolo.
MICHELE: Hello. Thanks for having me.
CHUCK: Do you want to introduce yourself since you’re new to the show?
MICHELE: Sure. So, I’m Michele Titolo. I am an iOS developer living out in San Francisco, doing it for a bunch of years now, shipped a lot of apps. I also do a bunch of other stuff. I contribute to CocoaPods, which is the Objective-C library dependency manager. I’m also CTO of Women Who Code.
MICHELE: So, you can ask me anything. [Laughs]
JAMES: That’s awesome. I want to talk to you about all of those things.
JAMES: That’s awesome.
CHUCK: Alright, let’s talk about CocoaPods.
MICHELE: Okay, cool.
MICHELE: No, no seriously. That’s what’s usually happens. I’ll introduce myself like, “These are the things that I do,” and everyone’s like, “Oh, CocoaPods.” I’m like, “Awesome. But there’s this other stuff too.”
CHUCK: Yeah. Didn’t you do an episode on NSBrief?
MICHELE: I did do an episode on NSBrief. I think that was also on APIs. [Laughs]
JAMES: Chuck, you sometimes remind me of Arsenio Hall. And I mean that as a complement.
CHUCK: I was going to say, “I’m not sure how to take that.”
JAMES: I used to watch his show late at night and I was always blown away by how he would have guests on and he had read their book or whatever. He somehow knew everything about them. And I have no idea how he did all that. And you, we just have guests on and you’re like, “Oh yeah, weren’t you on such and such?” Cool.
CHUCK: It’s the power of Google and listening to NSBrief.
JAMES: The power of Google.
MICHELE: Yup. Yeah.
JAMES: That’s awesome. Well, I invited Michele on today because of this kind of old but still cool post that I found on how to build APIs that don’t suck. So, Michele works with a lot of APIs and maybe that’s where we should begin. How come you work with a lot of APIs?
MICHELE: So, as many people know these days with mobile, you don’t just make an app that’s going to be on a phone that only ever deals with its own data because that’s kind of silly. There are some that do that, like to-do lists and productivity things.
MICHELE: But for the most part, you want to be able to access your data from multiple places. And for that, it pretty much means you need a web server. So, I’ve released over a dozen apps to the App Store in the course of my career and every single one of them has used some sort of API. So, [chuckles] I’ve worked with a lot of different APIs, a lot of different settings. Big, giant enterprises to really, really small bootstrap startups, because the APIs are like the app’s lifeline. You can’t really do much unless you have data.
JAMES: And also, it helps make things multi-platform. If you’re going to target many platforms, then you can just build the frontend for each one and have the API.
MICHELE: Exactly, exactly.
CHUCK: So, you’re saying that everybody should build an Open Graph API, right?
MICHELE: Not necessarily. One of the really interesting things, I’ve been doing consulting for about three years, and one of the most interesting things in terms of API that I’ve seen with that is there are two scenarios when you’re working with a new client. And one is they don’t have an API (this is the most frequent one), in which case you help them along in building and figuring out what they need. But two is when they have an API that was designed for something else. And I did an app that they had a Backbone site that they were using on, I think Tablet at the time. So, we were able to use a lot of those endpoints, thought they didn’t quite all work the best way. But it was still something. So, it’s very rare to have a company that, “Oh, we have a mobile API ready for you.” It’s usually, “We don’t have an API,” or, “We have an API for this other thing. Can you use it?” And I think we’re getting to the point in technology right now where that conversation’s changing and instead it’s, “We need to build something new. We need to build and API first,” which I think is awesome.
JAMES: Start with the API, yeah, yeah. I worked for a company that we often work with, government agencies and stuff like that. They tend to be a little behind the curve and we’ll say, “Okay, we need to be able to get all your data.” And they’re like, “Yeah, just scrape our site.”
JAMES: It’s like, “We had something a little more sophisticated in mind. But that could work.” [Chuckles]
MICHELE: Yeah. I’ve seen places that do that and you don’t quite get the full experience, especially when you’re dealing with stuff like authentication and customizing the app to be around the user. And don’t even get me started on push notifications. [Chuckles]
MICHELE: You cannot do that with a data scraper. [Chuckles]
JAMES: Right, right.
CHUCK: That is true. I’ve actually built a push notification service for iPhones.
JAMES: That’s cool.
CHUCK: Yeah, it’s not terribly hard. But it is interesting. And it’s really funny how reliant you are on the web when you are on the mobile stuff.
JAMES: Right. And that’s not even, we don’t talk about mobile a lot on this show because Ruby, obviously. But in our area where we spend a lot of time building web applications, even there the APIs are becoming supremely more important all the time with a heavy move to things like SOA architectures and stuff like that. So, splitting an app up into a bunch of little pieces and having them communicate with each other, almost always that communication happens through some form of API, or I guess you could say message queues too is popular. But at work we have probably 30 Ruby processes talking to each other all the time and they all communicate using APIs just sending messages to each other. So, it’s a big deal, I think, in almost any industry of computers, because I actually heard someone say once, and I can’t remember who, that there’s no such thing as a well factored large application, that once you go to a certain point, you need to start breaking it up into pieces to keep it under control. So, those are all the reasons why APIs are important. So, you wrote this post about how to make better APIs because I assume you’ve seen some not better APIs.
CHUCK: You’re being nice. It says how to write APIs that don’t suck.
MICHELE: Yes. [Laughs]
CHUCK: So, it’s not, better and not better. It’s sucky and not sucky, I think.
JAMES: How to make APIs that won’t make me tear my hair out at the…
MICHELE: [Laughs] Basically.
CHUCK: I have a solution to that. Dave has the same solution, I think, to tearing your hair out. [Chuckles]
JAMES: Yeah, we could tell from your Skype pictures.
DAVID: Yeah, it involves a BIC Razor.
JAMES: Our listeners don’t get that joke. [Chuckles]
CHUCK: What, they can’t see my shiny head? [Chuckles]
JAMES: So tell us, you had four points, Michele. Why don’t give us the first?
MICHELE: Okay. So, the first point is conventions. So, when I wrote this post, oh gosh, last year, it was after I’d done a lightning talk. So, I do a lot of speaking. I try and write a blog post after I speak because my slides are pretty much just single words and they’re useless. So, it’s been really interesting seeing how the conventions have evolved, even in just a year. But even stuff like, “Don’t roll your own authentication. Use OAuth. Use an HMAC signature,” to HTTP verbs when you’re using a get, when you’re using a PUT, and when you’re using a POST. Are you using DELETEs? Even just using conventions that are already established in the world of APIs, like if you have .json at the end of a URL, you should probably return JSON. You know, [pretty good]. But also, establishing conventions within your own API, because I’ve done a lot of work with APIs that were not built as a group of APIs that we intent to work together to be this cohesive thing. I remember at one point, I did a graph of we were getting a same object back from I think three different endpoints. And each endpoint had different keys. [Laughs]
CHUCK: Oh, wow.
JAMES: In the same object? [Chuckles] That’s awesome.
MICHELE: So, I think it was a product. Each product obviously has an ID. And one of them, it would just return id. One of them was product_id. And I think one of them was productID.
JAMES: [Laughs] That’s awesome.
MICHELE: So, establish your own conventions and use them everywhere, because then I’m not going to be hitting an endpoint from the client side expecting to get a product_id and all of a sudden I’m getting id. And now my app has this bug where I’m like, “Why is this not showing up? Why is this nil?” when it’s really the payloads are not consistent with each other. So, it’s conventions that everyone uses in the entire world of development (you can pick and choose those) and also conventions within your own system to make sure that it makes sense. [Laughs]
CHUCK: So, I think some of the conventions are pretty well understood, like using REST or SOAP or you know, some of those…
JAMES: Not SOAP. Please, don’t use SOAP.
MICHELE: Please, no SOAP. [Laughs]
CHUCK: I’m just throwing it out there.
DAVID: I want to challenge the beginning of that statement, that these are well understood.
DAVID: Because I’ve seen them implemented [inaudible].
JAMES: Oh my gosh, we just did a SOAP API at work last week and it was like stepping right back into the 1980s or something.
JAMES: Don’t do it.
CHUCK: What I’m saying is that they define certain specifications and conventions to follow. The thing that I run into most frequently is like you’re talking about with the data structure. And there are a lot of different ways of doing things. And I don’t really see conventions around JSON or XML (God help us).
CHUCK: Or whatever other format you’ll be getting stuff back in. And so, it’s not just the naming of the keys. I think that’s a pretty obvious one. If it’s the same thing, it should be named the same thing.
CHUCK: But things where it’s like, “Do I nest? Do I not nest?” In JSON, “Do I have a key at the beginning that defines a specific type?” Things like that. And besides being consistent, are there certain approaches to that that make more sense than others to you?
MICHELE: Yes and no. It’s one of those things that there are some standards for certain things. Like there’s a header called, I think it’s like Link header or I forget the name of it. But there’s a header that you can send that passes URLs for pagination kind of things. So, there are some standards out there for common things, pagination being probably the most obvious one because everyone does it differently.
DAVID: So, you’re telling me that there are HTTP headers to pass that are standard for pagination?
MICHELE: Yeah. They’re not standard but they are part of the specification [Laughs] for HTTP. Yeah. People don’t realize this. I remember having this debate a couple of weeks ago with some coworkers. And we couldn’t figure out if we wanted to use the header or if we wanted to have the information within the response. And this is something that I’ve seen happen, time and time again, because of the way that mobile clients process the data, which is slightly different than web clients. We don’t always get the full headers back by the time we’re actually using the data.
MICHELE: So, if you’re doing infinite scrolling, is the most obvious example, the user scrolls. So then, it’s a user action that eventually will trigger the request for more data. And how do you handle that? Because something needs to be keeping track of, “Am I on page four? Am I on page five?” Or if you’re doing something like you request with an offset, someone needs to be keeping track of that. So, being able to get that information, obviously the API needs to tell you where you are. [Chuckles] But then, how to communicate that information from the response that you get to the actual view controller in iOS, which is the thing that most often displays our screens. It’s a weird mix in MVC. Is that the one that’s keeping track of a pager or is there a separate object? Do you have some special data model thing that takes care of pagination? There are all these architectural concerns with something as simple as infinite scrolling sometimes. [Laughs] We have this joke in iOS that we frequently get one view controller to rule them all.
JAMES: Right, yeah. [Chuckles]
MICHELE: We all this one view controller that has a thousand, three thousand, I have one friend who said she once saw a 30,000-line view controller.
JAMES: That’s awesome.
MICHELE: And we don’t like those. [Laughs]
JAMES: Oh no, that’s fine. You’re fine.
DAVID: We can be impressed by them though, right?
DAVID: You see something like that and you’re like, what’s the quote from Anchorman? “I’m not even angry. Seriously, that’s amazing.”
DAVID: It has to go, but it’s amazing.
MICHELE: Yeah. So, a lot of these structures that the server is sending to our clients will actually have an effect on how we architect, which is why things like conventions are so important. Because if one endpoint is sending us a link header and one endpoint is sending us a block in the JSON that has all the metadata, we have to handle that differently. And now we have basically parallel implementations or one object that has to handle both things, which is never fun, to be able to handle pagination. So, it’s been really interesting to see how decisions on something like an API on the server side can really affect a mobile client, because we’re so tightly coupled in some ways.
CHUCK: Yeah. Can I point out another pet peeve on this?
JAMES: Go for it.
CHUCK: HTTP has these really nice things called status codes.
JAMES: [Laughs] No, everything, it’s 200.
CHUCK: That’s right. Everything gets 200 and then you send back a JSON object, or yeah.
JAMES: Explaining the error, right?
CHUCK: Right. So, you have success, true/false, and then error blahdy, blahdy, blah.
CHUCK: Because you don’t have access to the logs for your app, so you’ll never know what actually happened.
MICHELE: Well, that’s not true. [Laughs] There are ways to do that these days, thankfully.
MICHELE: Finally. [Chuckles]
CHUCK: You can send a body back with most, I said send a body back and my brain brought up an image of a body bag. Anyway…
CHUCK: But you can send information back besides just the status code. And that’s usually enough information for your client, if your client doesn’t have access to the backend, to tell you what’s wrong.
JAMES: It can also be really helpful if you’re doing something like AJAX for example. And so, you pull it back. If everything’s 200, then you have to have some special code inside of the success callback to figure out was this actually a success or something like that, whereas of you just use a proper code like maybe 403 Forbidden or something, then that will go to the error callback and you can handle it there.
MICHELE: Yeah. And we do the same thing in iOS. There’s a bunch of frameworks for making web requests because the stuff that Apple gives you is really, really raw and low-level. And it works if you’re doing something really simple. But as soon as you want to get to parameters and then you want to encode it to JSON and sometimes you have some requests where, “Oh, you need to send URL encoding for this one request,” and that’s just a mess. So, we have some open source things. One’s called AFNetworking. That will automatically hit success and failure blocks depending on the status code. So, I’ve definitely written some code where there would be an endpoint, it comes back, it has a 200, and you’re like, “Hold on a second. We need to check for the error key.” [Laughter]
JAMES: Right. It’s probably okay, but who knows?
MICHELE: Yeah. So, it’s like basically you’re rerouting all of your API calls through a certain funnel to make sure that, “Oh, well this one API call can return just an error key. This other one will have something that’s called errors.” [Laughs]
MICHELE: So, even I have seen error messaging not be consistent. But it is really good to have error messages, because on clients we usually display the error messages to the user, because we don’t know what went wrong. [Chuckles]
JAMES: Right, right.
MICHELE: The user’s trying to log in and their password’s incorrect. The server needs to tell us that because we don’t know.
JAMES: But that’s actually one of the arguments, I think, where status codes can be very helpful, is that 401 is unauthorized or something like that. So, then you know it was a login problem, right? So then, you could choose to take them back to the login screen or whatever. You could make a more intelligent decision hitting the status codes with not as much work, as opposed to, “Oh, let me just parse this arbitrary English error message,” or something.
MICHELE: Yup, exactly.
JAMES: Oh yeah, I think that’s a great point. With what you said on consistency, when I call, you mentioned before a route that’s got a .json at the end of it, then I expect my error to not be a webpage.
MICHELE: Or HTML, yeah.
JAMES: Right, yeah. You hit it and it’s like, “Oh, something went wrong. Here’s a webpage.” It’s like, “That’s not what I’m doing right now. I’m talking JSON.”
MICHELE: Yeah, no I’ve actually seen some funny crashes happen because there used to be, before Apple introduced their own JSON native serializer, we had to use a third-party kit. And that one, there at one point was a bug where if you tried to pass HTML into it, it wouldn’t fail and just fail, it would crash.
JAMES: That’s awesome.
MICHELE: It can be fun. [Laughs]
JAMES: Yeah. That’s a good point on consistency. Alright, anything else or should we move to the next point?
DAVID: Well, I have a question to throw out about consistency. I have a few, actually. Simplicity often is, well, almost by definition the enemy of optimization.
DAVID: And sometimes, people take simplicity to its logical conclusion and you end up with an app that is very, very, very, very, very slow, because you have to do REST calls to query each of the thousand objects and you’re waiting on the wire. How do you balance that?
MICHELE: That really comes down to optimizing. I’ve been a big proponent, both at companies I work with and also in some of the talks I’ve given, about making sure that your API provides the correct data. My philosophy is to load a screen on an app I should have to make at most one API call.
MICHELE: That’s what I want.
JAMES: That is so good. Yes.
MICHELE: At most. If I don’t have to use anything and it’s just, “Oh, I have this piece of data and I have that piece of data and I put the data together, that would be great.” But usually at most, I want one API call.
MICHELE: And that does usually require some special customizations. So, it’s a balance. It’s do we want to make this API super, super, super customized? A really good example of one that is that customized is the Instagram API. I’ve played around with it a little bit. And if you’re doing a search on Instagram with the API for a tag, it will return you the data you need to essentially recreate the Instagram feed view. And that’s it. That is all the data you get. And it is highly customized, but it’s all highly performant.
JAMES: Right. I was going to say to that question, I had a point I wanted to add of there are a lot of ways to stand up an API now that are really easy. Use this. Rails has a structure for it. “Here’s how we do it: we declare resources and you get these seven routes,” and all that. But the problem with those is, in my opinion, those are often a way to stand up an API that’s basically a shell over your SQL database.
JAMES: So, it reflects how the data is stored. So, hit this action if you want to get a list of items. Hit this action if you want to get all the details on a specific item. And I would argue that’s often a terrible way to make an API.
JAMES: The API should reflect how something is used, not how something is stored, right? And that’s what Michele was just talking about there. The Instagram API, you hit the feed stuff and you get the bits you need to know to make the feed, because that’s how it’s used. And who cares what the backend for that looks like and how that happens? It’s how that data is conveniently built. And I’ve run into more trouble, you run into the n+1 query API problems because it’s the way it’s stored in the database. And I have to get the list and then I have to go through and the list doesn’t include the descriptions so I have to go through to each entry and get the description of each of those items. And thus, what should have been one API call turns into 11.
DAVID: A common thing that I see done with this is you’ve got an app that’s looking at a dashboard and it’s showing you all of the other users and it’s showing you your recent feed items and it’s showing you the Instagram stuff from your friends and all this stuff. And the middleware or backend developer will not provide a resource for the dashboard. They’ll just say, “Well just query the user’s controller and the Instagram. Just hit those seven things.” And then the customer comes back and complains the dashboard takes three minutes to load.
DAVID: And you know what? We need a dashboard API that will give you all of that crap, right?
JAMES: Right. That would give you the top-level overview.
MICHELE: And there’s some really cool stuff you could do these days. I saw a talk or a blog post a couple of months ago on using something like Mongo as essentially a caching layer. So, there are all these really cool caching things you can do to make something like that dashboard API actually be really performant.
MICHELE: So, there’s definitely ways to optimize it without having to just be like, “Okay, let me query Instagram. Let me query my user’s feed. Let me query my user’s friend’s feed,” blah, blah, blah, blah, blah.
JAMES: Right. That’s a good point, that you could introduce, even if you’re going to go with one of those low-level stand an API up over the database, you could then put a layer on top of that that somehow intelligently organizes that.
DAVID: So, the other thing you mentioned in following conventions, you talked about if you have a URL that ends in .json it should return JSON data and that stuff. Do you also get into, if you’re going to have a search API call, your query should be the q key, q=something? Do you push that hard on convention following?
MICHELE: Yes and no. It’s one of those things that I’ve done a lot of search stuff because of e-commerce.
MICHELE: And it seems that every company I’ve done search with has a different implementation of it.
DAVID: Yup [chuckles].
MICHELE: Simply because they have not only searching but they combine it with filtering. So, you’re not only searching for a blue car, but you’re searching for a blue car that is a 2006-2009 and is either a Toyota, Honda, or a Ford. So, I’ve done a lot more work with things like search that’s actually a POST rather than a GET.
MICHELE: Because it just, the amount of information that was needed [chuckles] was just not sufficient to have in a little q=.
DAVID: Yeah, okay.
MICHELE: And it’s also much more descriptive, I think.
MICHELE: The q= if you’re just doing a plain text search of a single term, maybe with offset or a page size or something. But as soon as you’re getting into the advanced search, which is what most mobile does anyway, it reaches its limitations. When I’m developing and I’m printing out the log or I am opening something like Charles to inspect my web traffic, I would much rather not have a URL that’s three lines long. [Chuckles] I’d rather be able to see, I’m hitting the /search with a POST and these are my json parameters.
DAVID: And here’s my payload, yeah.
MICHELE: Because that’s just easier for me to parse as a person.
JAMES: I think you had a really good point there, though. You mentioned that q, we get that now. It’s a standard thing. Probably even my parents see it regularly because they google. And it’s there. And we know that q means what you searched for, your query. And that’s just a standard. Just like when we write a for loop, we typically call that variable that iterates over indexes i instead of index or whatever. It’s just we know what that means. But if you’re doing anything more complicated than that, like you said, if you have these other fields, then spell it out if. It’s not painfully obvious, then spell it out.
DAVID: Yeah. I’m coming around to q. I hate the q parameter on principle, on experience, and probably on personality.
DAVID: And I’m coming around to it because everybody’s using it.
JAMES: But he drives a nice car.
DAVID: Yeah, exactly.
DAVID: Do you ever see conventions where, how to phrase this, if you have a find method or a search method, or a method to GET an instance of an object and yet an instance to PUT one and an instance to destroy one? That’s most of a REST API at this point. You really need the update method. Do you ever see convention issues where, you know what, you’ve implemented two-thirds of a standard collection of methods and you need to finish that collection or you need to not implement it that way? Do you ever see that?
MICHELE: All of the time. [Chuckles]
DAVID: Okay. Could you give a better example than my poorly worded version? [Laughs]
MICHELE: [Laughs] Well, one of the things about using APIs that weren’t designed for what I’m using them for is the fact that they’re often incomplete. And there will be ways to, as you say, I’m going to get a list of objects. Great. I can POST to create a new object. But say I want to update a piece of information on one object, my biggest pet peeve whenever I’m updating an object, I hate sending the entire object. That’s my biggest pet peeve because it’s wasteful. If I need to update one key, I want to send one key.
JAMES: So, you’re a fan of the PATCH verb.
MICHELE: I love my patches. Yes, I do. [Laughs]
CHUCK: But I think you should send the whole collection when you want to patch one.
JAMES: [Laughs] The whole collection?
JAMES: I changed entry number seven.
CHUCK: No, I’ve seen that before where the only update you have is mass update. DAVID: Oh, yeah.
JAMES: Replace the massive collection? Yeah.
MICHELE: Yeah. That does not work. [Laughs]
DAVID: Here’s a new SQL dump of the database. Please upload it.
MICHELE: Yeah. So, I’ve seen places that don’t have that update functionality simply because it wasn’t there. There was no need for it yet. As APIs get built out in a very organic manner where it’s, “Oh, we need this thing. Oh, we need this other thing. Oh, we need that other thing,” usually there’s not someone looking down and saying, “Oh hey, we have three-quarters of a REST call for this. Let’s finish that out.” It’s usually, “Okay, we have these three things. We’re done. Let’s move on to something else.”
MICHELE: Especially on companies that do a lot of agile, that’s more what I’ll see, rather than, “We have all the REST verbs for this object.”
DAVID: And I’m torn on this one because YAGNI, right? You Ain’t Gonna Need It. So, I’m definitely against over-building stuff. But if you implement three-quarters of something and you don’t need that last quarter, maybe don’t waste money and time building that needless thing. But you should at least put a stake, a trellis basically, in the code that basically says, “If you need this, make sure that the vine grows this way.”
DAVID: Don’t come in and write a custom thing for this. Just come in and write the fourth method and you’ll be done.
DAVID: How much of that do you mark out as comments in the code or some type of review system? And how much of it do you just depend on the next developer to be a grownup? Because that second thing, I’m starting to become more cynical about humanity. I’m just going to phrase it that way.
MICHELE: You know, whenever I’m on a project, because I’ve done this so many times and I’ve seen going two-thirds of a way through a project and then realizing that, “Oh hey, this endpoint we didn’t think we needed, we actually do need it.” So, whenever I have the pleasure of helping design the API and figure out what the needs are and how the architecture is going to be, what are the data types, I always try and make it as complete as possible. Because you’re skipping ahead to one of the later points in the blog post, [chuckles] which is expect the unexpected.
DAVID: Okay. Yeah.
MICHELE: Because you don’t know what’s going to happen in the next six months or the next year. So, this thing that might take a day to make now might save you three weeks of work, because you don’t have to go through and, “Okay, we need to get this feature on the roadmap. We need to allocate a developer for this feature. Oh, the developer that built this the first time around is not available to do the work in the time that we have. So, we need to get another developer who then doesn’t know the codebase,” et cetera, et cetera, et cetera.
DAVID: Right. That’s actually a really good point that we glossed over. This is a thing that you see a lot in mobile where okay, if we’re all doing Rails and we’re not doing mobile, everyone’s a full-stack developer and everybody knows the whole system, then yeah, leave that call out because adding that call back later is easy. You’re not spending a day to save three weeks. You’re spending a day to waste three weeks of maintenance on something that you’re not using.
DAVID: But if you’re writing out a middleware layer and you’ve brought in contractors to write that middleware layer, if you’re a mobile programmer and you don’t do any backend work and you brought in contractors to write the backend and they’re gone, finding out that you don’t have something that you need is now very costly. And so, that’s something you should consider as a project risk. And so, if that was the case, I would absolutely say, “I want a robust API here, because I’m going to use it in a way that you don’t expect.”
JAMES: I also want to point out, and this is just one of my pet peeves and I run into it all the time, YAGNI stands for You Ain’t Gonna Need It. And what it means is if you pick a feature, you’re like, “Oh, I should add delete because I’ve done this six normal actions. But they didn’t ask for delete or whatever, so I should add delete.” If you’re doing it just to fill that out, or whatever, then that is a violation of YAGNI. That means that you had no reason to suspect there was a delete needed. Whatever. You filled it out just to check some checkbox or whatever. That’s a YAGNI problem. This is what’s not a YAGNI problem that I see people throw YAGNI on all the time, and that’s if your boss has been telling you from day one, “You know at some point, we’re going to have to support X, Y, Z. Blah, blah, blah. We’re not doing that now, but at some point, at some point, at some point,” and you start architecting the code to make it easier to support X, Y, Z, that is not YAGNI. [Chuckles]
JAMES: You are going to need it at some point, or all signs point to you are going to need it. So, planning for it as opposed to getting to the part where you finally need X, Y, Z and you have to rewrite the entire thing because you didn’t plan on that, that’s terrible, in my opinion.
DAVID: Yeah. Architecting an interface or what Michael Feathers calls a seam in the code where you can tease the code apart at that seam and replace it with something, yeah, if you know something’s coming, definitely don’t weld those two pieces together. Put a seam in between them so that you can replace it.
DAVID: Yeah, I totally agree. And it’s exacerbated with mobile, yeah.
JAMES: Right. And I’m not saying go architecture astronaut and try to plan out the whole thing. I’m just saying, “You know what? When that feature comes, it’s probably going to be here. Let’s go ahead and leave a hook or something.” Yeah. I think that’s a good point. Let’s go onto the second point. We’ve [inaudible]
CHUCK: I was about to say that. We’ve spent most of our time talking about one.
DAVID: Yeah. Well, the convention one is the one that I have the most ammunition on. In fact, I actually have one more question. I’ll throw it out and then if you guys don’t like it, we can just delete it from the call.
JAMES: Fire away.
DAVID: Or you can just mock me and leave it in the call.
JAMES: Always my favorite.
DAVID: Chuck will laugh about this because he’s seen this happen, because we were on the same team when we did it. This is a little bit of a confessional. We had an app that had to have a lot of data that did not change very often, like in your e-commerce site. We’ve got to send you all of the car manufacturers, Ford, Chevy, et cetera. This doesn’t change very often but it does change. And we’d like to not rebuild or recompile the entire app every time we do this. But, if I force the end user to request the list of auto manufacturers at startup time, you run into this problem where the first time they access your home page, they’re waiting for all of the global data for the app to load. Have you seen that problem a lot and have you seen a good fix for it?
MICHELE: I’ve seen that problem a lot.
MICHELE: [Chuckles] Because when someone downloads an app for the first time and launches it for the first time, the last thing you want is a blank screen or a spinner that’s just going.
MICHELE: Because the user will close the app and never come back.
JAMES: This app will complete in 45 minutes.
CHUCK: Well, and Apple won’t approve it if it does that. They’re picky about that.
MICHELE: You’d be surprised what gets through.
CHUCK: They’re not supposed to approve it if it does that.
DAVID: They approved the crime reports app. I’ll just say that much.
MICHELE: So, there’s this delicate balance. This is usually tackled in two parts. The first part is when you’re actually getting your app ready to submit for the store. You usually do a local cache somehow. So, we usually have some sort of build scheme action that will hit the API, download a bunch of the data, download a bunch of the images, and then put it into the app. So, when the user installs it, there is something there so that they can immediately have something that may be a week old, two weeks old, but it’s something. And that happens every single time you submit to the store. So, a user downloads version 1.0, there’s a certain set of pre-cached data. A user downloads version 1.2, there’s a newer version of cached data. So, it gets updated as frequently as you release your app. But then you also do have to do the whole, “Okay, there’s this one set of information. We need to make sure it’s updated. So we need to check for that.” That is something that you just can’t avoid. And this is where things like etags…
MICHELE: And cache control, if-modified-since, that’s where those headers really come to shine, because it’s a lot nicer to be able to make a request and do an if-modified-since. If this was modified since I last opened the app, send me data. If not, tell me all is well and I can proceed.
MICHELE: Because you still need to do that call. But if you don’t get data back and you don’t have to process the data, and the app doesn’t have to go through and say, “Okay, I have these two lists of things. Let me see if they are the same,” that is so much better for the user.
JAMES: Ah, I see what you’re saying. If you don’t do it with the intelligent way, by checking tags and stuff, you pull the entire list and then you’ve got, “Okay, now I have this old list, now I have this new list, and I have to reconcile all the differences.”
DAVID: You’ve just leveraged the inefficiencies of both solutions, right? You’ve got a bigger download when you get the app and you have to wait for the stupid list to download when you use it.
JAMES: Right. [Chuckles]
MICHELE: So, it’s one of those things that you always try and think about as early as you can, because I know a lot of APIs that don’t make use of those headers. And I want to see people using them more, because I would much rather get no payload. If I can send you something and it comes back with no changes, that is the most awesome thing for the user and for the client, because then it’s just nothing.
CHUCK: Yeah, you don’t have to do anything.
DAVID: Yeah. Okay, I said that was my last question, but I have one more.
DAVID: I promise. I promise I will shut up about this.
JAMES: That is awesome.
DAVID: So, what I’m hoping you’ll tell me is that this is starting to become a well-solved problem. But I’ve seen this so many times. This is right up there with don’t get involved with a land war in Asia.
MICHELE: Yes and no [laughs].
MICHELE: So, if you’re designing around data, that’s just going to be painful for everyone probably. But if you design APIs in terms of experiences, that can be really great for one and terrible for another. Or if you have similar enough experiences, it could actually work really nicely.
DAVID: That should be the motto for this entire episode, is design APIs for experiences. So many times, you see applications where the API is a really faithful model of the database.
JAMES: Right. And that’s just crazy. It’s like Michele said. She described it right off the bat. If you have a JSON API and a mobile API and you’re talking to one of these things where you’ve got to make five calls to get all the information in a collection, they’re both going to suffer.
JAMES: Nobody wins from that. That’s not how the data is being used. And the API endpoints reflect usage or experience, not storage.
CHUCK: So, the question that I have then is we did talk about a dashboard. So, do you make an API call for dashboard and have it give you back all of the objects or records that it needs to? Or do you actually do that per widget? Because then you’re going around the typical convention of saying, “Get me all the users,” or something like that where that’s pretty well-defined by REST or whatever.
MICHELE: I would say that’s when, if you’re doing something like a dashboard and you really, really want to be highly performant and you have those data-driven APIs available, this is when something like a middle layer for caching will be your best friend, because you can have some caching layer that you hit that one caching. It’s like /user-dashboard or whatever. And that has all of the information about all of those other different data objects already cached. And it can go and refresh them individually. So, it’s like a two-step process where you have the underlying database APIs that might be used by other things. Or you just might have been lazy and left the Rails default ones in there for example. But then on top of that, you create something that is highly customized to what you’re doing, because that’s how you can optimize your performance.
JAMES: One of the cool advantages about something you’re talking about, like a caching layer, is the concern with adding the whole separate dashboard action is then, “Okay, I’m going to repeat how I do these queries and stuff. So then someday we change the query of how we get the users and have to remember to hit that in both places where it’s being done twice,” whereas this caching layer, because it’s just reading from the lower data layer but then saving it in a more intelligent way for that usage, it’s going to be aware of changes underneath as they happen. So, it’s kind of cool.
MICHELE: Exactly. I’m always a big fan of creating at least one layer of abstraction so that something can change underneath you and then it doesn’t necessarily break everything. [Chuckles] Because I’ve had apps where we were in development and it was release day, and new version of the API server, all that codebase goes out. Then you open up the app and things are broken.
MICHELE: That’s what everybody doesn’t want.
JAMES: Let’s talk about clever people.
JAMES: [Chuckles] That’s awesome.
CHUCK: You want MyApp.com off of the file system?
JAMES: Right, yeah. Let me get that for you.
CHUCK: I know exactly where that is.
MICHELE: Yeah. So, that was fun. And that was just one instance of being clever. But my point about being clever is kind of what we’ve been talking about with the whole data-driven APIs, experience-driven APIs. But also, not having things be really super complicated. If I need to get a piece of data, I should be able to just get that piece of data. I shouldn’t have to go through the normal REST thing where, “Oh, this piece of data is nested four levels down.” I shouldn’t need to make four separate requests in order to get to that data because there are other pieces of information I need.
JAMES: So, a classic example for me is comments on a blog. Let’s say I’m going to pull a list of comments and I’m going to display them under the article. It may be more “correct” to have the users in a separate place, except I actually need that information to display the comment. I need to know who it was from. I need to know their email address so I can grab their Gravatar or whatever. I need that data. So, just put it there. It’s about experience again, like Michele says. I have to have that data to make sense of this data, so just give it to me.
MICHELE: Yup. And this is one of the things that I’ve seen work differently between different platforms. So, on my last job I made a little Rails app for a little internal app that we were using and built the iOS version. Android engineer built the Android version and we were doing caching differently. So, there were some endpoints where the iOS app had that user information already, because we were basically preloading users because of some other things we were doing. But the Android app wasn’t. [Laughs]
MICHELE: So, I had to go back and modify the payloads so that Android could do that. So, there are definitely different ways to be clever. And probably the coolest thing I’ve seen is one of the other CocoaPods team members, Florian Hanke, has this thing called picky, which is for searching. And he redid our whole CocoaPods search API around this where you can actually pass in how deep of data that you want to get. So, you can get back a flat array list of IDs.
MICHELE: You can get back an array list of pod name, GitHub URL, author email, author name. So, it can be highly customized.
JAMES: That’s cool.
MICHELE: And he was able to do it in a pretty performant manner. I haven’t seen that done in any APIs that I’ve used because obviously, performance things. But I definitely think that stuff is really cool. And I personally would like to see that used more, because I would love to be able to say, “Hey, the iOS client already has the user information. So, I just need an ID.” And then the Android app can be like, “Oh hey, we don’t have this user information yet when we get to the screen, for whatever reason. So, I need the full user object.”
DAVID: Yeah. I worked on a system last year that flies against the ‘Don’t be clever’ rule. But I would say the exception to ‘Don’t be clever’ is you can be clever as long as you are solving the problem that’s actually in front of you. And we did a layered API where you would basically say get me the post and all of the comments from the users and it would get back all of the text and the user name. And it would display out and it would leave a space for their avatar images. And the reason we did that, we didn’t include avatars or any of the really heavy-duty heavyweight data, was because it turns out that the users of this system were all on 3G networks. They were out in the middle of nowhere, doing natural research. So, they’re on radio towers. They’re lucky to get 256k downloads. And so, the first hit we would give them all of the data. And they could be scrolling through things while avatars slowly came down. And they could go to a different page and just abandon the avatar download thing. If they wanted to wait for the avatars, they could. So, we did it in a layered approach where yeah, you could basically say, “Give me all these things but don’t give me the really big data that’s just there to make it pretty. Give me the essential and then go back and make it pretty.” And it was a multiple request thing. But we did that deliberately so that we could rely on the local cache and basically get off of the wire as much as possible.
MICHELE: Yeah, cool.
JAMES: Yeah, that makes sense. If you have reasons to do those things, [inaudible].
DAVID: And that’s, sorry I’m really bad at having points today, aren’t I? My point was you can be clever, but solve the problem in front of you. Don’t solve problems that aren’t in front of you.
JAMES: I had that this morning. I was pairing before I came on this show and somebody had submitted a bug on the CSV library. And so, we went hunting for it and figured out what it was. And it was like, “Oh, we can just pass this extra parameter.” And so, we passed this extra parameter and that broke an expected interface. And so, a bunch of tests began failing. I was like, “Oh, well we can make that one optional.” So then, we made that one optional.
JAMES: And then it was like, “Okay, but when it’s not there, you have to do it this way.” And we did that. And my partner, all the credit to my partner for talking me off the ledge. It’s like, “Okay, we’re now three levels beyond the actual problem.
JAMES: Maybe we should go back.
MICHELE: It’s like that gif that was going around Twitter last week of the guy who comes home and the light bulb’s out. So, he goes to get a screwdriver and there’s something wrong with the screwdriver.
MICHELE: So, he can’t. And then he’s like, “Okay, so I have to go to the hardware store.” And then it turns out there’s a problem with his car. And he has to fix his car. And then the wife comes home and she’s like, “Oh, did you notice the light bulb’s out?” And he’s like, “What do you think I’m fixing?”
MICHELE: Because that’s what happens. [Laughs]
JAMES: Yeah, too true. Almost always, when you just get ridiculously clever and you’re thinking, “This will be the greatest thing ever,” and then somebody reads the API documentation and their eyes just glaze over.
DAVID: Yeah. I have to confess, I do really enjoy just that smooth feeling of a freshly shaved yak.
JAMES: We all do, David. That’s the problem.
DAVID: Yeah, that’s the problem. Yes.
JAMES: That’s the problem.
CHUCK: I need to go look up a yak call.
CHUCK: That I can put in a soundboard.
JAMES: [Laughs] That’s awesome. Okay, so documentation, which we were actually just kind of talking about in one way. What do you have to say about documentation?
MICHELE: Please have some?
CHUCK: Yeah, my documentation is, “This is a RESTful interface.”
MICHELE: Yeah, no. That’s not useful.
JAMES: Yeah, that’s not helpful. Not helpful at all. Especially since nobody knows what that even means. [Inaudible]
MICHELE: Exactly. Especially once you get into the different flavors of REST, which there are many of, as I’ve seen. So, my favorite type of documentation to receive is one that has an explanation of all the endpoints, explanation of all the parameters including what type of stuff should I be sending. Should I be sending a string? Date formats? Are you doing true/false or 0/1 is also a big one, because JSON parsers in Objective-C will automatically go to 0/1 most of the time. Fun story. And then things like, “I would like to be able to click a button and make a request,” in your documentation and also have samples. Because a lot of the times when we’re going through and building up our responses, our models, and all of that stuff, I want to just quickly go through each object and say, “Okay, I’m getting this key from the server for that property. I’m getting that key for that property. And I want to do all my mapping.” So, if I don’t actually have a response that shows me what’s nested, what are the different connections, what do I have to do to transform, since JSON doesn’t support a lot of types, things like dates, I always have to write a custom date formatter. It’d be like, “Okay, so the server is sending me this kind of date format.” So, I need to parse that into an actual date object, because that doesn’t happen automatically. So, yes, documentation is good and documentation that I can interact with is fantastic. I’ve also gotten documentation. I’ve gotten Postman JSON files. I don’t know if you use Postman. It’s a Chrome extension that lets you make web requests. But it has the feature that you could create a collection and you can save out URLs, parameters, headers, all of those things and export them. So, that was really cool. And that’s the kind of thing I would like in addition to, rather than in place of normal documentation.
MICHELE: Because that has the ability to prefill things like authentication tokens where you get all of your information about how your parameters interact, what kind of headers you want. It can all be there and you just literally click send and it will make requests for you. Because most of the time, when it comes to API problems and when you’re debugging, usually it can be solved with really good documentation because then I know whether to send true/false or 0/1, whether I know if you’re using Unix timestamps or your own custom timestamps, as well as things like, “Oh, I updated the server and changed this param type and I didn’t update the documentation,” [chuckles] which also happens a lot.
MICHELE: So, documentation is really important because it just makes everybody’s lives easier. [Laughs]
CHUCK: I like what you were saying about JSON. It has some standard types for certain things, but dates isn’t one of them. So, if you’re going to take a date, then that documentation needs to clarify what your application considers a date. And I think it’s standard to use ISO-8601 or whatever it is the standard date formatting. But even that is a massive range. If you look at all the things that that accepts, boy, it’s hard to write a string that doesn’t fit that specification.
MICHELE: Yeah. And the thing about the way that specifically Objective-C handles dates is it’s almost like a regex kind of thing where I literally have to have a hard-coded string that is a date format in order to parse it into a date, which is why whenever anyone talks about dates I’m like, “Just send me a Unix timestamp, time since the epoch, please. Integers.” That is so much easier, because it’s a number. [Laughs]
MICHELE: Rather than, “Oh, does this format have the T in there? Is there a space there? Is it a capital Z?”
JAMES: Yes. I know exactly what you’re talking about.
DAVID: And just so we’re clear, those seconds since the epoch are in UTC+0.
JAMES: Yeah, exactly. That’s a really good point. And a lot of these issues, defining the type and all of that, there are other ways you can do this, too. For example, we talked earlier about the HTTP Link header. One of the things the link header can be used for is to define a profile. So, if you have a JSON, your payload for example, then like we said, JSON defines the structure of your data but it doesn’t necessarily define what the individual keys and stuff mean. And that is, you can attach a profile link into the request. And then people can look at that and bring up your documentation. And that can explain what the individual parts are you’re expecting. So, I would call that a good practice to do.
MICHELE: Yeah. And another thing about documentation that’s always fun is that people don’t think about the lifespan of APIs. So, someone downloads an app on their phone today. They could still be running the same version of that app in a year.
CHUCK: Yeah, that’s true.
MICHELE: So, it’s important because there are a lot of apps that get made. And then they go into maintenance mode. So, they don’t really get updated that much. And then someone has to go back and update the app or even just update the API. Because if you have a new developer working on some backend stuff, having that person know how this thing is used is really important.
CHUCK: That leads me to one question. Should you be versioning your APIs, then?
MICHELE: Absolutely. And you need to plan for deprecation with version 1 [chuckles], because it’s going to happen. I actually only updated my iPad to iOS 7 about a month ago. And the only reason why I actually updated it was I started getting emails from LinkedIn, because I had the LinkedIn app. And they were saying they were going to be deprecating the version of the API that that app used so that the app would no longer function. And so, I was like, “Oh well. I should probably update my iPad anyway.” And then obviously, the emails stopped. But they were able to tell that I was using, not only an older version of the app, but that they were turning off that API. And you need to tell people when you’re going to do that. [Laughs]
JAMES: Give some runway.
MICHELE: Give some runway, exactly.
JAMES: Michele, have you worked a lot with hypermedia APIs or at all? Hypermedia APIs, kind of the new REST-y thing.
MICHELE: Yeah. I’ve worked with them a little bit, probably not in the really, really standard sense of the word. But there are definitely some things that I like about them.
JAMES: Yeah, so I don’t want to go too far down this rabbit hole because it’s easily an episode by itself and we should do that at one point. But I will just say a couple of quick things because it plays into the stuff we’ve just been talking about. So, to give probably the worst definition ever…
JAMES: A hypermedia API is basically an API that treats APIs like webpages. So, in a webpage you load up a webpage and that page has some links on it or some forms or both. And by interacting with those links and forms, that’s how you know where to go. And you see something else or you submit the form and that’s how you get some different kinds of data, et cetera. In a hypermedia API it’s the same way. You make a call to some action. It comes down and it may include links to other actions, so we were talking about pagination earlier. It may have a pages thing. You’re on page one. If you want to go to page 10, here’s the URL for that. It guides you around the system. And forms, there are different ways to encode forms and stuff, too, for what you can submit. So, one of the reasons I say this is it kind of falls into the documentation category. It’s that you pull that first request and it shows you what requests you can make. And it helps guide you around the API. And this is a powerful form of documentation in that one, it helps you explore. But also two, it can actually be a kind of documentation for the actual app, the client on the mobile in Michele’s case, in that for example: say my server is overloaded right now. I’m running Twitter or something. And I’m overloaded right now so I can’t let you tweet because I’m trying to get that under control, or we have a denial of service attack going on, or whatever. Trying to get that under control. So, if I send down the request and I just don’t give you that tweet form, your application could intelligently respond to that. It could show you your tweet o stuff. Maybe we still are doing okay on reading, just not on writing. It could still show you your tweets. But because it doesn’t have the form, it doesn’t give you the tweet button. And then you won’t be tweeting right now because the application was able to use the documentation as well as the developer. And so, it’s an interesting way to think about some of these problems. And very powerful and worth looking into. I won’t say there are not tradeoffs. Obviously, if you have to make a request and then find out where you’re going to go and then you have to follow that link, that can be really significant if you’re on a mobile, especially in a situation like David described where you’re on limited bandwidth or something. It can be hard to have the resources to make the actual request and stuff. So, there are tradeoffs like anything in programming. But another reason I brought it up is that generally, the hypermedia way of thinking is don’t version your APIs. And they have some reasons for that. There are certain rules you can follow on the client. And then if the server obeys those rules when they introduce changes, it is actually impossible to introduce changes in a non-breaking way. Like I said, it’s complicated and we probably should go into all of that. But I’m just saying there are other ways to think about these things. And hypermedia’s interesting on some of these points. So, if nothing else, it’s something that people should look into.
MICHELE: And just one comment from a mobile perspective on why I would like to see more hypermedia is because we always have to hard-code URLs. That’s just how you make requests, is you have a string and you need to compose the string with all the different parameters. And so, something like hypermedia where you are given a URL or getting the user for example, I personally much prefer that. Because then I can just have a user object and then have that user object keep track of whatever its URL is. So, anytime I want to update the user, I just use that property that is given to me to do that, instead of having to worry about, “Okay, here’s MyApp.com/b1/users/blahblahblahblahblah.”
MICHELE: And then you can, as long as the payload doesn’t change, you can update that. You can do performance optimizations. You can switch servers. You can do everything as long as where you get that, as long as you have the one place where you can get that URL that’s consistent.
JAMES: Yeah, what you’re saying is really powerful from the server end too. Because say users get extracted out into their own service for performance issues or whatever, that URL can just point somewhere else. And then now you have [inaudible].
MICHELE: Yup. And it helps with versioning and deprecation of APIs because then if the payload doesn’t change and the only thing different between version 1 and version 2 essentially is the fact that it’s now a different service, the app doesn’t care. App doesn’t care where it gets its data from, as long as it’s in the correct format.
JAMES: That’s right.
DAVID: Right. You’re not changing the shape of the payload, but you’re changing the content of what the API returns. So, technically you haven’t changed the version of the API, right? You’ve changed what the API has in it and it can be equivalent to an API change in the other style. But ultimately, your payload shape is the same.
JAMES: Right. And good hypermedia clients follow certain rules. One of the rules is ignore anything you don’t understand.
JAMES: So that if you add something to the list of things you could do on a given page and it’s scanning over that and it just doesn’t understand it, it’s like, “Oh, whatever. Skip.” And that allows you to make changes without having to specifically version your API and stuff. And there’s more to it than that. I’m definitely simplifying. But you get the idea. Cool stuff to look into. A friend of the show, Steve Klabnik, has a great book on it called ‘Designing Hypermedia APIs’ and I’ll put a link in our show notes. You should check that out.
JAMES: Alright. Did we cover it?
MICHELE: I think so. Because you already did the fourth lesson, which is expect the unexpected.
JAMES: Expect David Brady.
DAVID: Hi. [Laughs]
CHUCK: People gonna do dumb stuff.
DAVID: Wait, are we still talking about me?
DAVID: I had to ask, so that answers the question, right?
CHUCK: Alright. So, should we get to the picks then?
CHUCK: Alright. James, do you want to start us with picks?
JAMES: I can do that. I have two picks this time. First of all, we switched off of Campfire recently for our company chat. And we moved over to Flowdock, which I think Avdi has mentioned on the show before. But if you are still using something like Campfire and you have not moved over to Flowdock, you are totally missing a killer set of features. Just to hit a couple of the highlights that have been super popular with our crowd, you have this ability in Flowdock to basically fork the chat at any point. So, you’re just chatting along. Somebody mentions something and that turns into the big running topic. You can just hit a button and follow just that stream of related messages, or split those out, have two conversations at once about different things. And follow it without having to read the chat and figure out which one’s going to which one. It will show you which one’s going to which one because of these little highlighting and stuff. Really cool stuff, if you work with several people. And another feature that one of our friends loves is they have an IRC bridge. So, you can just connect over IRC if you like. And you’re in the channel and you still get most of the features including that forked chat I was talking about. It pulls that off. Amazing stuff. So, Flowdock. Super cool set of features and stuff. If you’re still on Campfire, you really got to check it out. My other pick, just for fun, I’ve been playing a game called Don’t Starve, which I got off of Steam. And I would describe it as kind of a 2D Minecraft-like thing except crazy hard. I die all the time. And it’s great and just really has you working for it. And I know the first time, I think my record now is I’ve lived 13 days. And I just know, the first time I have this long great run, I’m going to feel like it’s been a massive accomplishment in my life because I’ve had to work up to it incredibly well. So, if you enjoy a good challenge, it’s a fun game. So, those are my picks.
CHUCK: Awesome. David, what are your picks?
DAVID: And so, I’ve had to start taking typing lessons. And I was very happy to find a website that would give me typing lessons in the source code of languages that I use regularly. And if you give them $5 a month, they’ll let you upload your own projects to practice typing on. And the fun bit is at the end, is they’ll give you a breakdown of which fingers make the most mistakes, what keys you have the hardest time with, how likely you are to make, there’s a word for it. But when you make a mistake and then you keep typing, oh collateral errors is what they call it. When you’ve made a mistake but you keep typing, that stacks a multiplier on your errors. And so, it lets you know that, “Hey, you screw up and then you type 10 more words, that’s a habit you want to get out of,” if you’re going to do the perfect practice kind of thing that Katrina’s taught us how to do years ago, or months ago. So, that’s my pick, is typing.io. And if you want a keyboard that will absolutely be indispensable and yet make you hate it, and yet make you unwilling to leave it behind, ErgoDox is just freaking amazing.
CHUCK: So, what do you mean by an open source keyboard?
DAVID: Okay, so the keyboard that I am using, the schematics for the circuit board are freely available online. All of the keys and key switches, all of the electronic components, they give you Digi-Key part numbers that you can just go order all of the parts for it. And then you can solder it all up together. You get a teensy USB controller and solder it to the board. And then they give you the source code to the firmware to turn that into a keyboard controller. And at the end of the day, you plug it into your computer and the teensy device says, “Hi. I’m a keyboard.” And the computer says, “Oh hello, keyboard.” And you can now type. And it’s a keyboard that comes in two pieces. There’s no spacebar. It’s like you’ve got a thumb cluster under each thumb and keys under each finger. And yeah, by open source, what I mean is the entire thing is reprogrammable and all of the hardware is freely available and readily available. There’s nothing custom on it. So, I have reprogrammed the firmware on it to change the key layout for myself. Also, I broke it. Actually, it came to me missing a diode. And I went to the schematics and found the diode that was missing and I soldered a new one on. So, 99% of the people listening to this are just horrified by this.
DAVID: But that 1% of you who are going, “That sounds so freaking cool,” you need an ErgoDox keyboard. Massdrop.com. If nobody’s picked that, that’s my surprise third pick. Massdrop.com. They will, every three months or so, they will build and assemble these keyboards and send them out to people. And they will do it for a lot cheaper than you can buy all the parts yourself for, because they wait until they’ve got a hundred people ready to buy the keyboard. And then they go to Digi-Key and they say, “Hey, give us bulk discount pricing on this.” And so, I didn’t have to etch my own circuit boards or anything like that. They had circuit boards professionally printed. And so, it looks like…
JAMES: You wimp. [Laughs]
DAVID: Oh yeah, you know.
CHUCK: I was going to say, do you have to 3D print your own case and stuff?
DAVID: Close. [Laughs] They give you image files that you can take to a shop that does plastic cutting. And you basically say, “Give me just regular thin acrylic. Give me five layers of it so that it stacks up to be half an inch thick.” And in each layer, there’s a different image, cross-section of the keyboard for what goes on and what it holds together with.
JAMES: This pick has been a disturbing trip into David Brady’s mind.
DAVID: Yes, yes.
CHUCK: What’s said is I kind of want one.
JAMES: I know, right? He showed it to me. I’m not this type of person, but he showed it to me over Skype one day and I’m like, “Alright, that’s cool.” [Chuckles]
CHUCK: Alright. Well, I’ve got a couple of picks if I can remember what they are after that. The first one, I’ve been listening to, everybody knows I love audio books at this point. The last book that I read was ‘Stand and Deliver’ which is actually a Dale Carnegie Training for speaking. And it was excellent. I really, really enjoyed it. So, I’ll put a link to that in the show notes. My wife recommended a book to me as well. It’s called Divergent. They’re making a movie out of it. Here, within the next or so it comes out, I think. And it was an alright book. It wasn’t the best book. It’s a dystopian future book. But it was alright. And then I kind of enjoyed it. So, I’ll go ahead and pick that one as well. And then I’ve also taken to start cooking dinner for my family. And typically what it means is I dump a bunch of crap into a crockpot and then serve it up at the end of the day. And AllRecipes.com has been a terrific resource for that. So, I’m going to pick that as well. And I was going to pick ‘Designing Hypermedia APIs’, but I think James beat me to that.
CHUCK: So, I’ll skip that. And Michele, what are your picks?
MICHELE: So, my picks are much more development focused. So, I already mentioned Postman. That was going to be one of my picks but we already talked about it. And then my other main pick is this thing called RAML. It’s a RESTful API Modeling Language. So, it basically lets you go through and have a YAML file that has the definitions of your API. That also uses JSON schema to actually basically match your payloads. And it’s something that has been around for a couple of months now. And there’s good tooling that’s starting to be built on top of it. So, you could have a continuous integration server that when someone pushes to the release branch, will run a suite of tests to make sure your API doesn’t change, which is really useful because it will change. And then I have an iOS one, which is if anyone out there in Ruby Rogues land is also doing iOS, there’s this lovely book I’ve been going through on Auto Layout, which was introduced in iOS 6. It’s a new kind of way of thinking about layouts. And it’s all relative and all this fun stuff. And I’ve been going through Erica Sadun’s ‘iOS Auto Layout Demystified’, which has been an amazing introduction to a different way of thinking about laying out your views. So, that is it for me.
CHUCK: Yeah, that’s awesome. We talked to Jonas Budelmann about the Masonry Pod, which provides DSL over the top of auto layout. So, if you’re interested in that, you can go listen to that on the iPhreaks Show. So, our next book club book is ‘Object Design: Roles, Responsibilities, and Collaborations’, Rebecca Wirfs-Brock and Alan McKean. So, if you haven’t picked that up yet, go grab it and start reading it. And we’ll be talking about it here in a few months. Alright, well thanks for coming Michele.
MICHELE: Thanks for having me. This was really fun.
CHUCK: It was a great discussion.
JAMES: Yeah, thank you.
CHUCK: And really appreciate your expertise and taking the time.
[A special thanks to Honeybadger.io for sponsoring Ruby Rogues. They do exception monitoring, uptime, and performance metrics that are an active part of the Ruby community.]