Uber May 15, 2022

Managing Deep Scope Hierarchies in Large Codebases

Article Summary

Uber rewrote their Android rider app in 2016 and made an architectural choice that most Android teams avoid: deeply nested dependency injection scopes.

This article from Uber Engineering explains why their old two-layer scope architecture couldn't scale and how they built a deep scope hierarchy to support hundreds of cities with varying features. They ultimately created RIBs, their own architectural framework, when existing options fell short.

Key Takeaways

Critical Insight

Deep scope hierarchies solved Uber's scaling problems by eliminating coupling between features and removing stale state through short-lived, well-encapsulated scopes.

The article reveals why three-layer scope hierarchies still fail and includes specific code examples of their Dagger implementation.

About This Article

Problem

Uber's old rider app packed multiple screens into a single LoggedInActivity. This forced engineers to write large classes with fragile state logic, managing dozens of controllers and utility classes across hundreds of cities.

Solution

Brian Attwell's team added intermediate scope layers like PreRequest scope where needed. This let the new app's controller hierarchy match its scope hierarchy one-to-one, without forcing sibling scopes to share objects.

Impact

Engineers could now build features independently in Home, Product Selection, Airport, and Location Refinement without worrying about breaking existing features. The state combinatorics problem that came with the two-level architecture went away.