Efficient ViewController Transitions

Anyone familiar with RTR’s app knows that there are several different viewControllers that the user is able to navigate between; however, anyone not familiar with the code would most likely assume this navigation is done through simply pushing the relevant viewController via the navigation controller or by presenting the viewController modally (ex below).

Prior to joining the team, I would have made the same assumption. This assumption is wrong! You are probably now asking yourself “what other way is there to navigate between viewControllers?” Good question!

To handle efficient routing, we implemented a unique pattern to navigate between viewControllers. All of the data on the app’s viewControllers are populated by modelControllers. With that in mind, when a viewController is instantiated, the viewController’s initialization requires a modelController as a parameter. You don’t have to do it this way, but for reasons related to a whole different (future) blog post, we gather all the relevant information from the network at an earlier stage and persist this information throughout the app’s lifecycle.

After having created the viewController and established which modelController the viewController “owns,” it is time to create the route that will link to this viewController. RTR’s app has an entire class (AppRouter) dedicated to routing. One thing to note: we use JLRoutes, a cocoa pod that manages routes for URL schemes, to handle routing within the app. The main function we are concerned with inside AppRouter is adding a new route, which is a function provided by JLRoutes.

As you can see from the code above, addRoute requires a path as a parameter. We store all paths required for routing in a class, RTRURL. The enum Route (below) is the path to the specific viewController and the enum Param (also below) holds the paths to any parameters required to instantiate the viewController. In this example, case Experiment is the path to experimentsMC, which is the modelController that is required to initialize RoutingVC.

Great! We now have a way of routing the app to a given viewController based on the viewController’s path provided in the addRoute func. So…how do we present it?

We made a class, Presentation, that subclasses from RTRURL. This means that Presentation has access to all of the properties held in RTRURL. Yes, the code inside Presentation could be done inside RTRURL. However, we made this Presentation class as a way of abstracting implementation details to make the code easier to read. 👏

In order to “tie together” all of the components that contribute to navigating to a given viewController (aka creating a new route and providing the viewController’s route path), we decided to create a “route struct” for every viewController. Specifically, this struct encapsulates all of the information required to instantiate the viewController. It does this by adopting and conforming to the PresentationProtocol.

PresentationProtocol has three requirements: a path, required parameters and valid parameters. What does this mean, exactly? With this particular example, RoutingVC can’t be instantiated without an experimentsMC; therefore, this property must be provided in the RequiredParams. Similarly, a new route can’t be added without a path, thus, a path must be provided.

ValidParams takes in properties that can be displayed by the viewController but aren’t required in order to instantiate the viewController. ValidParams is encapsulated within the PresentationProtocol but can be an empty array. An example of ValidParams could be the way in which the viewController is presented. Is it pushed? Is it modal? You choose!

Screen Shot 2017-03-24 at 10.27.49 AM.png

FINALLY we are ready to show the viewController. The params property includes the required experimentsMC parameter as well as presentationStyle, which is a valid (but not required) parameter. These parameters are passed through to the Experiment “routes struct” held on the Presentation class.

After creating an instance of the “routes struct” (in this example, Experiment), we are now ready to actually present the viewController. openViewConrollerWithPresentation() takes in a conforming type of PresentationProtocol as a parameter. After establishing the path, parameters and URL, routeURL is called. Using JLRoutes, routeURL presents the viewController associated with that url.

This may seem like a complicated solution for a “simple” transition between viewControllers. So, why did we decide to do it this way? For two key reasons:

  1. By creating a route for each viewController, integrating deep linking with universal links is much simpler. The url path already exists!
  2. When testing new features on the app, it is much more efficient to link directly to the viewController that contains the feature in question rather than navigating throughout the app to finally get to the relevant viewController.

The next time you use RTR’s app, you now have a “behind the scenes” understanding of what’s happening when you navigate between viewControllers. Thoughts? Comments? Please don’t hesitate to reach out to us!

iOS Data Binding is Better with Signals

