iOSアプリにおけるソフトウェアアーキテクチャパターンの考察

私が試したことのあるiOSアプリでのソフトウェアアーキテクチャパターンとそれに関わるフレームワークの考察です。実際に使ってみて考えたことや感じたことを元に書いていきます。

基本のMVC

コントローラが肥大化することやモデルレイヤーの設計が明確でないなどの問題があるといわれています。しかし、比較的小さいプロジェクトではたいてい肥大化の心配もモデルレイヤーの詳細な設計も必要ないのでMVCを選択すると良いと思います。


MVVM

MVVMはビューとモデルを繋ぐビューモデルが重要な役割を果たします。問題は、画面遷移やモデルレイヤーの設計が示されていないことです。極端な例ですが、ビューモデルにAPIアクセスのコードを書いてしまい、ビューモデルが肥大化して問題になったという話を聞いたことがあります。MVVMを採用するほどのアプリになると画面遷移やモデルレイヤーの実装方法を規定すると良いのですが、MVC同様にMVVMだけではそれが解決できません。ですので、あとで言及するVIPERやクリーンアーキテクチャからアイデアを採用するとよいでしょう。

また、MVVMを採用する必要がない程度のサイズの実装でもMVVMを採用する事もあるようです。その場合はMVCで実装しておいて、必要が出てきた段階でMVVMに移行する方が良いように思います。FRPを効果的に利用すればMVVMを利用する場面はかなり少なくなると思います。

ビューモデルとビューを接続するために大抵はFRPライブラリが利用されます。ですのでアプリ全体でFRPでデータの流れを作っていくことになると思います。そうなるとアプリの開発がFRPライブラリの開発に引きずられることになります。FRPライブラリのSwiftの最新バージョンへの対応が遅れればアプリの対応も遅れますし、ライブラリの開発が遅滞すればアプリにも影響があります。アプリ全体がFRPに依存するので、アプリの寿命に影響を与えかねません。

さらに、開発者のFRPの概念とライブラリの理解度をある程度揃える必要がありますが、FRPは理解し難いといわれています。FRPのFはFunctionalですが、ロジックの実装をFunctionalにすることでFRPの力を最大限発揮させることができると思うのですが、そのためにはFunctional Programmingを学ぶ必要があります。

ですのでMVVMを採用することはつまりFRPひいてはFunctional Programmingを学ぶということとなり、実際の採用ではその点を十分検討する必要があります。

FRPライブラリ

FRPライブラリには主にReactiveCocoa(以下RAC)とRxSwiftがあります。日本ではSwift時代になってからはRxSwiftの人気が圧倒的なようです。ですので日本語の情報はRxSwiftの方が得やすいです。

しかし、RxSwiftはエラー型やHot/Coldが分かりにくいので規模が大きくなってきたり複数人での開発となると、エラー型もHot/Coldの違いも分かりやすいRACの方が有利になる可能性があります。このような点に注意して採用を検討すると良いと思います。


VIPER

Router-View-Presenter-Interactor-Entityにレイヤーを分けるのですが、プロトコルに依存して主に双方向の参照を持ってメソッドを呼び合うので、参照の管理に注意が必要です。メモリーリークが発生しないように片方はweak参照にしたり、全ての参照を構成するためにDIを使うことになります。

クリーンアーキテクチャには画面遷移のレイヤーは規定されてないと思いますが、VIPERにはRouterとして規定されています。またクリーンアーキテクチャはVIPERより更に細かい役割が規定されているので、実際にはVIPERとクリーンアーキテクチャを混ぜて実装する場面もあると思います。

VIPERは小規模なプロジェクトで採用するとオーバースペックなので、大規模もしくは複雑なプロジェクトで採用する方が良いです。

DIコンテナ

DIはDIコンテナを使うと簡単に実装できます。SwiftだけであればSwinjectを採用すると良いと思います。AssemblyTypeを利用するとモジュールごとにInjectionを記述することがやりやすくなります。Objective-Cまで含めるとTyphoon Frameworkがありますが、今後開発されるアプリでObjCを採用することは少ないでしょう。Typhoon Frameworkは現在Swift実装版を開発中らしいです。

ちなみにプロトコルを多用した実装ではプロトコルとその実装とを行き来することが多いのですが、AppCodeを使うと簡単に行き来することができるのでプロトコルの利用を面倒に感じることがありません。AppCodeでのSwiftの実装はかなり実用的になってきているので、一度試して見られると良いと思います。


Redux

Reduxを利用するのは私にはまだ躊躇われます。なぜならまだフレームワークが成熟しておらず、今後どのライブラリが主流になるかが決まっていないと思うからです。Reduxはアプリ全体がフレームワークに依存するので、フレームワークの選定は慎重にならざるを得ません。ReSwiftというフレームワークが有名ですがまだ他のフレームワークが伸びる可能性が十分あります。

また、Reduxやその元となったFluxはSingle Page Application(SPA)での状態管理の問題の解決に利用されるのですが多くのiOSアプリはSPAほどアプリ全体での状態の管理を必要としないと思われます。ですのでReduxを採用するかどうかはアプリ全体での状態の管理がどの程度必要かを検討すると良いでしょう。


以上のように、私がこれまで利用したり試したりしてきたアーキテクチャパターンやフレームワークについて考察してみました。私が会社で担当しているアプリでは現在はVIPERを採用しています。しかし個人で制作しているアプリではFRP(RAC)を採用してMVVM+Router+Interactorのような構成です。そのアプリにふさわしいアーキテクチャを、時に既存のパターンをそのまま利用したり、時に組み合わせたりして作り上げていくと良いと思います。