Slide 1

Slide 1 text

Sansan Androidアプリ開発における マルチモジュール化の進め方 i O S / A n d r o i d ア プ リ 開 発 の マ ル チ モ ジ ュ ー ル 化 【 ア ン ド パ ッ ド | ク ッ ク パ ッ ド | S a n s a n 】 Sansan株式会社 技術本部 Mobile Applicationグループ 赤城 史哉

Slide 2

Slide 2 text

前職ではAndroidアプリの受託開発に従事。 2019年にSansan入社後、Sansan Android アプリの開発・運用を担当。 赤城 史哉 Sansan 株式会社 技術本部 Mobile Applicationグループ 1

Slide 3

Slide 3 text

2

Slide 4

Slide 4 text

Sansan株式会社とは 名刺管理から、営業を強くする 名刺でつながる、 ビジネスのためのSNS 請求書受領から、 月次決算を加速する 設立年 2007年6月 拠点 表参道本社 Sansan One Sansan パラシオ 関西支店 福岡支店 名古屋支店 資本金 63億33百万円 (2021年8月31日時点) 代表者 寺田親弘(代表取締役社長) 事業 働き方を変えるDXサービス (クラウド名刺管理サービス等)の 企画・開発・販売 グループ会社 Sansan Global Pte. Ltd. (シンガポール) Sansan Corporation (アメリカ) ログミー株式会社 東京証券取引所市場第一部 上場証券取引所 従業員数 979名(2021年8月31日時点) 3

Slide 5

Slide 5 text

Sansan – 働き方を変えるDX – 4 新世代エントリーフォーム 新世代パンフレット 全文書き起こしメディア 名寄せエンジン Sansan Data Hub ピアボーナスサービス 契約書データ化サービス クラウド請求書受領サービス スマート受付 無人名刺受付システム 名刺作成サービス セミナー管理システム クラウド名刺管理サービス スマート署名取り込み AI名刺管理 オンライン名刺 同僚コラボレーション メール配信 イベント・セミナー 請求書 名刺 契約書 組織コミュニケーション 名刺印刷・発注 データ活用 反社チェックオプション powered by Refinitiv/KYCC 契約管理オプション for クラウドサイン 商談管理オプション for Salesforce アンケートオプション powered by CREATIVE SURVEY powered by MotionBoard 名刺分析オプション 業務連携

Slide 6

Slide 6 text

本発表のゴール - マルチモジュール導入の具体的な事例を知る - 各々の開発現場での技術的な意思決定の材料とする 5

Slide 7

Slide 7 text

Agenda - Sansan Androidアプリのマルチモジュール化の現状 - マルチモジュール化の計画 - マルチモジュール化で困ったこと - 様々な規模の開発現場におけるマルチモジュール化との向き合い方 6

Slide 8

Slide 8 text

Sansan Androidアプリの マルチモジュール化の現状

Slide 9

Slide 9 text

- 名刺管理 - スマホのカメラを使って名刺登録 - 登録した名刺に関連する企業のニュースを確認 - 商談メモや議事録 (コンタクト機能) - 社内チャット - 企業情報の閲覧 - 同僚一覧を閲覧 アプリの主な機能 8

Slide 10

Slide 10 text

- ファイル数 - Kotlin : 約3000ファイル - Xml : 約1000ファイル - コード行数(Kotlin) - Kotlin : 約16万行 - Xml : 約5万行 - モジュール数:80モジュール - エンジニア数:7名 - アーキテクチャ:Flux + Clean Architecture Sansanアプリ開発の現状 9

Slide 11

Slide 11 text

すごく便利!!! おかげで、快適な開発が出来ている。 Gradleさんありがとう!!!! マルチモジュール化の恩恵(1エンジニアの感想)

Slide 12

Slide 12 text

- 開発の大規模化 - 複数人での並列的な機能開発による諸問題 > コンフリクトの増加 > アーキテクチャのルールが守られなくなる懸念 - コードの肥大化による諸問題 > ビルド時間の増加 > コードの読みづらさ > 改修・調査するファイルの見つけづらさ アプリ開発における課題 11

