Kiri ライブラリで、ネットワークリクエストの新しいやり方を試しています。 KiriMoya にインスパイアされたネットワーク抽象化レイヤーです。Moya のアーキテクチャにとても感銘を受けたので、そこから最大限学ぶために、コピー&ペーストではなく、同じアーキテクチャを自分の手でなぞって書いてみることにしました。:D

クライアントライブラリは 3 つの部分に分解して考える必要があります。

Request

通常、ネットワークリクエストは毎回組み立てなければなりません。 一方 Kiri では、ネットワークの設定を class や enum のような形で 1 か所にまとめて記述します。 そして、その class や enum は RequestContainer プロトコルに準拠している必要があります。

サンプルコードは次のようになります。

enum TestAPIRequest {
  case getitems
  case postitem
  case updateitem
  case deleteitem
}

enum TestAPIRequest: RequestContainer {
  var baseURL: URL {
    return URL(string: "https://www.example.com/api/v1")!
  }
  
  var path: String {
    switch self {
      case .getitems:
      return "/getitems"
      .....
    }
  }
  
  ....
}

これは API クライアントの設計という観点で優れています。 クライアントモジュールを作り始める前に、全体の構造をひと目で把握できます。 また、定数文字列をすべてのクラスに渡す必要もありません。Kiri は baseURL のような共通部分を持てるので、そうしたものをメソッドに切り出してラップしていけば、アプリ内の重複コードを避けられます。

ただし、API ごとにエンドポイントが異なるといった場合は、そう簡単にはいきません。そのようなケースでは、API ごとに別々のクラスを作りたくなるでしょう。それも理にかなっています。(残念ながら)そうした API に出会ってしまったら、代わりに APIKit を検討するのがよいと思います。APIKit はもともと API ごとにクラスを分ける設計になっており、レスポンスについても Kiri や Moya よりジェネリックなアプローチを取っています。

Networking

iOS には URLSession という独自のネットワーククラスがあります。しかし、今さら URLSession をラップする意味はありません。私たちには Alamofire があります。 Alamofire はリクエストとレスポンスを自動的にバリデーションし、JSON も返してくれます。とはいえ、ネットワークライブラリは複数のレスポンスフォーマットをサポートすべきなので、私はレスポンスを Data のまま保持するほうが好みです。

Kiri はネットワークリクエストに Alamofire を利用し、リクエストの構築を Alamofire に委譲しています。

ほとんどのケースで Alamofire はとてもうまく機能しますが、パラメータを自分で組み立てたいなど、よりプリミティブなネットワーク処理が必要な場合には向かないかもしれません。

Response

ここにはトレードオフがあることに気づきました。レスポンスをジェネリックにすると、リクエストが複数のクラスに分断されます。逆に、リクエストをジェネリックにすると、今度はレスポンスが分断されます。

MoyaAPIKit の両方のコードを読みました。私見では、この 2 つは Swift のネットワーキングにおいて最も洗練されたアーキテクチャですが、それぞれに一長一短があります。

ネットワーキングのベストな解はまだ見つけられていませんが、今のところは、アプリの要件に応じて賢く選ぶのが最良の答えだと思います。

参考リンク

Kiri は Moya よりはるかに小さいライブラリですが、私の個人プロジェクトでは問題なく動いています。ぜひ試してみてください!