it-swarm-ja.com

APIに裏打ちされたiOSアプリのデザイン

REST api。

ビューコントローラーにアドホックに配置されたAPI呼び出し。

このアプローチでは、View Controllerには、Userオブジェクトなどのバックエンドからフェッチし、そのUserのプロファイルをレンダリングする状態があります。このアプローチは、同期を処理する必要がないという点で単純です。 Webページをレンダリングしているかのように、必要なときにデータをフェッチするだけです。

このアプローチの欠点は2つあります。

  • モデルの表示/更新における競合状態
  • 他のViewControllerのモデルのインスタンスとの同期の問題

最初のポイントを説明するために、ユーザープロファイルに通知カウントがあるとします。プロファイルページにアクセスすると、ユーザーオブジェクトがフェッチされますが、特定のタブにアクセスしたときにユーザーを更新する必要もあります。したがって、2つの呼び出しがあります。

GET /rest/user  # gets the user
POST /rest/user  # clears notifications

その結果、ユーザーのフェッチと通知カウントの更新の間の競合状態が発生します。通知をクリアせずにユーザーオブジェクトをフェッチできます。

2番目のポイントでは、ユーザーオブジェクトを更新しても、更新されたユーザーオブジェクトに依存する他のViewControllerを使用できます。どういうわけか、これらのViewControllerに更新を通知する必要があります。

APIと同期するデータストアを備えたキャッシュとしてアプリを扱います

このアプローチでは、すべてのモデルの更新とフェッチがデータインターフェイスを介してローカルで行われます。データインターフェイスは、バックエンドに同期するタイミングを決定し、ローカルにデータがない場合は、データが利用可能になるまで呼び出し元をブロックします。このアプローチの欠点は、より複雑で、キャッシュの無効化に対処する必要があり、同期を実装する方法が明確でないことです。

このルートに行きたいのですが、どうすればいいのかわかりません。だから、私はいくつかの質問があります:

  • このデータストアは正しいアプローチのように見えますか?
  • このようなデータストアを実装するライブラリはありますか?または、このルートを進むプロジェクトの例はありますか?
  • ビューコントローラーはデータストアを介してオブジェクトのインスタンスをフェッチする場合がありますが、これらのビューコントローラーは通信された更新を何らかの方法で認識する必要があり、それらの更新を通信する方法がわかりません。
1
Eric Conner

ここで2つの良いオプションを提示したと思います。どちらか、または両方の組み合わせが最適に機能するかどうかは、実際に使用しているデータとその使用方法によって異なります。決定的な推奨にはおそらく十分なコンテキストがありませんが、ここにいくつかのアイデアがあります。

アドホックリクエスト

ビューコントローラがAPIに直接アクセスすることを決して許可しないことをお勧めします。最初の提案では、少なくとも「サービス」または「リポジトリ」レイヤーを紹介します。ビューコントローラーにサービスを挿入し、コントローラーに、ドメインモデル(「ユーザープロファイルの更新」など)に関して何らかのアクションを実行するようにサービスに要求させます。これにより、少なくとも複数のAPIリクエストを1つの論理操作にグループ化できます。サービスは複数のリクエストを行い、成功/失敗の結果を集約して完了ブロックを呼び出すことができます。また、サービスは、クライアントキャッシュを導入したり、リクエストの重複を防止したりするための1つの場所を提供します。

提示するデータが異なる画面間で共有されることがめったにない場合、またはクライアント側のキャッシュがほとんど使用されないように頻繁に更新する必要がある場合は、これを使用します。

キャッシュされたREST/SOAPリクエスト

複数のコントローラーで共有されるサービスオブジェクトを介したHTTPキャッシュにより、APIルートが分離されたデータで応答する場合、モデルの一貫したビューが得られます(つまり、1つのルートへのリクエストによって、他のルートからのキャッシュされた応答が無効になることはありません)。

より複雑なバージョンには、APIエンドポイントと正確に一致しない方法でクエリを実行できるCoreDataまたはその他のクライアント側ストアに結果を保存するサービスが含まれる場合があります。結果を共通ストアにアップサートすると、1つのAPI応答で多くの関連エンティティを更新できます。お気づきのとおり、これには、このストアからデータを削除するタイミングに関するポリシーが必要です(APIからの削除手順、最新のAPI応答に表示されないデータを削除するタイミングに関する規則、データ自体の有効期限、またはなど)。 http://jsonapi.org/includedオブジェクトのパターンは、API応答が多くの関連するクライアントモデルを更新する方法としてここで役立つことがわかりました。

データが高度に相互接続されている場合、通常は一度に完全なデータセットのごく一部のみを更新し、残りを再利用できる場合、クライアントが同じデータをさまざまな方法でクエリしたい場合、またはデータを取得した後、データとのオフライン操作をサポートしたい場合。

同期

「同期」と言うとき、私は最後の同期以降の変更のイベントストリームを提供するAPIを思い浮かべます。その後、これらのイベントをクライアントで再生して、ローカルキャッシュを最新の状態にすることができます。ユースケースによっては、これには、すべてのクライアントが増え続けるイベント履歴全体を再生しようとしないように、開始する最近の時点でモデルのスナップショットを要求する機能も必要になる場合があります。そうすれば、十分に古くなったクライアントはあきらめて、最近のスナップショットを要求し、そこから同期を開始できます。

この種の同期は、クライアントのユーザーからのアクションに応答せずに予期せずに到着する更新のストリームに対してはうまく機能しますが、そのようなイベントストリームを生成できるバックエンドが必要です。ニーズに応じて、これはIRCルーム内の一連のメッセージまたはドキュメントを更新する操作変換(Etherpadなど)の場合があります。

これは、定期的または予測不可能であるが頻繁な更新、またはドメインでデータの完全なオフライン編集と後でそれらの変更の再同期が許可される場合に使用します。

2
Jonah