Slide 13

Slide 13 text

- ビルド時間の短縮 - レイヤー間の依存関係の強制 - 各モジュールの関心事を小さくできる - packageではクラスのグルーピングしか出来ないが、レイアウトファイルや resource等も含めたグルーピングが可能 マルチモジュール化のメリット 12

Slide 14

Slide 14 text

- 差分ビルドの時間が約半分に - legacyを触るときはまだ遅い - string.xmlやlayoutファイル、Android Manifest等の情報が 機能単位に集約され、見やすい - ノイズが少なく、担当している機能に集中できる - internal修飾子による、モノリスより柔軟な可視性の制御 - モジュール追加のタイミングで、アーキテクチャのレイヤーが 守られる事を担保 マルチモジュール化の恩恵 13

Slide 15

Slide 15 text

Sansanアプリ開発の現状:マルチモジュールの構造 14 :app :legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common

Slide 16

Slide 16 text

:legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common Sansanアプリ開発の現状:マルチモジュールの構造 15 :app 全てのモジュールに依存 Daggerによる依存性の解決を行う

Slide 17

Slide 17 text

:app :legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common Sansanアプリ開発の現状:マルチモジュールの構造 16 :legacy :feature:bizcard :feature :company :feature :company_common Presentationレイヤー Activity, Flux etc… Featureは画面・機能に切り分け

Slide 18

Slide 18 text

:legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common :app Sansanアプリ開発の現状:マルチモジュールの構造 17 Domainレイヤー その他各featureモジュール が共通して使うクラス :repository :resources :xx_util :router :domain

Slide 19

Slide 19 text

:legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common :app Sansanアプリ開発の現状:マルチモジュールの構造 18 Dataレイヤー SharedPreference, Retrofit など を取り扱う実装 Presentationレイヤーから 直接依存されない :data:repository_impl :data:local :data:network

Slide 20

Slide 20 text

:legacy :repository :data:repository_impl :data:local :data:network :resources :xx_util :router :domain :feature:bizcard :feature :company :feature :company_common :app Sansanアプリ開発の現状:マルチモジュールの構造 19 実態は、featureがdataレイヤーを参照していたり、 その他のモジュールも存在していて複雑。こちらは基本的なコンセプト。 このコンセプトにそう実態になるよう、日々改修している。

Slide 21

Slide 21 text

マルチモジュール化の計画と実行

Slide 22

Slide 22 text

- STEP 1 : domainのみを分離 - STEP 2 : data関連のモジュールを分離 - STEP 3 : UI関連のコードをlegacyに移動 - STEP 4 : Repository, Routerのinterfaceを切る - STEP 5 : UIのコードを機能ごとに分割 マルチモジュール化の5ステップ 21

Slide 23

Slide 23 text

STEP1 : domainのみを分離 22 :app

Slide 24

Slide 24 text

STEP1 : domainのみを分離 23 :resources :xx_util :domain :app

Slide 25

Slide 25 text

STEP2 : data関連のモジュールを分離 :app :data:local :data:network :resources :xx_util :domain 24

Slide 26

Slide 26 text

STEP3 : UI関連のコードをlegacyに移動 :app :legacy 25 :data:local :data:network :resources :xx_util :domain

Slide 27

Slide 27 text

STEP4 : Repository, Routerのinterfaceを切る :app :legacy 26 :data:local :data:network :resources :xx_util :domain :router :repository :data:repository_impl

Slide 28

Slide 28 text

STEP5 : UIのコードを機能ごとに分割 :app :legacy 27 :data:local :data:network :resources :xx_util :domain :router :repository :data:repository_impl :feature :bizcard_common :feature :company :feature:bizcard

Slide 29

Slide 29 text

STEP5 : UIのコードを機能ごとに分割(完成形) :app 28 :data:local :data:network :resources :xx_util :domain :router :repository :data:repository_impl :feature :company_common :feature :company :feature:bizcard :feature:piyo :feature:hoge :feature:fuga

Slide 30

Slide 30 text

