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

Sansan Androidアプリ開発におけるマルチモジュール化の進め方 / Approaches to multi-module development in Sansan Android app

Sansan
January 13, 2022

Sansan Androidアプリ開発におけるマルチモジュール化の進め方 / Approaches to multi-module development in Sansan Android app

■イベント
iOS/Androidアプリ開発のマルチモジュール化【アンドパッド|クックパッド|Sansan】
https://sansan.connpass.com/event/232503/

■登壇概要

タイトル:Sansan Androidアプリ開発におけるマルチモジュール化の進め方

登壇者:技術本部 Mobile Applicationグループ Androidエンジニア 赤城 史哉

▼Sansan Engineering
https://jp.corp-sansan.com/engineering/

Sansan

January 13, 2022
Tweet

More Decks by Sansan

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

  3. 2

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  16. :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による依存性の解決を行う

    View Slide

  17. :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は画面・機能に切り分け

    View Slide

  18. :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

    View Slide

  19. :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

    View Slide

  20. :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レイヤーを参照していたり、
    その他のモジュールも存在していて複雑。こちらは基本的なコンセプト。
    このコンセプトにそう実態になるよう、日々改修している。

    View Slide

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

    View Slide

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

    View Slide

  23. STEP1 : domainのみを分離
    22
    :app

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  28. 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

    View Slide

  29. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. View Slide