image Gilt says “dzień dobry” to Natalia Barthol, who recently joined our engineering in team in Dublin, Ireland! Natalia is a passionate software engineer and open source contributor who will work on continuous delivery at Gilt. Originally from Poland, she moved to Dublin nearly four years ago and has been getting used to Irish weather ever since. “I eventually fell in love with the taste of Guinness and even started to appreciate windy weather and the cold sea, as I recently took kite-surfing lessons,” she says. “I also enjoy rock-climbing, skiing and… shopping.
Discovering Gilt brings about both fascinating technological challenges and a fashion thrill :-)”

Welcome, Natalia!

image

Gilt recently released Mockingbird Toolbox, an open-source project for iOS intended to make common development tasks easier. The Toolbox is the basic building block of Mockingbird library, which will be released in stages over the coming months. Mockingbird serves as the base layer of Gilt’s award-winning iPhone and iPad applications.

This post is the first in a series that will be highlighting the code available in Mockingbird Toolbox and explaining how you can use it in your iOS projects.

Modularity

Modularity in software design is a key strategy for managing complexity. A well-crafted code module is:

  • Focused — it tries to do one main thing; anything else it does is in support of that
  • Isolated — it reduces interconnections within code by providing a public API that minimizes the points of contact between modules
  • Well-behaved — it doesn’t change global state in a way that interferes with other modules

When separate modules need to interact with a shared resource, modularity becomes more difficult to attain.

In order to be well-behaved, modules need to use shared resources in a way that recognizes the fact that other modules may be using that resource, too.

One way to try to account for that might be to introduce a mechanism for modules to communicate with each other to ensure proper behavior with respect to the shared resource. But doing so would make the modules less focused and isolated.

Gilt’s mobile team faced these sorts of design decisions during the evolution of our iOS apps. One generic solution we built was the MBServiceManager class, which we’ll discuss further in a future post.

But there was one specific shared resource that required its own solution: namely, the network indicator that appears in the status bar.

The Status Bar Network Indicator

The network indicator is the animated spinner that you sometimes see in the status bar, typically to the right of the other network information in the upper-left corner of the device screen.

The spinner doesn’t appear automatically; instead, applications are responsible for turning it on when they’re using the network, and turning it back off once they’re done. Displaying the network indicator is entirely optional, but polite applications are honest about when they’re consuming the user’s bandwidth.

Applications control the spinner through the UIApplication’s networkActivityIndicatorVisible property. Setting the value to YES causes the animated spinner to appear. Setting the property back to NO hides the spinner.

You might think that managing the network indicator is as simple as setting networkActivityIndicatorVisible to YES when an operation starts and back to NO when it finishes, but consider what happens when an app sends multiple network requests:

  1. Network operation A starts
  2. Network operation B starts
  3. Network operation B completes
  4. Network operation C starts
  5. Network operation A completes
  6. Network operation C completes

Under this scenario, the spinner should be animating from Step 1 through Step 6.

But that’s not what happens if we directly manipulate the networkActivityIndicatorVisible property at the start and end of each request. Instead, we get this behavior:

  1. Spinner appears
  2. Spinner animating
  3. Spinner disappears
  4. Spinner appears
  5. Spinner disappears
  6. Spinner remains hidden

Half the time, the network indicator is reflecting the wrong state.

Because the beginning and end of different network operations can be interleaved, the fact that there is only a single on/off value for the network indicator becomes problematic. If more than one set of code attempts to directly manipulate the value of networkActivityIndicatorVisible, we will get unexpected results.

Network Indicator Coordination

To avoid this problem, we decided upon creating a coordinator for the network indicator. The coordinator provides a simple interface for reporting when operations begin and end. Wherever network operations are performed, our code interacts with the coordinator, which in turn decides when to show and hide the spinner based on what’s happening across the entire application at any given moment.

The coordinator was designed to:

  • Maintain a count of in-progress network operations
    • Whenever an operation starts, the count would increment
    • Whenever one completes, the count would decrement
  • Set networkActivityIndicatorVisible property to YES whenever the count increases from 0 to 1

  • Set networkActivityIndicatorVisible property to NO whenever the count decreases from 1 to 0

  • Operate correctly in a multi-threaded environment

Introducing MBNetworkIndicator

The public interface to our coordinator is provided by the MBNetworkIndicator class, part of the Mockingbird Toolbox open-source project.

