Dependency Injection in iOS and Android Apps
As apps become large, it often makes sense to build parts of the application as reusable components or modules. For large companies, either with several apps or several mobile teams, reusing the code owned by another team becomes a no-brainer.
For example, a mobile platform team might own networking and shared architecture components. A Money team would build and own payments components — this was my team at Uber! — and a Maps team would own all things mapping-related. Components and modules in the app would often map to the structure of the company's teams, mirroring the observation known as Conway's law.
With multiple modules, modules need to have a way to define their dependencies, both at a module and a class level. This concept is dependency injection, a form of inversion of control. It is a simple, yet often underrated concept in mobile development and one that is far more commonplace with backend and web projects. Here is a Swift code sample and explanation of the concept.
A major challenge with dependency injection is the amount of work it takes to modify or update dependencies if you do not use a framework to solve this. Even without using a framework, the time-consuming nature of this is a trade-off for clearer abstractions and good testability.
Dependency injection is a powerful tool for maintaining testable code consistently across the codebase. With dependency injection, classes that have multiple dependencies can be unit-tested by passing mock dependency classes when instantiating them. Larger, modular apps tend to introduce this concept one way or the other.
Manual dependency injection — creating all interfaces, then hardcoding all dependencies — works fine when there are few such dependencies. However, as the number of components and the number of dependencies grow, maintaining and updating dependencies becomes more difficult. Spotting things such as circular dependencies also becomes tricky and using dependency injection frameworks begins to make more sense.
Android has a mature dependency injection framework that analyzes dependencies’ compile-time, called Dagger2. Google recently introduced Hilt on Dagger; a dependency framework built on top of Dagger, and Koin is becoming more popular with Kotlin.
On iOS, there have historically not been similar frameworks. At Uber, we built, used, and open-sourced Needle, based on similar concepts. We would have had trouble scaling the code with over a hundred engineers working on the same codebase without dependency injection. We used this tool to be explicit about all class dependencies, make unit testing easy — and non-negotiable for most of the code — and reuse components across teams.
This post is an excerpt from my book Building Mobile Apps at Scale: 39 Engineering Challenges. Get the book here as a free PDF, until 31 May.
Featured Pragmatic Engineer Jobs
- Engineering Leader - Card Platform at X1 Card. $250K+. Remote (US).
- Engineering Leader - Card Product at X1 Card. $250K+. Remote (US).
- Senior Android Engineer at Polarsteps. Amsterdam.
- Frontend Software Engineer at Enveritas. $130-150K. Remote (Global).
- Senior Software Engineer, Distributed Systems at Mixpanel. $200-270K + equity. New York, San Franciso, Seattle or Remote (US).
- Senior Software Engineer, Fullstack at Mixpanel. $200-270K + equity. New York, San Franciso, Seattle or Remote (US).
- Software Development Manager - eCommerce at Card Kingdom. $175-195K. Seattle, WA or Remote (US).
- Senior Frontend Engineer at Pento. £80-92K. Remote (Global).
- Senior Fullstack Engineer at Synthesia. £70-110K . Remote (Europe or US Eastern time) or onsite (London, Amsterdam, New York).
- Senior Backend Engineer at Synthesia. £70-110K . Remote (Europe or US Eastern time) or onsite (London, Amsterdam, New York).
- Senior Frontend Engineer at (catch) Health. $90-120K + equity. Remote (North America).
- Staff Backend Engineer at Pento. £95-115K. Remote (Global).
- Senior Full Stack Engineer (Laravel / Vue) at RXMG. Remote (Global).
- Sr. Cloud Infrastructure Support Engineer at RXMG. Remote (Global).
- Founding Engineer, Front End and API at Causal. $175-225K - equity. Boston.
- Senior Full Stack/Frontend Engineer at Vitally.io. $180-270K. New York or Remote (US).
- Senior Software Engineer - Core Platform at CAST.AI. €72-€96K. Remote (EU).
- Senior Software Engineer - Cost Optimization at CAST.AI. €72-€96K. Remote (EU).
- Solution Architect at CAST.AI. Remote (EU).
- Senior Software Engineer - Security at CAST.AI. Remote (EU).
- Solutions Engineer at Pigment. $70-120K. New York or Toronto.
The above jobs score at least 10/12 on The Pragmatic Engineer Test. Browse more senior engineer and engineering leadership roles with great engineering cultures, or add your own on The Pragmatic Engineer Job board and apply to join The Pragmatic Engineer Talent Collective.
Want to get interesting opportunities from vetted tech companies? Sign up to The Pragmatic Engineer Talent Collective and get sent great opportunities - similar to the ones below without any obligation. You can be public or anonymous, and I’ll be curating the list of companies and people.
Are you hiring senior+ engineers or engineering managers? Apply to join The Pragmatic Engineer Talent Collective to contact world-class senior and above engineers and engineering managers/directors. Get vetted drops twice a month, from software engineers - full-stack, backend, mobile, frontend, data, ML - and managers currently working at Big Tech, high-growth startups, and places with strong engineering cultures. Apply here.