Here at Rent the Runway, we want to make sure that all of our users have a responsive and rewarding iOS mobile app experience. With our backend architected to use many highly performant microservices, there is a whole lot of data and user interactions to keep in sync. We have services for user memberships, promotions, products, search categories, user hearts, and so much more. Without a one-to-one mapping of API service calls to application views, it was critical that we come up with a robust and coordinated approach for data binding and content updates.

One of the main iOS communication patterns is delegation. Delegation creates a one-to-one messaging structure between two objects, where one object can act on behalf of another. Using this pattern, it is typical that a completed API call would inform its delegate object that new data exists and is ready for processing and/or display somewhere else in the app.

On this diagram we can see that we have several UIViewControllers (ProductCollectionsVC, ProductsGridVC, ProductVC) that hold a ModelController (HeartsMC), which is responsible to fetch all the hearts from a user. 
While this approach is useful in many situations, it makes it difficult for communicating data updates from one object to many objects at the same time as we can see on the diagram.
As an alternative to delegates, we can use ReactiveCocoa’s framework to use signals for communication. In short ReactiveCocoa is a functional reactive programming framework which represents dataflows by the notion of events. An event is just a concept that represents that something happened, which could represent a button being tapped or the status of a network call being made. ReactiveCocoa uses Signals and SignalProducers to send messages representing these events.  A Signal will only notify an observing object of events that have occurred after the observer has started observing, not any past actions. On the other hand, a SignalProducer allows you to start observing for an event but also have the visibility for past and future events.

ReactiveCocoa explains these concepts by comparing them to a person (the observer) watching television (the signal or signal producer). 

[A signal] is like a live TV feed — you can observe and react to the content, but you cannot have a side effect on the live feed or the TV station. [A signal producer] is like a on-demand streaming service — even though the episode is streamed like a live TV feed, you can choose what you watch, when to start watching and when to interrupt it.
— https://github.com/ReactiveCocoa/ReactiveSwift

Signals work very well for UI events like tapping a button, where an observer would only be interested in reacting to touch events after it has started observing. A Signal Producer would be more useful for a network request, where its on-demand nature would help provide more contextual information about a network request, such as allowing an observer to know if it is in progress, has it previously failed, should we cancel it, etc.

Objects throughout our app can then observe these event-driven signals and take any action they need to bind data to views, process data, or trigger any other actions. This allows multiple views and viewControllers in our app to be notified of data changes at the same time without the need for complex delegation chains. 

In the code snippet above, we are setting up signals for a modelController. When it receives a signal, it can call a method that is defined by our protocol. If we were to configure these methods and interactions with a delegate, other ViewControllers would not receive any message and would not know to update their data.

In the app, we have a TabBarController that allows users to quickly switch between viewControllers that provide different functionality. However, we do have some shared data sources between these controllers, so our signals allow us to update data on every accessible viewController so the user can interact with them immediately after switching tabs.

This approach has been very helpful for broadcasting changes of the datasource on a ModelController throughout the app. While implementing, we paid special attention to weak/strong references with our observers to prevent retain cycles, routinely testing that objects were being deallocated when needed. Additionally, deadlocks can occasionally occur if signals trigger other signals that are dependent on the completion of another signal. However, with well thought out protocols and implementation patterns, we have been able to provide a responsive and stable app experience for our users.

Refactoring Sass with Lists and Maps

At Rent the Runway, we have an internal tool to easily create emails for our customers. It’s a Rails/React system that turns .erb template files into SailThru-compatible layouts (SailThru is our software for sending customer emails).

In this repo we use Sass utility classes. If you’re unfamiliar with utility classes, they’re usually classes that contain a single CSS rule, like so:

.left { text-align: left; }

They’re useful for highly descriptive markup – in our case, creating inline styles for emails. For example, to align your text left in an email, you would use the above class like so:

<td class=”left”> Here is some left-aligned text. </td>

