Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS Conf SG - 2022 - Dependency Injection at scale

iOS Conf SG - 2022 - Dependency Injection at scale

Building a feature in an app consisting of 95+ modules is complicated and leads to dependency management hell. Splitting a module into a public interface and a separate implementation framework for the interface allows to create simpler deps management and improve build times.

https://www.youtube.com/watch?v=a1KvjxNVEq8&list=PLED4k3CZkY9R9mhRW5V74gS9cVTp28CbK

Maciej Piotrowski

January 21, 2022
Tweet

More Decks by Maciej Piotrowski

Other Decks in Technology

Transcript

  1. 9+ years iOS development Mobile Core Team @ allegro “I

    make devs’ lives easier” Maciej Piotrowski
  2. 20 million customers each month one of top ten most

    visited e-commerce sites worldwide mobile apps big chunk of traf fi c the most popular product search engine in Poland
  3. OVERVIEW: Steve provides you a convenient way to solve daily

    👨💻 development problems and complete repetitive tasks. USAGE: steve <subcommand> OPTIONS: --version Shows the version -h, --help Shows help information SUBCOMMANDS: fixme Fixes most common issues that developers encounter generate Allows to generate modules for Allegro app bazel Use this command to invoke Bazel with parameters focus Allows to focus on selected modules from Allegro workspace test Runs tests for the given project and scheme Media: https://www.macrumors.com/2011/10/05/steve-jobs-has-passed-away OVERVIEW: Steve provides you a convenient way to solve daily 👨💻 development problems and complete repetitive tasks. USAGE: steve <subcommand> OPTIONS: --version Shows the version -h, --help Shows help information SUBCOMMANDS: fixme Fixes most common issues that developers encounter generate Allows to generate modules for Allegro app bazel Use this command to invoke Bazel with parameters focus Allows to focus on selected modules from Allegro workspace test Runs tests for the given project and scheme
  4. January 2021 78 modules 77 standard modules 1 utility module

    January 2022 91 standard modules 26 utility modules 117 modules
  5. how to inject dependencies to ? 117 modules NetworkClient .shared

    Core Cart ItemPage Payments SearchEngine Lists … Address OLD import Networking import Networking import Networking import Networking import Networking import Networking import Networking
  6. Cart ItemPage Payments SearchEngine Lists … Address Networking 
 Interface

    Networking NEW import NetworkingInterface import NetworkingInterface import NetworkingInterface import NetworkingInterface import NetworkingInterface import NetworkingInterface how to inject dependencies to ? 117 modules
  7. January 2022 91 private modules 91 public modules 26 utility

    modules January 2021 78 modules 77 standard modules 1 utility module 208 modules
  8. The Build of iOS Conf SG 2021: Speeding up the

    build process of a monolithic application 208 modules
  9. Cart ItemPage Payments SearchEngine Lists … Address Networking 
 Interface

    Networking ./steve focus Networking NEW Networking 
 Interface
  10. Cart 
 Interface ItemPage 
 Interface Payments 
 Interface SearchEngine

    
 Interface Lists 
 Interface … Address 
 Interface Cart ItemPage Payments SearchEngine Lists … Address NEW
  11. Cart 
 Interface ItemPage 
 Interface Payments 
 Interface SearchEngine

    
 Interface Lists 
 Interface … Address 
 Interface Cart ItemPage Payments SearchEngine Lists … Address NEW
  12. Cart 
 Interface ItemPage 
 Interface Payments 
 Interface SearchEngine

    
 Interface Lists 
 Interface … Address 
 Interface Networking 
 Interface Networking Cart ItemPage Payments SearchEngine Lists … Address NEW
  13. import Networking func injectProductPageDependencies() { let container = ProductPage.DependencyContainer.default container.apiClient

    = Networking.NetworkClient.shared // … } OLD // Module: Core Media: https://giphy.com/gifs/cbs-indianajones-harrisonford-raidersofthelostark-TGogvP0s0QESHmyYi9
  14. import NetworkingInterface class ModuleConfiguration: ModuleConfiguring { func registerImplementations(in registry: Registry)

    { registry.register(type: NetworkingClient.self, service: NetworkClient()) // Module: Networking NEW
  15. import NetworkingInterface class ModuleConfiguration: ModuleConfiguring { func registerImplementations(in registry: Registry)

    { registry.register(type: NetworkingClient.self, service: NetworkClient()) } // Module: Networking NEW Media: https://giphy.com/gifs/cbs-indianajones-harrisonford-raidersofthelostark-TGogvP0s0QESHmyYi9
  16. import NetworkingInterface class ModuleConfiguration: ModuleConfiguring { func resolveDependencies(with resolver: Resolver)

    { guard let networking = resolver.resolve(type: NetworkingClient.self) // Module: ProductPage NEW
  17. import NetworkingInterface class ModuleConfiguration: ModuleConfiguring { func resolveDependencies(with resolver: Resolver)

    { guard let networking = resolver.resolve(type: NetworkingClient.self) } } // Module: ProductPage NEW Media: https://giphy.com/gifs/cbs-indianajones-harrisonford-raidersofthelostark-TGogvP0s0QESHmyYi9
  18. let container: Registry & Resolver = // … modules.forEach {

    $0.registerImplementations(in: container) } modules.forEach { $0.resolveDependencies(with: container) } // Module: Application NEW
  19. // Module: DependencyInjection NEW class DependencyContainer: Registry, Resolver { func

    register<T>(type: T.Type, service: Any) { dependencies[DependencyKey(type)] = service
  20. // Module: DependencyInjection NEW class DependencyContainer: Registry, Resolver { func

    register<T>(type: T.Type, service: Any) { dependencies[DependencyKey(type)] = service } }
  21. // Module: DependencyInjection NEW class DependencyContainer: Registry, Resolver { }

    func resolve<T>(type: T.Type) -> T? { return dependencies[DependencyKey(type)] as? T }
  22. NEW // Summary: New Dependency Injection at scale private public

    Cart 
 Interface ItemPage 
 Interface Payments 
 Interface SearchEngine 
 Interface Lists 
 Interface … Address 
 Interface Cart ItemPage Payments SearchEngine Lists … Address Media: https://www.macrumors.com/2011/10/05/steve-jobs-has-passed-away
  23. NEW // Summary: New Dependency Injection at scale private public

    Media: https://giphy.com/gifs/cbs-indianajones-harrisonford-raidersofthelostark-TGogvP0s0QESHmyYi9 func application(_:, didFinishLaunchingWithOptions:) -> Bool { modules.forEach { $0.registerImplementations(in: container) } modules.forEach { $0.resolveDependencies(with: container) } }
  24. • lighter workspace • light dependency injection framework • intermodule

    dependencies on public interfaces • private modules inject implementations of interfaces • module extracts what it needs from the dependencies container // Summary: New Dependency Injection at scale Media: https://giphy.com/gifs/cbs-indianajones-harrisonford-raidersofthelostark-TGogvP0s0QESHmyYi9
  25. allegro.tech Speeding up iOS builds with Bazel Speeding up warm

    builds in Xcode Maciej Piotrowski twitter.com/macpiotrowski89 swifting.io