[iOS] ViewControllerが遷移先のViewControllerについて知っているのが気持ち悪い!

2016.11.16

おばんです、友人にもらったオーブンレンジの具合を見ることもかねて、東京に来てからできていなかったおかし作りを再開した田中です。
クッキー作った、おいしい。(・〜・)mgmg

15027584_1163304260421309_2193501885167340203_n

今回はふと気になったViewControllerがViewControllerについて知っているということについて、画面遷移をつかさどるRouterを実装してみたという話です。
GitHubにサンプルと走り書きのREADMEも用意したので合わせて読んでいただければと思います。

ktanaka117/TransitionRouterSample: An implementation sample of TransitionRouter which manages ViewController transition.

依存関係について

僕は知る=依存しているだとこと思っています。(ここ哲学)
iOSにおいて画面遷移を行うのはUIViewControllerであり、フレームワークの設計上、一見なんの問題も無いように思いますが、クリーンアーキテクチャでアプリを実装している際に、ある役割(ViewController)が同一の役割を知ることに違和感がありました。
ゴーストのささやきです。

違和感の正体

Presenterが他のPresenterを保持することはなく、UseCaseが他のUseCaseを保持することはありません。
それをすればクリーンアーキテクチャにおいてはその依存関係を一方向に保つことができなくなります。
にも関わらずViewControllerは他のViewControllerを生成して画面遷移をそのまま実行するという作りを実装していました。
クリーンアーキテクチャのPresentation層において、描画に関するロジックと描画指示はPresenterが行っています。
その認識に間違いがなければ、画面遷移に関する指示もPresenterから送るべきだと思いました。

正しい形は

クリーンアーキテクチャないしMVPパターンにおいて、遷移に関するロジックとViewControllerへの指示はPresenterが受け持ちますが、ViewController自体をPresenterが生成したりそのViewControllerを操作したりすると依存関係が複雑になります。
PresenterはViewやControllerに関して直接の操作を行いません。
では誰が行うか?ここで登場するのが(Transition)Routerです。

TransitionRouterというのは「画面遷移を一元管理するクラス」として勝手に命名している名前ですが、役割は画面遷移のルーターです。
このRouterが遷移先のViewControllerを生成し、遷移元のViewControllerにそれを「渡すだけ」の形にすれば綺麗だと思いました。
こんな作りです。

TransitionRouter

これでViewControllerはRouterが生成し、Protocolを実装したViewControllerが渡されたViewControllerに対して遷移するだけになりました。
ViewController同士が知り合うことは無くなりました。

まとめ

設計の話に正解はありません。(と言って逃げておきます)
今回はお試しで書いてみたという感じで、GitHubのREADMEにも書いている今後の研究事項も試してみようと思います。

参考