See this post on CSS tricks for a great summary of why inline design is commonly used for emails. Using utility classes allows us to more easily match inline styles to particular email elements.

However, creating stylesheets for utility classes can get messy. We quickly ended up having a number of stylesheet partial files that contained quite repetitive CSS blocks:

The padding partial had almost 200 lines of definitions like that! We had similar problems for heading definitions and background colors:

I could go on, but you get the idea – not very DRY and awkward to add to. What do you do if you quickly need another padding utility class? Just add it onto the end, and worry about duplication later. These stylesheets were getting unruly, unreadable, and impossible to maintain. It seemed like a great opportunity to refactor using two cool Sass features: lists and maps.

First up, we refactored the padding partial to use lists – similar to arrays in other languages. The padding classes were mixed up and mostly named after the padding pixel value specified (e.g. .padding-left-25px). However, a couple used comparative suffixes – e.g. padding-left-max. Our first job was to standardize all the classes to use pixel values in their class names. It’s easier to understand `.padding-left-25px` than `.padding-left-max`.

Next, we grouped all the classes by rules: whether they specified one particular padding (e.g. padding-left), two sides (e.g. top and bottom) or all padding.

Already it was easy to see that there were a couple of duplicate rules. Those could be deleted. The next step was to turn the necessary values into a list. Lists in Sass are incredibly easy to create: just take all values and separate them with commas:

$padding-left-values: 5px, 10px, 20px, 30px, 50px, 70px;

Then, we could use the @each function of Sass to loop through all the pixel values. Using interpolation with #{} , we could name the class appropriately and give the padding value:

