iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

ReactorKit における Clean Architecture の立ち位置を考える

ReactorKit はリアクティブかつ一方向のデータフローをサポートするための Framework です。ReactorKit について詳しく知りたい場合は以前の記事を参照してください。

yamato8010.hatenablog.com

yamato8010.hatenablog.com

ReactorKit はユーザアクションからのデータの流れや各クラスにおける強い制約が存在するため、ある程度の範囲はカバーできますが、副作用のある処理(ReactorKit の説明でいうところの side effect) については制約がなく、公式では Service レイヤーを設けてそこで処理するとの説明があります。そのためService レイヤーで、より Testability や処理の見通しがいいような設計思想を Service レイヤーで持つために、今回は Clean Architecture を使おうということで、簡単に Clean Architecture 設計をまとめていきたいと思います。

Clean Architecture

メリット

  • Testability の向上

    • それぞれのレイヤーのクラス単位が細かい且つ疎結合なのでテストが簡単になる。またクラスで他のクラスのオブジェクトに依存する際はプロトコルを使用することで Mock との差し替えが容易になる。
  • 再利用性の向上

    • 疎結合になることでそれぞれのクラスは特定のオブジェクトに依存しないのでクラス間の再利用性が向上し、実装の効率をあげることができる。
  • 機能修正・置き換え

    • 各レイヤーの責務が明確に分けられているので、DB の差し替えや UI の差し替えも比較的容易に行うことができ変更に強くなる。

デメリット

  • 学習コスト
    • 複数人で開発する際などは、チーム全体が Clean Architecture の設計思想を理解している必要がある。
  • コード・ファイル量の増加
    • がっつり新しい機能開発をする際は、それぞれのレイヤーを作る必要があるので、必然的にコード・ファイルの数は多くなる。

各レイヤの役割

下記の記事の図が大変分かりやすかったため参照させていただきます。

qiita.com

参照: https://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc

Presentation Layer

UI イベントの通知や表示などの処理をこのレイヤーで行い、ビジネスロジックなどはこのレイヤーでは持たない。

  • View

    • 責務:
      • ユーザから受け取ったタッチイベントなどのイベントを Presenter に通知
      • Presenter から受け取った Model を元に View を更新
    • 依存範囲:
      • Presenter Protocol
  • Presenter

    • 責務:
      • View から受け取ったイベントを元に UseCase を実行
      • UseCase から受け取った Model を View に通知
    • 依存範囲:
      • UseCase Protocol

Domain Layer

iOS アプリケーションに依存しているビジネスロジックを担うレイヤー。

  • UseCase

    • 責務:
      • Presenter から通知を受け取りビジネスロジック(どのデータをどのように取得するのかなど)を処理
        • 必要なら Repository を実行してデータを取得
        • 必要なら Translater を実行して Model を取得
      • ビジネスロジックで処理した結果の Model を Presenter に通知
    • 依存範囲:
      • Repository Protocol, Translater Protocol?
  • Translater

    • 責務:
      • UseCase から通知とデータを受け取り Model を生成
        • Converter 的役割
      • UseCase に Model を渡す
    • 依存範囲:
      • Model

Data Layer

通信とデータ管理のロジックを担うレイヤー。

  • Repository

    • 責務:
      • UseCase から通知を受け取り、DataStore にデータの取得処理を依頼
        • どこからデータを取得するかは知る必要がなく、単にデータの CRUD に対応する I/F を記述する
      • UseCase にデータを渡す
    • 依存範囲:
      • DataStore Protocol
  • DataStore

    • 責務:
      • Repository からの通知を受け取りデータを取得
        • サーバ・DBやキャッシュからの取得のハンドリング
        • 必要なら DB の更新(Realm, CoreData など)
      • 取得したデータを Repository に渡す
    • 依存範囲:
      • Entity
        • Entity は Presentation Layer では使用されない

ReactorKit + Clean Architecture での個人的な勘所

ReactorKit の制約として、Clean Architecture でいう Presentation Layer は、設計として担保されているので必要なさそうで、逆に Service レイヤーとしての設計では、Domain Layer・Data Layer が必要そうです。ただし、Data Layer 以外のロジックをどこに持たせるかは悩ましいところで、処理の見通しの良さと Clean ArchitectureUseCase の役割を考えた場合は、Reactor の mutate()ビジネスロジックは持たずに、UseCase で処理を行った方が良さそうです。(Reactor にビジネスロジックを持たせたら、UseCase の意味はなくなる + Reactor が複雑化する)

また、実際に取り入れたらコードを交えて記事を書きたいと思います🙃

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com