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

巨大な機能を VIPER + MicroViewController でいい感じに実装した話

巨大な機能を VIPER + MicroViewController でいい感じに実装した話

こちらの勉強会の登壇資料です

iOS Clean Architecture勉強会 sponsored by Sansan
https://connpass.com/event/158269/

yuichiro_takahashi

January 21, 2020
Tweet

More Decks by yuichiro_takahashi

Other Decks in Technology

Transcript

  1. - 髙橋佑一朗 (@ChaaaaaaaaaaanU) - Sansan 株式会社 - iOS アプリエンジニア -

    Flutter やってます - ゲーム大好き - DbD, Bloodborne, Dark Souls, Pokemon, Smabro, etc... Who am I?
  2. - Why VIPER? - What’s happened? - What MicroViewController -

    How do we combine them? - Summary - Next Step Agenda
  3. - アプリが複雑化し ViewController が FatViewController へ進化 - 更に各ロジックがほとんど ViewController に記述されていて密接に絡み合って

    いる - テストも書けないし、コードの見通しも悪くなってしまった - どこかを直すとどこかが壊れるピ◯ゴラスイッチ状態 Why VIPER? - 課題感
  4. - 機能が大きすぎて一つの VIPER Module として実装するのは無理がある - 各機能毎に独立した ViewController を用意して一つ一つの Module

    を小さく保 ちたい - 機能毎に分割するとそこそこ ViewController の量が増えるので各 ViewController の通信の Interface を統一したい - TableViewCell に ViewController を attach するのは意外と面倒そう What’s happened? - 課題感
  5. - Mercari 発のアーキテクチャで iOSDC 2018 にて発表 - 画面はもちろん画面を構成するボタンやラベルまで全て ViewController で構成

    するアーキテクチャ - 画面を構成する全てのパーツが自身に紐づくロジックを持っており、画面遷移な ど複雑になりがちな処理をすっきりさせられる - 全てのUIパーツが独立した ViewController であるため並列での作業が行いや すい - MicroViewController の導入を支援する Mew というライブラリが公開されてい る What MicroViewController?
  6. How do we combine them? - VC間の通信 public protocol Injectable

    { associatedtype Input func input(_ input: Input) } Mewより抜粋: https://github.com/mercari/Mew
  7. How do we combine them? - 第一層 - 人物詳細の大元のモジュール -

    ここはまだ標準的な VIPER - この層の役割は以下の三つ - 人物詳細画面のコアとなる人物の基本データを取得する - 人物詳細画面全体にかかわるエラーやイベントの制御 - 人物詳細全体の遷移処理を行う > 遷移に必要なデータと遷移のイベントは子や孫から渡ってくる
  8. - PersonDetail モジュールの子供達 - ここから Router がいなくなる - この三つのモジュールは PersonDetail

    の Router でインスタンス化される - この層の役割は主に以下の三つ - 子供達の管理 - 子供達が自身を描画するのに必要データの取得 - 子供から受け取った各種イベントを PersonDetail へ伝播させる How do we combine them? - 第二層
  9. - Summary, OwnBizCard モジュールの子供達 - 大家族 - ここの ViewController は

    自身で依存性の解決を行う - この層の役割は主に以下の二つ - 親から受け取ったデータを表示する(正常系、エラー系共に) - 遷移などのイベントを必要なデータと共に親へ伝える How do we combine them? - 第三層
  10. - Instantiatable と Router の責務が被ってしまった (依存性の解決) - 更に遷移は大元の Router で行うようにしているため必要性がなくなってしまっ

    た - 各 ViewController から遷移させるようにすれば Router の必要性は出てくるが どっちつかずになってしまいそう - 今は以下のルールで運用 - 原則 Instantiatable を利用しない - Instantiatable を利用しなくてはならない場合は Router は作成しない - 遷移は Interactable 経由で大元の Router にイベントを伝えて遷移させる How do we combine them? - なぜ Router は消えたか?
  11. - メリット - 当初抱えていた課題間は大方解消されていてかなりやりやすかった - Input, Output の Interface が統一されているのでデータの受け渡しについて混乱す

    ることはなかった - 面倒な ViewController の管理も Mew が引き受けてくれるのでとても楽 Summary - この構成のメリット
  12. - デメリット - Instantiatable と Router の落とし所を見つけるのが少し大変だった - モジュールが多くなるのでファイル数とコード量が凄まじい -

    二つのアーキテクチャを正しく理解しないといけない(自分もチームのメンバーも) - 基本的にデータの受け渡しが Input, Output 経由でのフロー同期なので距離が離れ た viewcontroller のデータの受け渡しはかなり冗長 - Mewのメンテナンスがちょっと心配 Summary - この構成のデメリット
  13. Next Step - 今後 - Instantiatable を拡張して Router を渡せるようにしたい (もう少し

    VIPER に寄 せたい) - ファイル数とボイラープレートの量が尋常じゃないのでもう少し減らしたい - Qiita にそんな記事があったような