マルチモジュール化で困ったこと

Slide 31

Slide 31 text

- モジュール化の認識をチームで合わせる必要性 - 共通化されたクラスを使いたい時、循環依存を回避するのが難しい - 意図せずデグレしてしまう事がある 困ったことのカテゴリ 30

Slide 32

Slide 32 text

- モジュールの切り方が分からない - 作成方法のドキュメントを用意しておく - モジュールの切る粒度 - 都度議論して方向修正していく - 新規開発でのモジュールの切り方、モジュール名の付け方 - 開発時に、詳細設計レビューを実施している。 その際にモジュール設計もレビューする モジュール化の認識をチームで合わせる必要性 31

Slide 33

Slide 33 text

循環依存を考慮した設計をする必要がある 会社詳細画面のモジュールに、新しく名刺の一覧画面を作ることになり 既存の名刺レイアウトを流用したい場合 32 :feature:会社詳細 (new) 会社に紐づく名刺一覧画面 :feature:名刺詳細 名刺レイアウト.xml

Slide 34

Slide 34 text

循環依存を考慮した設計をする必要がある 会社詳細画面のモジュールに、新しく名刺の一覧画面を作ることになり 既存の名刺レイアウトを流用したい場合 33 :feature:会社詳細 (new) 会社に紐づく名刺一覧画面 :feature:名刺詳細 名刺レイアウト.xml implementation project(”:feature:名刺詳細”)

Slide 35

Slide 35 text

循環依存を考慮した設計をする必要がある 名刺詳細でも、会社詳細に依存したいケースが出てきてしまうと… 34 :feature:会社詳細 (new) 会社に紐づく名刺一覧画面 :feature:名刺詳細 名刺レイアウト.xml implementation project(”:feature:会社詳細”) implementation project(”:feature:名刺詳細”)

Slide 36

Slide 36 text

循環依存を考慮した設計をする必要がある 35 名刺詳細でも、会社詳細に依存したいケースが出てきてしまうと… :feature:会社詳細 (new) 会社に紐づく名刺一覧画面 :feature:名刺詳細 名刺レイアウト.xml implementation project(”:feature:会社詳細”) implementation project(”:feature:名刺詳細”) コンパイルエラーになってしまう

Slide 37

Slide 37 text

循環依存を考慮した設計をする必要がある Sansan Androidでは、feature_commonモジュールを作り解決 36 :feature:名刺_common 名刺レイアウト.xml :feature:会社詳細 (new) 会社に紐づく名刺一覧画面 :feature:名刺詳細

Slide 38

Slide 38 text

- シングルモジュールのアプリではコンパイルできた依存関係でも、 マルチモジュールに移行するとエラーになってしまう - 注意しながら依存関係を設計しないと、すぐに複雑なモジュール間の 依存関係が作り出されてしまい、負債となる 循環依存を考慮した設計をする必要がある 37

Slide 39

Slide 39 text

意図せずデグレしてしまう事がある :feature:名刺詳細 :feature:会社詳細 strings.xml strings.xml 38

Slide 40

Slide 40 text

意図せずデグレしてしまう事がある 39 :feature:名刺詳細 :feature:会社詳細 strings.xml strings.xml string.xmlなどのresource idがコンフリクトすると、 片方のresourceが上書きされてしまう

Slide 41

Slide 41 text

意図せずデグレしてしまう事がある 40 :feature:名刺詳細 :feature:会社詳細 strings.xml strings.xml マルチモジュール環境では、resource id はユニークにする必要がある

Slide 42

Slide 42 text

意図せずデグレしてしまう事がある resource prefix機能を使うと、そのモジュールの中のresource id にprefixを 設定できる。 41

Slide 43

Slide 43 text

様々な規模の開発現場における マルチモジュール化との向き合い方

Slide 44

Slide 44 text

