業務で採用してみたいiOSアプリのアーキテクチャと技術
浅井 徹
はじめに
こんにちは、初めまして、iOSアプリエンジニアのtasaiです。この記事は リクルートライフスタイル Advent Calendar 2019 19日目の記事です。私は入社したばかりなので業務で使っている技術についてではなく、業務で採用してみたいiOSアプリのアーキテクチャと技術についてご紹介します。
前提
業務でMVVMでのアプリリニューアルやVIPERでのリアーキテクチャをしてきた経験をもとに、クロスプラットフォーム技術の採用を視野に入れて検討した内容となります。
解決したい課題
モバイルアプリの開発において継続的に改善を行うようなプロダクトでは、以下のような課題があるのは珍しいことではないかと思います。
- 長年の運用で溜まっていた技術的負債
- ユニットテスト/UIテストコードが書きづらい責務分割
- そもそも設計方針が決まっていなかったり、複数のアーキテクチャを抱えたりしている
Appleは毎年新技術を発表し、iOSアプリの主要な開発言語であるSwiftもどんどんバージョンアップが行われています。ビジネスサイドの要求に答えつつ技術的な改善を行っていくことは難しい面もあると思いますが、アーキテクチャや構成を整えることで改善しやすいプロダクトにしておくということが重要だと思います。
アーキテクチャ
MVVM + Layered Architecture
前述した3つの課題を解決できるアーキテクチャの1つは、MVVMとLayered Architectureの併用だと考えます。
MVVMとは?
MVVMは有名なアーキテクチャのためご存知の方も多いでしょう。簡単に説明をすると、プレゼンテーションロジックとビジネスロジックを分離するGUIアーキテクチャのひとつで、ViewとViewModelをデータバインディングすることで宣言的にViewの更新が行えるという特徴があります。
Layered Architectureとは?
Layered Architectureとは、日本語では多層/階層化アーキテクチャと呼ばれ、アプリケーションを複数の層に分割し、それらを独立したモジュールとして疎結合にすることで、モジュールごとの開発がしやすかったり入れ替えが容易になるような特徴のあるものです。Clean ArchitectureやOnion Architectureもこれの一種です。
前述した通りMVVMはGUIアーキテクチャのため、Modelの詳細な責務分割については関知していません。そこで、Modelの責務分割としてLayered Architectureを採用します。Layered Architectureと言っても層の分割方法はプラットフォームによっても違いますし粒度によっても違うなど多種多様です。その中で、今回採用するのは以下のようなInfrastructure層、Data層、Domain層と分割するものです。
Layered Architectureの各層の役割はこのように定義します。
Infrastructure層
サーバーへの通信処理やDBへのアクセス、キャッシュ機構などを定義する層
Data層
データの定義とInfrastructure層の機能を使った実際のデータ取得処理を記述する層
Domain層
アプリケーションの仕様を実現するためにデータ取得をData層に依頼したり、取得したデータを加工する層
採用したいアーキテクチャの全貌
MVVMのModel部分にLayered Architectureを適用してみると以下のような図になります。(厳密にはLayered Architectureとは言えないかもしれませんが、そのエッセンスを組み合わせたものとしてご認識ください)
採用技術
Embedded Framework分割
Embedded Frameworkとは?
Embedded Frameworkとはアプリのコードをフレームワークとして分割できる機能です。メインとなるターゲット(iOS App、App Extension、Watch Appなど)とは別に、任意の区分でソースコードをフレームワークとして分割する機能です。
Embedded Frameworkのメリット
- App ExtensionやwatchOS向けAppなどへのコード共有
- 差分ビルドによるビルド時間短縮
- アーキテクチャの依存関係の強制とテスタブルなコードの書きやすさ
などがあります。Embedded Frameworkに分割しない場合、メインとなるターゲットごとにソースコードをコンパイルするのでバイナリサイズやビルド時間が増加してしまいますが、Embedded Frameworkに分割することで、メインとなるターゲットがソースコードを共有するようになりサイズの減少/ビルド時間の短縮されるメリットがあります。
そして注目したいのが、3のアーキテクチャの依存関係の強制についてです。妄想iOSアプリ新規開発やiOSアプリを作るときのおすすめ構成でも言及されていますが、前述した通りLayered Architectureは複数の層に別れた構造をするためEmbedded Frameworkとして分割することでメリットを受けやすく、わかりやすい構成にすることができます。
Kotlin/Native
Kotlin/Nativeとは?
Kotlinで記述されたプログラムをNativeなバイナリコードにコンパイルする技術です。サポートしているプラットフォームは公式サイトを見ていただくのが良いですが、iOS/Androidをはじめとする多数のプラットフォームのサポートが行われています。昨今で話題のReactNativeやFlutterとは違い共通UIを提供していないことでアプリケーション全体の構成には関与しないという特徴を持っています。2019年12月時点ではまだbeta版となっています。
Kotlin/Nativeを導入するとどうなるか
前述したようにまだbeta版のため、他社の採用事例もあまり存在しておらず業務で採用するにはリスクがあり注意が必要となります。しかし、Kotlin/NativeはOSSで開発されており、非常に細かくリリースが繰り返されているため、正式リリースに向けて着実に進んでいると考えられます。また、今回紹介したアーキテクチャのModel(= Layered Architecture)部分をKotlin/Nativeで作ることで全体のアーキテクチャに影響を与えずに、iOS/Androidアプリのドメインロジックを共通化できることが非常に大きなメリットになるため採用してみたいと考えています。さらに、KotlinConf'19のOpening Keynoteでも大きく取り上げられており、今後への期待の高まりを感じられます。
SwiftUI / Combineへの備え
SwiftUIとは?
WWDC2019でAppleから発表された新しいUIフレームワークです。宣言的にUIを記述でき、リストを表示するコードは既存のUITableViewを使うよりもかなり少ないコード量で実現できるなどの特徴があります。iOS13から利用可能です。
Combineとは?
こちらもWWDC2019で発表された非同期イベントを処理するフレームワークで、データバインディング機構も提供しています。同様にiOS13から利用可能です。
将来を見据えた備え
iOSとしてMVVMを採用したいと考えている理由として、SwiftUIとCombineへの備えがあります。前述した通りこの2つの新機能はiOS13から利用が可能です。実際のプロダクトに導入できるのはiOS13以上のサポートになった時で2,3年後からです。MVVMのView部分がSwiftUIに置きかわり、ViewModelとViewのデータバインディング機構をCombineに置き換えるといった作業が必要になると思います。置き換えることを想定して作ることでコストを限りなく抑えることが可能になるため、MVVMはSwiftUI/Combineへの備えとして採用するのが良いと考えています。
まとめ
- アーキテクチャはMVVM + Layered Architecture
- SwiftUI + Combineを見据えて、置き換えしやすいMVVMを採用する
- MVVMのModel部分にLayered Architectureを採用する
- Model(= Layered Architecture)部分をKotlin/Nativeで実装する
最終的に採用したいアーキテクチャと技術を図にすると以下のようになります。
終わりに
この記事ではクロスプラットフォーム技術の採用を視野に入れて業務で採用してみたいアーキテクチャと技術を記事にさせていただきました。紹介した内容はまだ実際に採用されているものではないことにご注意ください。組織や時代、プロダクトのフェーズによって採用するべきアーキテクチャと技術は違うと思います。アプリのアーキテクチャや採用技術に正解はないですが、将来を見据えてベストを尽くすことが必要です。最後までお読みいただきありがとうございました。