Any code that issues network requests can maintain one or more MBNetworkIndicator objects. Each instance is intended to represent one or more related network operations occurring on a single thread. While those operations are in progress, the MBNetworkIndicator instance is kept around, and is notified when operations begin and end.

The API consists of three instance methods:

  • operationStarted — Called whenever a network operation begins
  • operationFinished — Called whenever a network operation completes
  • cancelOperations — Called to signal that all in-progress operations associated with that specific instance should be considered finished (equivalent to calling operationFinished once for each in-progress operation)

Implementation

Every MBNetworkIndicator instance maintains a counter of network operations that is incremented for each call to its operationStarted method and decremented for each call to its operationFinished method.

Calls to those methods also update a master counter, which keeps a single, application-wide count of in-progress operations.

You can think of it this way:

  • The count maintained by any given MBNetworkIndicator instance is equal to (the number of times its operationStarted method was called) minus (the number of times its operationFinished method was called)

  • The master count is equal to (the number of times operationStarted was called on all MBNetworkIndicator instances) minus (the number of times operationFinished was called on all MBNetworkIndicator instances)

Whenever the master count of network operations is greater than zero, the status bar network indicator is displayed. Otherwise, when there are no operations, the indicator is hidden.

Canceling Operations

Let’s say you have a UINavigationController-based app, and any given UIViewController pushed onto the navigation stack could result in multiple network requests being issued. Further, you handle the user tapping the Back button by hooking into viewWillDisappear: to cancel any network operations that haven’t yet finished.

In such a case, you might opt to have each UIViewController maintain its own MBNetworkIndicator instance. You would call operationStarted and operationFinished as requests are processed normally. But within viewWillDisappear:, you would call cancelOperations to signal that all pending operations for that view controller have been cancelled.

Calling cancelOperations is equivalent to calling operationFinished once for each pending operation.

Maintaining References

To ensure that the master counter balances over time, MBNetworkIndicator assumes that when an instance is deallocated, it is a signal that there are no related network operations still pending. (This is achieved by a call to cancelOperations from within dealloc.)

Because of this, you are expected to maintain strong references to MBNetworkIndicator instances that are still tracking pending operations.

Thread Safety

Because individual network operations are bound to specific threads, MBNetworkIndicator instances are designed to be used only on a single thread; instances must not be shared across threads.

However, the underlying mechanism that maintains the master counter and manages showing and hiding the network activity indicator is thread-safe.

The mechanism uses functions declared in <libkern/OSAtomic.h> to ensure that the master counter is handled correctly when several MBNetworkIndicator instances are in simultaneous use on multiple threads.

What’s Next

Our MBNetworkIndicator class is just one way to manage a shared resource while adhering to the principles of modularity.

In subsequent posts, we’ll discuss:

Sitepoint has just published the third installment of Gilt Email Engineer Lauren Ribando’s informative “best practice email design series.” This time around, Lauren gives us tips on coding practices—from avoiding CSS shorthand to slicing images. Go here to read her full article.

image

Terve, aloha, and nǐ hǎo are just a few ways the #gilttech and #giltpmo teams would like to welcome Mackenzie Nicholson, the newest business systems manager to join our Program Management Organization! This global citizen was born in Napa Valley, grew up in Hawaii, went to high school in Seattle, attended college in Chicago and New York, and spent a year living in Helsinki running her own American-style baked goods company while commuting to London and Hong Kong for the engineering consultancy Systra. (She’s already given us a presentation on making the best of travel reward programs!)

Fittingly, Mackenzie is currently working with our back office team, which works on Gilt’s international payments and logistics. We’re thrilled to have her. Welcome on board, Mackenzie!

image

Earlier this summer our friends at Sauce Labs released Appium 1.0, which the Gilt Mobile team has been using to automate our mobile testing efforts. Not long after its release, Gilt Senior Software Engineer Matt Isaacs wrote a blog post for for Sauce Labs highlighting Appium’s advantages and where it still falls a bit short. Yesterday (August 20) Matt joined representatives from Sharecare, Softcrylic and other Appium-using companies at Sauce Labs’ all-day Appium Roadshow at Projective Space in the Lower East Side. 

For all of you who couldn’t make it to yesterday’s sold-out event, here are Matt’s slides:

image