- 今までのセクションは、あくまでSansan Androidアプリ固有の話 - 様々な開発現場のシチュエーションを想像して、マルチモジュール機能を どのように使うか、考えてみましょう! - Twitterで #ANDPAD_cookpad_Sansan タグをつけて @ginyolith_tech の アカウントでツイートするので、同じくタグを付けて、お題に対する回答 を引用リツイートお願いします! - 経験豊富な方は初心者時代の自分と同じような人を助ける気持ちで、 マルチモジュール初心者の方は自分で考えるトレーニングとして、 ぜひツイートしてください! このセクションについて 43

Slide 45

Slide 45 text

- エンジニアの人数:1人(あなた) - アプリ開発のアイデアがあり、これから作っていく 技術選定のフェーズ - とにかく早くリリースをして欲しいという社長からの要望 開発現場1 創業したてベンチャー企業で1人エンジニア 44

Slide 46

Slide 46 text

- マルチモジュール化には向き合わなくて良い - とにかくリソースが無いことが想像できる - マルチモジュール化は詰まりどころが多い - コードベースが小さいのであれば、ビルド速度は問題にならない - 余裕があれば、packageでの最低限のレイヤー分けが出来ていると良い - ViewModel, Repository等 - 補足: 初心者の場合は、他の技術(coroutineやcompose等)を優先して学習すべき 開発現場1 自分の考え 45

Slide 47

Slide 47 text

- エンジニアの人数:2~3人(あなた + 中堅エンジニア2, 3人) - 半年程度でアプリを完成させ納品する契約 - 要件やデザインは決まっており、これから技術選定する段階 - 納期には多少余裕がありそう - 納品した後は大きなアップデートの予定は無い バグ修正程度の依頼がちょくちょく来る想定 開発現場2 中規模な受託開発案件 46

Slide 48

Slide 48 text

- レイヤー分けレベルのマルチモジュール化はした方が良い - 納期間際でのバグ修正や仕様変更に対応したい - アーキテクチャをある程度守らないとバグになりやすい規模感 - 機能単位のモジュール化は余裕があればしてもよさそう - コンパイルが通らなくなったり、循環依存の問題が出やすいので注意 開発現場2 自分の考え 47

Slide 49

Slide 49 text

- エンジニアの人数:4人(あなた + ベテラン、中堅、ジュニア各1) - 技術的負債が大きく、新機能の開発に工数がかかるのを解消したい - コードベースが大きくなっており、ビルド時間がかかるのがストレス - 最近はアーキテクチャを導入してきれいなコードになっているが、 一部の昔のコードはFat Activityなどつらいコードが存在する - 定期的に新機能の開発を行っている - アーキテクチャやライブラリなどを刷新する計画が立っている。 その技術選定を考えるフェーズ 開発現場3 中規模な事業会社でのリアーキテクチャ 48

Slide 50

Slide 50 text

- 計画的にマルチモジュール化に向き合ったほうが良い - アーキテクチャを考え直すのとセットで向き合うと良い - モノリス -> モジュール化は工数が結構かかるので注意 - featureモジュールも作ったほうが良い - 機能開発と並行してモジュール化をする場合 - ビルド速度に関しては、即時の対応としてマシンスペックを上げるのも手 > M1Macだと大分変わる 開発現場3 自分の考え 49

Slide 51

Slide 51 text

まとめ - マルチモジュール機能は大規模な開発現場における協力な味方 - 一方で、もちろん銀の弾丸ではない メリットデメリットを正しく検討して導入しよう - 巨大なモノリスからのモジュール化は計画をきちんと建てて行うと良い 50

Slide 52

Slide 52 text

エンジニア情報サイト「Sansan Engineering」 51 ・Sansanエンジニアのミッション ・プロダクト、テクノロジー概要 ・エンジニアインタビュー ・技術スタック ・働く環境、社内制度 ・募集職種 ・Blog ・イベント情報 ... and more Sansan Engineering Sansanのプロダクトやテクノロジー、カルチャー、採用情報など、エンジニアリングに関するあらゆる情報を掲載 https://jp.corp-sansan.com/engineering/

Slide 53

Slide 53 text

※ 登録の際、紹介コードの欄に「0 1 1 2 勉強会」と入力ください。

Slide 54

Slide 54 text

No content