Deep Dive

19 Aug 2014

We’re six days into final projects at Dev Bootcamp, and at the risk of jinxing it, I think things are going pretty well. That definitely doesn’t mean things are easy. After seven and a half weeks of Ruby-heavy web development, my team and I decided to make the leap into mobile with an iPhone app for CitiBike navigation. (See below for more details about the product.) Since last Wednesday, we’ve had the opportunity to work with a slough of unfamiliar technologies, from geolocation to XCode. One of the most exciting aspects of the project has been our immersion in Objective-C.

I hit my first major roadblock yesterday. One of the quirks of our project is that our “back end,” to the extent that we have one, is the station data provided by CitiBike. This includes bike stations addresses, latitude and longitude coordinates, number of bikes remaining, total number of bike docks at the location, etc. While CitiBike does make this data freely available to developers, they do not currently provide an API, so we get our information via a plain vanilla HTTP GET request to this URL, which is updated roughly once per minute. My task yesterday morning - after our MVP demo - was to optimize our app’s loading time by caching CitiBike’s response to our first HTTP request, so that we would not have to make the other two. (We did consider the fact that our cached data would technically be invalid after a minute. However, since our users are only likely to keep the app open for a few minutes at a time, we decided that the improvement in speed would be worth that risk.) An added twist to the problem was the fact that CitiBike’s HTTP response omits Cache-Control headers.

See the response to this curl request:

$ curl -i http://www.citibikenyc.com/stations/json
HTTP/1.1 200 OK
Date: Wed, 27 Aug 2014 02:19:37 GMT
Server: Apache/2.2.15 (Red Hat)
X-Powered-By: PHP/5.4.30
Set-Cookie: ci_csrf_token=0fa63e2d37ccd1bf99c205a6bc3644c2; path=/
Set-Cookie: ci_csrf_token=0fa63e2d37ccd1bf99c205a6bc3644c2; path=/
Set-Cookie: ci_csrf_token=ae1b2bdabc98e03f0553574cffe53270; path=/
Set-Cookie: ci_session=VWFTbABkCTMFfFUmUWtRYlc9AW1UIgZyUTcCdVUnA2xdYlVoDAIHOFBhBiEGbQBzU2sCMVVnU2sAeAdpAmdXZFYzUjcHMFQxAmpbalY0BmJVNFNnADYJPQUzVWJRZ1FkVzoBNlQ5BjZRMwI0VWIDZF07VWMMawdiUDUGIQZtAHNTawIzVWVTawB4BzgCJlcPVjRSMgdiVCACN1t7VnQGclU7UyUAagk4BTRVb1FzUWRXPAF5VDEGOVFhAihVZQM1XThVKAxrB2ZQJwY4BiUAOlNgAjJVb1NzAC8HIgIzVyJWClI3B2FUNwI8W3xWJQZrVXNTbABhCTgFPVV3UTJRJld%2FATtULwY2UXwCNVVkAytdPVUkDGYHIlA%2FBjIGZQA6U3MCblU0UyIALgcOAjdXM1YhUj8HcFQ7AiZbcVYlBmtVaVNsAGEJPQU3VWxRYFFjVzgBblQ3BjZRaQJ7; path=/; httponly
x-version: 1.0
Last-Modified: Wed, 27 Aug 2014 02:19:01 GMT
Vary: Accept-Encoding,User-Agent
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json

As a result, a feature that I thought would be solved with a relatively simple implementation of Objective-C’s basic NSURLCache necessitated a deep dive into a wide variety of approaches to caching in Objective-C.

My first idea was to simply ignore the absence of a Cache-Control header and work by the Last-Modified header instead. When that failed, I attempted to manipulate the incoming HTTP response to fake a Cache-Control header, using this blog post as a guide. That tactic didn’t fail, but it also didn’t solve my problem. I found that I was able to cache the incoming data fairly easily; a pair of NSLogs revealed an empty cache when the app launched, and occupied memory in the cache immediately after a successful HTTP request. Accessing the data later was more difficult, especially because at least three view controllers relied on its information. I considered a number of other solutions, including the use of a global variable (shudders!) and/or saving the data to disk. Finally, however, I settled on the simplest solution that occurred to me: an array set as a property of the App Delegate. This approach met the project’s needs and led me to learn about Objective C’s delegate protocol, which was a fascinating experience in and of itself.

This challenge was one of the most rewarding experiences I’ve had yet in coding. While perhaps not the most technically difficult issue I’ve encountered, it required more research and far more trial and error than most problems I’ve solved so far. It also helped me understand how critically important team dynamic is to the success or failure of a project. After a day of hacking away at this with very little success and even less sleep, I was frustrated and exahusted. I can’t imagine how frustrated I would have felt without my teammates’ suport - words of encouragement, offers to pair, and occasional reminders to step away from the computer. I’m incredibly lucky to be working with these people: all three of them are talented programmers, hard workers, reliable team members and truly kind people. I’m beginning to understand why Dev Bootcamp places so much emphasis on engineering empathy: I would love to have coworkers like these for the rest of my career, and I certainly intend to be one wherever I end up working.

Molly Huerster

Published on 19 Aug 2014 Find me on Twitter!

blog comments powered by Disqus