Slide 1

Slide 1 text

Micro Modular Architecture with Bazel Ryo Aoyama iOSDC Japan 2020

Slide 2

Slide 2 text

Ryo Aoyama Mercari Software Engineer Architect iOS Tech Lead @ra1028 @ra1028fe5

Slide 3

Slide 3 text

Agenda • Drawbacks of Monolith • Micro Modular Architecture • What is Bazel? • The power of Bazel with micro modules

Slide 4

Slide 4 text

Drawbacks of Monolith

Slide 5

Slide 5 text

Disclaimer: Monolithic application is NOT an absolute bad thing.

Slide 6

Slide 6 text

FeatureA FeatureB FeatureC FeatureD FeatureZ … Networking DesignSystem Analytics Database Architecture etc… Entity Monolithic Application All features are concentrated in one or a few modules.

Slide 7

Slide 7 text

Monolithic Application Build time increases as the product grows: Build time can increase linearly or exponentially.

Slide 8

Slide 8 text

Coupling complexity between features: Monolithic Application Coupling complexity between features gradually increases and there is no going back.

Slide 9

Slide 9 text

Barriers to evolutionary potential: Monolithic Application The introduction of new technology affects the entire app and is pretty costly. And also, it does not have the ability to evolve progressively.

Slide 10

Slide 10 text

So we need to tackle more advanced architecture.

Slide 11

Slide 11 text

Micro Modular Architecture

Slide 12

Slide 12 text

Micro Modular Architecture Our coined term showing a highly modularized application structure. =

Slide 13

Slide 13 text

The idea is to split our application into hundreds of smaller modules.

Slide 14

Slide 14 text

Concepts One module has only one screen (aka view controller). All the layers needed for the screen are also in the same module. • Module by feature

Slide 15

Slide 15 text

Concepts The screens do not depend on each other and work independently. • Independent between features

Slide 16

Slide 16 text

Concepts Create one module for just one functionality. Larger functionalities consist of a composition of these smaller modules. • Fine-grained shared functionality modules

Slide 17

Slide 17 text

Monolith Application Feature Feature Feature Feature Feature Common Common Common Common Concepts

Slide 18

Slide 18 text

Looks great, but will the modules depend on each other complexly?

Slide 19

Slide 19 text

Modularization Group Applications Features Libraries Domain Grouping modules to give order to the way they depend on each other.

Slide 20

Slide 20 text

Application Feature Feature Feature Feature Feature Common Common Common Common Modularization Group The modules in this group contain an App Delegate, and that's it. It might also contain DI to feature modules. Applications

Slide 21

Slide 21 text

Application Feature Feature Feature Feature Feature Common Common Common Common Modularization Group Features Each vertical feature module is independent and can only depend on modules in the Domain and Libraries groups.

Slide 22

Slide 22 text

Application Feature Feature Feature Feature Feature Common Common Common Common Modularization Group Domain (Library) Contains modules of functionality shared by several feature modules. It also allows modules to have service-specific information.

Slide 23

Slide 23 text

Application Feature Feature Feature Feature Feature Common Common Common Common Modularization Group Libraries Contains modules of generalized functionality. It cannot have service-specific information.

Slide 24

Slide 24 text

Modularization Group Applications Features Libraries Domain Grouping modules and make them unidirectional dependencies. Circular dependency Complexity

Slide 25

Slide 25 text

Next, let's stop into Bazel for more advanced micro modular architecture.

Slide 26

Slide 26 text

What is Bazel?

Slide 27

Slide 27 text

Bazel • Fast + Reliable + Scalable + Extensible • Multiple language support • Starlark language for build scripts • Remote Caching • Open Source https://github.com/bazelbuild/bazel

Slide 28

Slide 28 text

Example of Benefits My product completes clean build, unit test, and land to testers in around 1m 30s in the shortest. But it's still too early stage for a sample.

Slide 29

Slide 29 text

Example of Benefits Pinterest https://medium.com/pinterest-engineering/developing-fast-reliable-ios-builds-at-pinterest-part-one-cb1810407b92 Local Build: CI Build: Beta Distribution: Build Success Rate: 4m 38s -> 3m 38s, 21% improved 10m 24s -> 7m 34s, 27% improved 14m 32s -> 7m 52s, 45% improved 80% -> 97%-100%

Slide 30

Slide 30 text

Tokopedia Example of Benefits https://medium.com/tokopedia-engineering/how-tokopedia-achieved-1000-faster-ios-build-time-7664b2d8ae5 Local Clean Build: 56m 31s -> 4m 56s, 91% improved

Slide 31

Slide 31 text

LINE Example of Benefits https://engineering.linecorp.com/en/blog/improving-build-performance-line-ios-bazel Minimum: Maximum: Average: 28m 24s -> 4m 24s, 85% improved 35m 25s -> 26m 32s, 25% improved 30m 58s -> 14m 32s, 53% improved

Slide 32

Slide 32 text

Example of Benefits Amazingly, these improvements have been brought to each individual developer by remote caching.

Slide 33

Slide 33 text

Build Scripts WORKSPACE Defines external dependencies. BUILD Contains build scripts for 1~N modules. .bazelrc Configuration file for project-specific options. xxx.bzl Defines utility extension for build scripts which will be loaded from the BUILD.

Slide 34

Slide 34 text

Bazel for iOS rules_apple rules_swift apple_support https://github.com/bazelbuild/rules_apple https://github.com/bazelbuild/rules_swift https://github.com/bazelbuild/apple_support

Slide 35