Last month Gilt CIO crossed the Hudson River to present a talk for the NJ Tech Meetup, the largest tech community in the Garden State. Steve’s talk focused on creating emotional connections with customers, and how Gilt constantly innovates to strengthen and maintain those connections. NJ Tech Weekly was there, and have just published an article on Steve’s presentation! Go here to check it out.

As an added bonus, here’s the deck from Steve’s talk:


By day, Senior Software Engineer Yoshi Sugawara works on Gilt’s Personalization team. By night—or at least tonight—he presents on Swift! As the featured speaker of the Organization for the Understanding of Dynamic Languages’ August meetup, Yoshi will deliver a Swift primer and answer questions. Regular readers of this blog are likely to expect meetups we announce here to take place either in NYC, Dublin (Ireland, not Ohio) or (to a lesser extent) Portland (Oregon, not Maine), but tonight’s (Aug. 20) meetup takes place at the Manoa Innovation Center in Honolulu, Hawaii. RSVP here.

By Gilt Director of Mobile Product Christopher Gonzalez

Gilt Japan has released a brand-new version of our iPhone app—and the updates are significant! It’s been extremely rewarding to see so many people—and Apple—embrace our work and share positive feedback with us. If you haven’t already, please download the app now to check it out! (If you’re outside Japan, you might need to switch your store to see the app—the new version is only available in the Japan App Store.)

Let’s take a stroll down memory lane by looking at some screenshots of the old Gilt iPhone app. A sales page from the women’s category used to look like this:

image

A brand page, like this:

image

And a product page used to look like this:

image

With this being our first update in three years, there was much that we wanted to change about the old Gilt app. Some of our top priorities:

  • To provide support for iPhone 5 screens. Notice the constraining letterboxing in the old design—the content is just straining to be set free!

  • Enlarge the images. We invest a lot of time and creative energy into our photography, and we wanted our Japan customers to be able to enjoy them fully!

  • Introduce a lighter palette. The old Gilt branding was heavy on the black and gold, and quite dark.  

  • Create a single checkout experience across all devices and offer a consistent experience for our users. We also wanted to develop a platform that was easier to maintain.

Now, let’s reveal our gorgeous new app! Let’s start with the sales page. So light, airy and visually arresting:

image

Here’s an individual sale page:

image

And here’s a product page—so bright and cheerful:

image

Besides brighter backgrounds, what’s new about the new Gilt app?:

  • Support for iPhone 5 screens. The elbow room feels good!

  • The branding and design now incorporates the conventions of iOS 7. Check out those edge-to-edge images and transparencies!

  • Bigger images to highlight our amazing photography

  • Full account support. Whether you want to update your shipping and payment information or start a return, you can now manage your full Gilt Japan account on the go

  • A great zoom view so that you can see every detail of an item

  • More than 40 very detailed sizing charts to ensure a precise fit

  • Maps featured with all Gilt City offers

In making these changes, we wanted to provide users with features that would inspire confidence in their purchases, and also make the Gilt Japan shopping experience even more simple and delightful than before. Our team built the app as a smart native/webview hybrid app: The full shopping experience is native, and checkout and account pages are responsive webpages loaded in the app. This strategy allows the app to share the same checkout experience as our mobile web and (eventually) full desktop site. Our platform is now more efficient, and making updates or rolling out new features will be a much faster process for us going forward.

Thanks, Apple!

Not only have our customers embraced the new Gilt app, but Apple has also supported it with some major promotional love—giving it a prominent position on the App Store homescreen as the top “best new app,” and helping to expose our work and the Gilt brand to so many new users:

image

As well as here:

image

And lastly:

image

What do you think about our new app? Share your feedback with us by emailing productfeedback@gilt.com!

New York City’s Atlassian User Group is celebrating their one-year anniversary with a (undoubtedly well-organized!) big party for the project and program management set, and we’re proud to say that Gilt Tech is going to be a part of the festivities! Gilt Senior Director, PMO Heather Fleming will present “Beyond the Crystal Ball: The Agile PMO” in advance of her appearance in September (along with Gilt Director of Program Management Justin Riservato) at the Atlassian Summit. Representatives from Venmo, Vector Media Group, Goldman Sachs, and NYU Langone Medical Center will also give talks on JIRA, HipChat and PM-related topics. The fun starts at 7 PM at SNAP Interactive; go here to register.