はじめに
こんにちは。iOSエンジニアの@nonoka-yamamotoです。
最近各社のiOSのマルチモジュール構成について調べていたので、比較してみました。
マルチモジュール化を考える上で、参考になれば嬉しいです。
主なマルチモジュール構成
全てのアプリにおいて、機能の縦割り横割りの考えを持っています。 アプリによって縦割りを重視した上で、横割りも取り入れていたり、その逆もあります。
縦割りのモジュール構成
- 機能毎に分割している
横割りのモジュール構成
- レイヤー毎に分割している
マルチモジュールはそれらを分割しやすくするもので、各社前提が異なるので、全く同じマルチモジュール構成は存在しません。 混合されていることを前提として、それぞれを重視してマルチモジュール化を行った企業の例をご紹介したいと思います!
縦割りメインのマルチモジュール構成
クックパッドの場合
縦割りのマルチモジュール構成を重視した企業の例としてクックパッド株式会社が挙げられます。彼らは、ビルド時間の改善と機能の依存関係を解消したい(疎結合にしたい)という課題を解決する為に、縦割りのマルチモジュール化に着手しました。(6月16日開催iOS Tech Talk 〜 Multi module 戦略座談会 vol.1 〜より)
(引用元: https://techlife.cookpad.com/entry/2021/06/16/110000 )
メリット
- 単機能ビルドが早くなる、開発スピードが上がる
- (依存関係の解消が必要になるので結果的に)全体を疎結合にできる
- お互いに参照していると、、、
- モジュールの循環参照が発生してしまう(リンクができず、ビルドができない)
- 結合が密になっていると、、、
- 修正した際にコンフリクトが起きる可能性がある
- お互いに参照していると、、、
- オーナーシップを持てる
- 組織構造とモジュールが近くなり、他のモジュールに触れる必要が減る
デメリット
- 依存関係の解消が課題
- 依存を抽象化する為のコード量が増える
- いかに自動生成できるかが課題
- オーバーヘッドが増える
- どのモジュールに何を置けば良いか、どこまでを共通コンポーネントに入れたら良いか、それらの交通整理や明文化が大変
具体的な構成
Core ModuleとFeature ModuleでApplication Targetを構成する
Feature Aの開発を行う場合は、Core ModuleとFeautre Aのみで、FeatureASandboxという動作確認用のミニアプリをビルドできる。
- Core Module (CookpadCore / CookpadComponent)
- 抽象化する為のインターフェースやアプリ内で共通しているUIコンポーネントを提供(2021/09/17-19に開催されたiOSDC時点ではCookpadCoreのみの構成に変更されています)
- Feature Module (Feature A / Feature B / Feature C)
レシピの検索機能や投稿機能、買い物機能など、機能単位で一纏めにしている
(引用元: https://techlife.cookpad.com/entry/2021/06/16/110000 )
Feature Moduleの中の各Scene(黄色背景の四角)は、アプリ内の1画面に相当
- 各Sceneは、VIPERアーキテクチャで実装されている
- 近しい機能のSceneが集められ、1つのFeature Moduleを構成
- 例えば、検索機能なら、検索一覧画面と検索結果画面といったイメージ
横割りメインのマルチモジュール構成
AbemaTVの場合
横割りのマルチモジュール構成を重視した企業の例として株式会社AbemaTVが挙げられます。彼らは、iOSとAndroidの設計共通化や、それぞれのプラットフォームで負債化した実装の改善をする目的から、横割りのマルチモジュール化に着手しました。(6月16日開催iOS Tech Talk 〜 Multi module 戦略座談会 vol.1 〜より)
メリット
- 抽象度に応じて分けられる
- 画面の表示確認やそれぞれのフレームワークだけでのビルドが早くなる
- テストを高速で回せる
- マルチモジュール化により責務をはっきりさせることで、iOSとAndroid間の設計差異を無くせる
- エンジニア毎の設計の認識の差異を減らせる
- エンジニアが状況や希望に応じてプラットフォーム間を行き来しやすくなる
- 共通する仕様も多いので、PMや他チーム(サーバーサイドや分析・QAチームなど)とのコミュニケーションを効率化できる
デメリット
- ボイラープレートが増える
- 各レイヤーでモデルの変換が大変
- どこまで自動生成していけるかが課題
- iOSとAndroidの設計差異を減らそうとしても、同じ仕様で必ずしも同じように実装できるとは限らない
- そもそも機能に差異を出す場合もある?
具体的な構成
レイヤー分けをiOSとAndroidで共通化し、レイヤーの中の各モジュール分けは、ある程度プラットフォーム毎に自由を持たせる
- Domain Layer
- サービス全体で共通するような知識をコードとして表現
- Application Layer
- アプリの仕様をUseCaseで記述
- Data Layer
- レポジトリの実装
- Fluxでコアなロジックを実装しており、全て移行する訳にはいかないので、そこにアクセスするインターフェスを提供
- UI Layer
- UIのコンポーネントを実装するUIComponent
- ViewModelを実装するUILogic
- 画像リソースを格納するUIResource
- ダイナミックリンクでないと使い勝手が悪かったりする為、ここだけダイナミックフレームワークで、他はstatic
- UICatalog App
- アプリ全体をビルドしなくても、UIComponentだけ試して触れる環境を用意
- UI Layerがあればビルドできる
縦割りと横割りを組み合わせたマルチモジュール構成
縦割りと横割りのマルチモジュール構成については、これまでご紹介した通りです。どちらかに寄せなければならないということはなく、前述したようにこれらを混合しているアプリがほとんどかと思われます。クックパッド株式会社は、縦割りを重視した企業としてご紹介させていただきましたが、実際にはUIコンポーネントやロギングの為のモジュールといった特定機能を集めた横割り的な構造も持っています。
まとめ
「同じ機能を別アプリで実装する可能性があるか」が縦割り・横割りのどちらを重視するかのポイントにもなってくるのではないかと思います。
ここでは、ざっくりと縦割り横割りという観点でマルチモジュール構成について取り上げました。メリットデメリットで共通するものも多く、一概にどちらが良いとは言えません。自社の状況や目的に合わせて、マルチモジュール構成を考えていきましょう。
謝辞
本記事を掲載するにあたり、クックパッド株式会社のgiginetさん、株式会社AbemaTVのAkio Yasuiさんに、ご確認ご指摘いただきました。 双方お忙しい中、大変ご丁寧な対応をしていただき、心から感謝の気持ちと御礼を申し上げます。