Slide 35 text

Bazel for iOS for more complicated modules rules_apple_line https://github.com/line/rules_apple_line

Slide 36

Slide 36 text

How to build load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "build_bazel_rules_apple", sha256 = “….", url = “https://github.com/bazelbuild/rules_apple/releases/download/x.x.x/rules_apple.x.x.x.tar.gz”, ) load( "@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies", ) apple_rules_dependencies() load( "@build_bazel_rules_swift//swift:repositories.bzl", "swift_rules_dependencies", ) swift_rules_dependencies() load( "@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies", ) apple_support_dependencies() WORKSPACE

Slide 37

Slide 37 text

Library How to build load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") swift_library( name = "Sample", srcs = glob(["Sources/**/*.swift"]), data = glob(["Resources/**/*"]), visibility = ["//visibility:public"], ) BUILD

Slide 38

Slide 38 text

Test How to build load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test") swift_library( name = "TestLib", srcs = glob(["Tests/**/*.swift"]), ) ios_unit_test( name = "Test", deps = [":TestLib"], ) BUILD

Slide 39

Slide 39 text

Application How to build load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application") load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") swift_library( name = "AppLib", srcs = glob(["App/**/*.swift"]), ) ios_application( name = "App", app_icons = glob(["Assets.xcassets/AppIcon.appiconset/**"]), bundle_id = "com.example.app", families = [ "iphone", "ipad", ], infoplists = ["Info.plist"], launch_storyboard = "Launch.storyboard", minimum_os_version = "14.0", deps = [":AppLib"], ) BUILD

Slide 40

Slide 40 text

How to build $ bazel build //… Build all targets $ bazel build //package-name:target-name Build specified target

Slide 41

Slide 41 text

Carthage CocoaPods • pinterest/PodToBUILD • bazel-ios/cocoapods-bazel • with build scripts: swift_library, objc_library • with build scripts: apple_dynamic_framework_import Our Choice Third-party Library

Slide 42

Slide 42 text

Bazel + Xcode BUILD xcodeproj

Slide 43

Slide 43 text

Tulsi by Google https://github.com/bazelbuild/tulsi XCHammer by Pinterest https://github.com/pinterest/xchammer Bazel + Xcode

Slide 44

Slide 44 text

index-import by Lyft https://github.com/lyft/index-import Bazel + Xcode Replaces the paths in the index file created by Bazel so that it can be used for Xcode.

Slide 45

Slide 45 text

Downside • High adoption cost • High learning cost • iOS is not officially supported • Some Xcode features have been disabled

Slide 46

Slide 46 text

Downside Wrong setting will rather increase the build time.

Slide 47

Slide 47 text

Alternatives Buck by Facebook https://github.com/facebook/buck Gradle https://github.com/gradle/gradle

Slide 48

Slide 48 text

The power of Bazel with micro modules

Slide 49

Slide 49 text

Aggressive Caching Once a module is built, it won't be rebuilt until the code in that module is changed.

Slide 50

Slide 50 text

Aggressive Caching Caches are created per module. Micro modular architecture maximizes cache efficiency. =

Slide 51

Slide 51 text

Test Results Caching Bazel will not run already succeeded tests.

Slide 52

Slide 52 text

Test Results Caching That’s can be ignored by bazel test //… --nocache_test_results

Slide 53

Slide 53 text

Remote Caching Once it's built somewhere, all developers don't have to rebuild it. Build once, reuse everywhere:

Slide 54

Slide 54 text

Remote Caching Remote Cache Client CI Client Client Cache Cache Push

Slide 55

Slide 55 text

Remote Caching Caches can be minimized by bazel build //… ——remote_download_minimal

Slide 56

Slide 56 text

Remote Caching Now, all we need is ample network bandwidth instead of Mac Pro.

Slide 57

Slide 57 text

Static Linking Too many dynamic frameworks can have a negative impact on the launch speed of your app.

Slide 58

Slide 58 text

Static Linking Bazel compiles all modules into static libraries, so micro modules has no negative impacts.

Slide 59

Slide 59 text

Dependency Diagrams Bazel can track all dependency graphs and parse them with the bazel query command. It can be output as a graphical diagram with Graphviz.

Slide 60

Slide 60 text

Dependency Diagrams https://github.com/kastiglione/bazel-xcode-demo-swift-driver

Slide 61

Slide 61 text

Conclusion

Slide 62

Slide 62 text

• Micro Modular Architecture maximizes the synergy with Bazel, and vice versa. Conclusion • Build speed has room for improvement in software architecture as well as hardware performance. • Bazel will dramatically improve our developer experience.

Slide 63

Slide 63 text

References • Bazel Document • Faster Together: Uber Engineering’s iOS Monorepo • How Tokopedia Achieved 1000% Faster iOS Build Time • Improving Build Performance of LINE for iOS with Bazel • Developing fast & reliable iOS builds at Pinterest (Part one) • kastiglione/bazel-xcode-demo-swift-driver https://eng.uber.com/ios-monorepo https://engineering.linecorp.com/en/blog/improving-build-performance-line-ios-bazel https://medium.com/tokopedia-engineering/how-tokopedia-achieved-1000-faster-ios-build-time-7664b2d8ae5 https://medium.com/pinterest-engineering/developing-fast-reliable-ios-builds-at-pinterest-part-one-cb1810407b92 https://bazel.build https://github.com/kastiglione/bazel-xcode-demo-swift-driver

Slide 64

Slide 64 text

Thank you Ryo Aoyama iOSDC Japan 2020