@each $px in $padding-left-values {
  .padding-left-#{$px} {
    padding-left: $px;

This produces all the classes I need without having to type them all out manually. Also, it makes the process of adding a new padding class far easier: just add the px value to the list.

The next challenge was to refactor the heading sizes. Again, there were a number of repeated classes detailing the various header sizes. However, this time they were named based on relative sizes (e.g. small, medium, large) rather than the absolute pixel value that was found in the style rule.

This called for a map – similar to objects in JavaScript or hashes in Ruby. The heading sizes map had keys that corresponded with the name, and values that corresponded with the pixel size of the text:

$heading-sizes: (
  smallest: 25px,
  small: 36px,
  medium: 40px,
  large: 80px,
  largest: 110px

As with lists, you can loop over a map using the @each function. As we’re using both the key and the value, you define both of those first.

@each $size, $px in $heading-sizes {
  .heading-#{$size} {
    @include times($px);

Notice here that we’re already using a mixin – times() – that sets an appropriate font family, size, and calculates a line-height based on the font-size passed in.

We did a similar thing with colors, using a color map to loop through and create utility classes for background colors:

$colors: (
  // Primary copy
  midnight: #272c32,
  cotton: #fff,
  // Accent
  tan: #cd9365,
  fawn: #c79176,
  tangerine: #e85940,
  error: #eb5840,

// Background colors file

@each $color, $hex in $colors {
  .#{$color}-bg {
    background-color: $hex;

Both of these compile to CSS similar to our bloated Sass stylesheets from before. However, it’s much easier to add, remove, or check for duplicate colors or header sizes in this system. Let’s say a new seasonal color needed to be added – rather than having to write out the whole class definition, just add the name and hex value to the colors map.

What’s more, it always feels so satisfying making a commit with more deletions than additions, don’t you think?

Evolving Our Style Guide to Better Unite Designers and Developers

Exactly two years ago Jess Brown wrote Bridging the Design-Development Divide. Her post summed up Rent the Runway’s efforts to create consistent styling, and then translate that styling into Sass variables and classes for easy reuse. This ultimately was embodied in a style guide that lived in GitHub Pages and was publicly accessible.

Jess Brown’s GitHub Pages style guide

Jess Brown’s GitHub Pages style guide

The style guide that Jess created greatly aided in developer-designer relations by ensuring designer mockups were consistent with the colors and Sass stylings powering the site. However, because it was separate from our site and we were rapidly evolving our brand identity, the GitHub Pages style guide quickly fell behind our storefront stylings. There was nothing forcing the guide to be kept up-to-date.

Since Jess’ creation of the first robust style guide for RtR, the company underwent a rebrand as well as a shift towards using React. This created a new opportunity for a more dynamic system of presenting, maintaining, and using our styles. React allows for the creation of reusable components of varying scales such as a button, product card, or even carousel of products. Components can be nested and reused for various purposes, allowing for flexible building blocks to be created for pages. By taking the elements of the styleguide and translating them into React components, we are able to ensure consistent stylings across the site’s elements.

In tandem with the translation of site elements into components, we moved the style guide into the same code base as the storefront. This means that the style guide is powered by the same Sass files that power the site’s front end. Change the font on a button in the style guide and it is instantly reflected site-wide!

The new React component based style guide.

The new React component based style guide.

We then categorize these components for easy discoverability according to Brad Frost’s Atomic Design principles. This means that small components such as buttons, links, etc. are labeled as “atoms.” Collections of atoms are categorized as molecules and so on. If you are interested in creating an atomic design style guide for your own use, checkout patternlab.io. It provides templates for creating style guides that are organized by atomic design principles and served as an inspiration for Rent the Runway’s guide.

So this all sounds great, but one of the biggest challenges is getting cross team collaboration and buy-in to ensure that the living style guide becomes an effective manner of generating consistent styles and fast paced development. For the engineering team, I presented to the Architecture Review Board (ARB) for the introduction of a new grid system in tandem with the style guide. At RtR, we use "ARBs" to screen changes to the way we work, such as using new libraries, or accepting new naming conventions. The ARB for the guide was accepted and the new grid and stylings are being used on Rent the Runway’s pages today. For the product and creative teams, I created Sketch and Photoshop templates of the elements and grid system for use by PMs and Designers, ensuring that the designs the engineering team receives can be built by the frameworks and components in the style guide. In theory, this combined toolkit means every design being passed from a UX designer to a front end engineer can be built by laying out React components from the style guide using the new grid system which in turn greatly reduces repetition of code and speeds up development times.

We will continue to advocate the use of this guide for cataloging, onboarding, and accessibility purposes. By centralizing our styles onto the same Sass codebase, we hope to ensure seamless translation of UX/UI designs into pages.

And one last thing: The new React Styleguide is publicly accessible right on renttherunway.com!

Tech Stack

Lately, RTR's engineering team has been doing a lot of recruiting and when we do anything we like to iterate, iterate, iterate to improve our process. We recently realized that candidates could benefit from a clear, concise picture of our tech stack. So here is that clear (always-work-in-progress) picture!

An image for sharing!

Some things to note:

  1. The groups of boxes correspond with typical engineering roles/responsibilities at RTR.
  2. Developers often think of "full stack" as JavaScript/HTML/CSS UI code on the client side plus Ruby (or Python or PHP or Node) on the server side. In our case, our use of Ruby is a bit atypical. We don't touch the database with Ruby. It's just a thin layer for templating/routing/sessions between JavaScript in the browser and Java REST services on the back end. In terms of engineering roles, Ruby tends to fall on the "frontend" side for us vs. our Java "backend".
  3. Additionally, we don't use Rails. Rather we have a home-grown setup built on Sinatra that we affectionately call Ruby on Rocks. :)
  4. We build a lot of stuff. Our main website, our retail point-of-sales system, the software that runs our fulfillment center, our iOS app, internal tools for customer service. They pretty much all fall into one of the two columns (JS or iOS) shown here.
  5. We have lots of Java services powering all this. Something like 43 Dropwizard microservices at last count. (Pricing, Reservations, Commerce, Membership, Referrals, Recos, Reviews...)
  6. We have some other odds and ends. Some Scala for instance. Some Redis. This picture shows our most common, widely vetted technologies.

And one last important thing: we're hiring!!!