Slide 1

Slide 1 text

マルチモジュール懐疑派だったかつての自分に送る マルチモジュールの効能 モバイルアプリLT 会 一瀬喜弘(@mikanIchinose)

Slide 2

Slide 2 text

自己紹介 object Mikan { val name = " 一瀬喜弘" val company = "karabiner.tech" val work = Engineer.Android val hobby = listOf( " 漫画", " アニメ", " ゲーム", " 折り紙", "OSS 開発・コントリビュート", ) }

Slide 3

Slide 3 text

巷ではマルチモジュールが流行ってるっぽいけど なんであんな複雑そうな構成が流行るのか分からん

Slide 4

Slide 4 text

とかつて思っていた自分の疑問に答える形式で マルチモジュール構成の利点を解説

Slide 5

Slide 5 text

Q1 モジュールに分けて何が嬉しいの? Q2 モジュールを​ 分けると​ プロダクションコード以外の​ ファイルが​ 増えて、​ 管理コストが​ 増すのでは? Q3 開発スピードが落ちそう Q4 モジュールを上手に分けられる気がしない

Slide 6

Slide 6 text

Q1 モジュールに分けて何が嬉しいの?

Slide 7

Slide 7 text

1 依存の方向をビルド構成によって定義できる モノモジュール 何が何に依存しててもおかしくない

Slide 8

Slide 8 text

1 依存の方向をビルド構成によって定義できる マルチモジュール ビルド構成によって依存関係を厳密に規定できる feature-module はdata-module のコンポーネントを、domain-module はfeature- module のコンポーネントをインポートすることが不可能 // feature/build.gradle.kts implementation(project(":domain")) // domain/build.gradle.kts implementation(project(":data"))

Slide 9

Slide 9 text

2 関係ないコンポーネントが思考を遮らない モノモジュール . └── app └── src ├── data │ ├── AuthRepository.kt │ ├── AuthRepositoryImpl.kt │ ├── UserRepository.kt │ └── UserRepositoryImpl.kt ├── domain │ ├── GetUserUseCase.kt │ └── LoginUseCase.kt └── ui ├── LoginScreen.kt ├── LoginViewModel.kt ├── SplashScreen.kt └── SplashViewModel.kt

Slide 10

Slide 10 text

2 関係ないコンポーネントが思考を遮らない マルチモジュール . ├── app │ └── src │ └── MainActivity.kt ├── data-api │ └── src │ └── data │ ├── AuthRepository.kt │ └── UserRepository.kt ├── data-impl │ └── src │ └── data │ ├── AuthRepositoryImpl.kt │ └── UserRepositoryImpl.kt ├── domain │ └── src │ └── domain │ ├── GetUserUseCase.kt │ └── LoginUseCase.kt └── feature ├── login │ └── src │ └── feature │ └── login │ └── ui │ ├── LoginScreen.kt │ └── LoginViewModel.kt └── splash └── src └── feature └── splash └── ui ├── SplashScreen.kt └── SplashViewModel.kt

Slide 11

Slide 11 text

3 モジュールに分けられる構造 = 良い設計 モジュールとして切り離すことができるということは以下を達成しないといけないので自ずと良い設計になる 疎結合 共通パーツは共通なモジュール(shared, common, core) として切り出したくなる 機能間の依存がなくなるのでfeature-module 内の変更がモジュールで完結する 循環依存しない コンパイル不可能

Slide 12

Slide 12 text

モジュールを ​ 分けると ​ プロダクションコード以外の ​ ファイルが ​ 増えて、 ​ 管理コストが ​ 増すのでは?

Slide 13

Slide 13 text

マルチモジュールを触りだしたころはそう思っていた

Slide 14

Slide 14 text

1 新しくモジュールを作るという作業は面倒 new module したときにウィザードで正しい項目を入力できているだろうか Package name とか入力するの地味にめんどくさい あとから修正したくなったときにどこまで修正したら完了なのか分からん hoge/src/main/ hoge/fuga hoge/src/main/AndroidManifest.xml hoge/build.gradle(.kts) やること自体はそこまで多くないので割とすぐ習熟する ` `

Slide 15

Slide 15 text

ソースコード以外はほとんど変化することがないので 作ってしまえばほぼ終わり

Slide 16

Slide 16 text

2 ビルド設定の共通化という難所 gradle に対する習熟度が求めれる 手段が幾通りもありどれに手を出そうか迷う 共通構成を記載したgradle ファイルを作り、各build.gralde でapply する とくにキャッシュされるわけではないのでビルドタイムには貢献しない Convention Plugin 共通処理をプラグインとして定義する

Slide 17

Slide 17 text

2 ビルド設定の共通化という難所 Convention Plugin precompiled script plugin .gradle.kts ファイルで書く 依存やバージョンをKotlin ファイルで管理 → Version Catalog が主流になったので不要かも standalone gradle plugin .kt ファイルで書く せっかく依存をVersion Catalog で管理したのに文字列で指定しなくちゃいけなくなるので微妙な気持 ち 最新のサンプル実装(nowinandroid) はこちらを使用している more information https://star-zero.medium.com/gradle のconvention-plugins-ba19a1332540 https://speakerdeck.com/jmatsu/gradle-convention-plugins

Slide 18

Slide 18 text

Q3 開発スピードが落ちそう

Slide 19

Slide 19 text

コードを書くスピードは落ちることもある

Slide 20

Slide 20 text

しかし、それとこれとはスコープの違う話

Slide 21

Slide 21 text

マルチモジュールは設計の道具 設計する = 戦略的思考 コードを書く = 戦術的思考

Slide 22

Slide 22 text

Q4 モジュールを上手に分けられる気がしない

Slide 23

Slide 23 text

アーキテクチャとか ​ 設計系の ​ 技術書で ​ 勉強してください クリーンアーキテクチャ 単体テストの考え方/ 使い方 iOS アプリ設計パターン入門 ソフトウェアアーキテクチャの基礎 ー エンジニアリングに基づく体系的アプローチ ドメイン駆動設計

Slide 24

Slide 24 text

バックエンドや ​ フロントエンドの ​ トレンドも ​ 参考になる バックエンド モノリス モジュラーモノリス マイクロサービス フロントエンド コンポーネント指向 Atomic Design

Slide 25

Slide 25 text

まとめ Q1 モジュールに分けることの嬉しさ → 良い設計をこころがけるようになる Q2 管理コストの増大 → あまり変化しないのでコストにならない Q3 開発スピードの低下 → 頭の使い方が違うだけなので慣れれば低下しない Q4 モジュール分割難しい → アーキテクチャとか設計の勉強して