Successfully reported this slideshow.
Your SlideShare is downloading. ×

Preparing for Growth - Architecting Giant Apps for Scalability and Build Speed

Upcoming SlideShare
Buck outside Valley
Buck outside Valley
Loading in …3
×

Check these out next

1 of 38 Ad
1 of 38 Ad
Advertisement

More Related Content

Slideshows for you (19)

Advertisement

Preparing for Growth - Architecting Giant Apps for Scalability and Build Speed

  1. 1. Preparing For Growth 16.04.2021 1 Spotify Preparing for Growth Architecting Giant Apps for Scalability and Build Speed Bruno Rocha - iOS Engineer @ Spotify
  2. 2. 2 Preparing For Growth 16.04.2021 Spotify How does an iOS app evolve overtime?
  3. 3. Preparing For Growth 16.04.2021 3 Spotify "Level 1" app A monolith All Classes All Resources Features - Single module - MVC - Simple features - No testing - Direct navigation MyAppModule
  4. 4. Preparing For Growth 16.04.2021 4 Spotify "Level 2" app A larger (but better) monolith MyAppModule Feature1 Feature2 Feature3 Feature4 Feature5 Feature6 Feature7 Feature8 The app is now larger, but not large enough to be a big issue New Features - Usage of protocols and composition - A more testable architecture - Features are slightly more complex - Presence of unit testing - Navigation with injection
  5. 5. Preparing For Growth 16.04.2021 5 Spotify Feature Feature Feature Feature Feature Feature Feature Feature Feature Feature Feature Feature MyAppModule ⚠ Slow build times! Module cache invalidated!
  6. 6. Preparing For Growth 16.04.2021 6 Spotify Onboarding "Level 3" app A modularized app Home FeatureFlags NetworkSDK New Features - More modules means less cache misses - Compilation of modules individually - Better structure/division of concerns in general
  7. 7. Preparing For Growth 16.04.2021 7 Spotify Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module New... features? - ⚠ Slow build times! (...again?) - ⚠ Awful launch times - ⚠ Small changes are impossible - ⚠ Navigation changes are almost impossible - ⚠ Architectural changes are impossible - ⚠ Isolated development compiles half the app
  8. 8. Preparing For Growth 16.04.2021 8 Spotify Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Level 1 problems: Quantity of code Level 2 problems: Testability of code Level 3 problems: Structure/Isolation of code Level 4 problems: Module architecture
  9. 9. Preparing For Growth 16.04.2021 9 Spotify Dynamic Frameworks .dylibs loading in runtime might cause launch performance issues Each additional framework that your app loads adds to the launch time. Although dyld caches a lot of this work in a launch closure when the user installs the app, the size of the launch closure and the amount of work done after loading it still depend on the number and sizes of the libraries loaded. Linking Static Libraries instead can improve launch time Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module
  10. 10. Preparing For Growth 16.04.2021 10 Spotify Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module
  11. 11. Preparing For Growth 16.04.2021 11 Spotify Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module
  12. 12. Preparing For Growth 16.04.2021 12 Spotify Direct Dependencies Directly depending on concrete implementation modules makes cache invalidation more common and makes the app inflexible (harder to add new screens in the middle of the flow) Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module
  13. 13. Preparing For Growth 16.04.2021 13 Spotify Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module Module 👑 Minions, destroy this app.
  14. 14. Preparing For Growth 16.04.2021 14 Spotify Module Module Module Module Now: Horizontal Dependencies Module Module Previous:Vertical Dependencies Module Module
  15. 15. Preparing For Growth 16.04.2021 15 Spotify Module Module Module Module "Level 4" app Modules don’t depend on each other, navigation is dynamic Module Module Module Module Module Module Module Module UI
  16. 16. Preparing For Growth 16.04.2021 16 Spotify Classes / Structs Protocols Feature Feature Classes / Structs Protocols Feature2 ❔
  17. 17. Preparing For Growth 16.04.2021 17 Spotify Protocols FeatureAPI Classes/Structs Feature (Concrete) Protocols Feature2API Classes/Structs Feature2 (Concrete) Concrete modules shouldn’t depend on other concrete modules! API/Impl Module Pair Incremental build time issues may still exist when making changes directly in the API modules, but they are now a much rarer occurrence.
  18. 18. Preparing For Growth 16.04.2021 18 Spotify Protocols FeatureAPI Classes/Structs Feature (Concrete) Protocols Feature2API Classes/Structs Feature2 (Concrete) How to navigate to Feature2? Dependency Engine
  19. 19. Preparing For Growth 16.04.2021 19 Spotify Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI AppDelegateModule (.app) 🗒 ClassList 🗒 APIRequest ConcreteClass
  20. 20. Preparing For Growth 16.04.2021 20 Spotify SPTServiceSystem Manages a graph of SPTServices, working as a runtime dependency injector that handles the lifecycle of every Spotify feature. Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI Feature FeatureAPI MainModule (.app) 🗒 ClassList
  21. 21. Preparing For Growth 16.04.2021 21 Spotify Networking (Concrete) NetworkService: NetworkAPI AppDelegateModule (.app) (SPTServiceSystem) Hey! I have a service that implements "NetworkAPI". 👍 HomeModule Hey! Can you provide me the impl of "NetworkAPI"? 👍 
 (Inject "NetworkService")
  22. 22. Preparing For Growth 16.04.2021 22 Spotify Service Scopes A group of services, allowing fine-grained service access control. 1 2 3 4 LoggedInScope 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 LaunchScope CarPlayScope SiriScope HomeScope
  23. 23. Preparing For Growth 16.04.2021 23 Spotify final class SiriIntentsService: SPTService, SiriIntentsAPI { 
 



 } func load() { print(”SiriService loaded”) } func unload() { 
 print(”SiriService unloading”) } static let serviceIdentifier= SiriIntentsAPI.self @Dependencyvar connectivity: ConnectivityAPI @Dependencyvar keychain: KeychainAPI import ConnectivityFeatureAPI import KeychainFeatureAPI
  24. 24. Preparing For Growth 16.04.2021 24 Spotify features/siriintents/services.yaml - SiriIntentsService (SiriScope) - MyService (MyScope) - MyOtherService (MyScope) - MySuperSecretFeatureSerice (MyScope)
  25. 25. Preparing For Growth 16.04.2021 25 Spotify let serviceList = SPTServiceList() 
 let serviceOrchestrator = ServiceOrchestrator(services: serviceList) 1 2 3 4 5 6 7 8 Directed Acyclic Graph (DAG) [8, 7, 6, 4, 2, 5, 3, 1] Load/Notify Order Unload Order (Topologically Sorted)
  26. 26. Preparing For Growth 16.04.2021 26 Spotify let serviceList = SPTServiceList() 
 let serviceOrchestrator = ServiceOrchestrator(services: serviceList) 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 Not in memory Lazy reference injected Loaded in memory serviceOrchestrator.activate(scope: "LaunchScope") serviceOrchestrator.load(NavigationService.self, fromScope: "LaunchScope") serviceOrchestrator.load(CrashReporterService.self, fromScope: "LaunchScope")
  27. 27. Preparing For Growth 16.04.2021 27 Spotify serviceOrchestrator.deactivate(scope: ”CarPlayScope”) 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 LaunchScope LoggedInScope CarPlayScope 1 2 3 4 5 6 7 8
  28. 28. 28 Preparing For Growth 16.04.2021 Spotify Isolated Development 
 (Mini apps)
  29. 29. Preparing For Growth 16.04.2021 29 Spotify FeatureA FeatureAAPI FeatureBAPI FeatureB FeatureC FeatureCAPI FeatureD FeatureDAPI FakeFeatureB MyApp
  30. 30. Preparing For Growth 16.04.2021 30 Spotify FeatureA FeatureAAPI FeatureBAPI FakeFeatureB FeatureADemoApp
  31. 31. Preparing For Growth 16.04.2021 31 Spotify Mini Apps Horizontal dependencies allow the creation of minified example apps. Huge productivity boost! FeatureA FeatureAAPI FeatureBAPI FakeFeatureB FeatureADemoApp
  32. 32. 32 Preparing For Growth 16.04.2021 Spotify Dynamic Navigation
  33. 33. Preparing For Growth 16.04.2021 33 Spotify Module Module Module Module Dynamic Navigation Not having explicit dependencies mean we can go anywhere from anywhere Module Module Module Module Module Module Module Module UI
  34. 34. Preparing For Growth 16.04.2021 34 Spotify final class ProfilePage: SPTService, ProfilePageAPI { 
 


 } func load() { navigation.register(”page-profile”) { _ in 
 return ProfileViewController() 
 } } static let serviceIdentifier= ProfilePageAPI.self @Dependencyvar navigation: NavigationAPI import NavigationFeatureAPI
  35. 35. Preparing For Growth 16.04.2021 35 Spotify func navigateToProfile() { navigation.push(”page-profile”) }
  36. 36. Preparing For Growth 16.04.2021 36 Spotify Backend-Driven UI page-playlist?id=f8sn03k page-playlist?id=v92kalp page-charts page-new page-videos page-podcasts (HubsRenderer)
  37. 37. Preparing For Growth 16.04.2021 37 Spotify iOS App Evolution Amount of issues when evolving Level 1 Level 2 Level 3 Level 4 Level 5 No issues! Some issues. Some bigger issues. TONS of issues. ????
  38. 38. Preparing For Growth 16.04.2021 38 Spotify @rockbruno_

×