web-dev-qa-db-ja.com

モバイルでRESTサービスを実装するのに適した設計パターンは何ですか?

APIエンドポイントへの呼び出しを実装し、JSONを解析してデータを処理するのは簡単ですが、これに適した設計パターンは何ですか?

ここに私が試したいくつかの方法がありますが、もっと良い方法があるはずだと思います:

  1. すべてのエンドポイントのアプリケーション全体のすべてのネットワークコードとすべてのデータ解析コードを管理するシングルトンクラスを作成します。次に、任意のコントローラクラスがシングルトンをヒットできます
  2. View Controllerから直接ネットワークエンドポイントタスクを作成する-View Controller内のブロックを使用して応答を管理する

エンドポイントをヒット(GET)して、アポイントメントのリストをダウンロードできるアプリケーションを検討してください。また、新しい予定を送信できるPOSTエンドポイントを検討してください。

データはJSONでパッケージ化/パッケージ化解除する必要があり、エラーは適切に処理する必要があります。

これを達成するための良いデザインパターンは何ですか?

そして、あなたがこの投稿に反対票を投じてその広すぎるか主観的であると言う前に、このページを見てください:

https://softwareengineering.stackexchange.com/help/dont-ask

いくつかの主観的な質問は許可されていますが、「主観的」は「何でも」という意味ではありません。すべての主観的な質問は建設的であることが期待されます

この一般的な問題に対する適切な答えを見つけるのは困難です。

4
Spentak

REST APIを他のデータソースと同様に扱い、コントローラーが使用する抽象化(AppointmentRepositoryなど)を作成します。私の例はJavaですが、アイデアはわかると思います。

public interface AppointmentRepository {
    Appointment findById(String id) throws RepositoryAccessException;
    void create(Appointment appointment) throws RepositoryAccessException;
    void update(Appointment appointment) throws RepositoryAccessException;
    void delete(Appointment appointment) throws RepositoryAccessException;
}

public class RestAppointmentRepository {
    @Override
    public Appointment findById(String id) throws RepositoryAccessException {
        // make the API call
        // translate the JSON to an Appointment object
        return appointment;
    }
    // etc
}

このように抽象化を使用すると、コントローラーがデータの具体的なソースから切り離されるため、2つは互いに影響を与えることなく変更できます。 REST APIが予定の表現を変更するかどうか、つまりマッピングコードを変更する必要があるかどうかを検討します。そのマッピングコードが抽象化の背後に隠されている場合、変更を行う必要はありません。 REST APIの変更を処理するためにコントローラーに追加します。

このアプローチでは、REST APIがデータを返すことを心配せずに、コントローラーをより簡単にユニットテストして、ユニットテストをサポートすることもできます。ハッピーパステストに加えて、 REST APIが利用できない場合、つまりリポジトリメソッドが例外をスローした場合に、コントローラが適切に反応することをテストします。リポジトリインターフェースをコントローラの依存関係として取得し、ユニットテストでモックします。その動作を簡単に定義できること。

public AppointmentController extends ViewController {
    private final AppointmentRepository appointmentRepository;

    public AppointmentController(final AppointmentRepository appointmentRepository) {
        Preconditions.checkNotNull(appointmentRepository);
        this.appointmentRepository = appointmentRepository;
    }
}
...
// unit test
AppointmentController appointmentController = new AppointmentController(mockAppointmentRepository);
3
Mike Partridge

2つ目の方法(ビューコントローラーからの直接エンドポイントコール)は、ビューから切り離されたバルク/自動化されたapiコールに機能を拡張する必要がある可能性があるため、あまり将来的には向きません。

たとえば、Excelの入力に基づいて、アプリ経由で100,000件の予定を投稿するという新しい要件が出てきた場合、ターゲットエンドポイントでのAPI呼び出しの制限を回避するために実行をバッチ処理およびスケジュールする必要がありますか?呼び出しと処理のコードがフォームのビューコントローラーに組み込まれている場合(SINGLEの予定を定義して投稿する)、それを独自のクラス(おそらくシングルトン)に抽出し、拡張してバルクケースを処理できるようにします。 、および応答を処理します。

リクエストの送信はライブラリによって処理され、応答のJSON解析は(おそらく?)ライブラリによって処理されるため、重要な点は、すべてのエンドポイントのすべての呼び出し応答ロジックを1つのクラスにラップするか、各ターゲットシステム。

アポイントメントAPIへのget/postを調べる代わりに、ERP統合による請求書の作成とProduct Server統合による資格の両方を制御するマスターCRMシステムを検討してください。この場合、 2つのSEPARATE APIが統合ロジックによって消費されますが、同じライブラリロジックを利用して応答を要求および解析します。

私のアプローチは:

  1. 各システム統合のすべてのコントローラー(そしてそれほど重要ではないがビュー)ロジックを、アプリケーション内の独自の名前空間に分離します。例)ERP_Example、PS_Example

  2. 統合呼び出しの内容(リクエストの属性)を(インラインの可能性がある)クラスに抽象化し、JSONシリアライゼーションを使用して、システム固有の専用の静的統合クラスによって制御され、呼び出しを行い、応答を解析し、ルーティングします成功/失敗ロジック。

例)ERP_InvoiceIntegration.class、PR_EntitlementIntegration.class

  1. 次に、コールをバルク化する必要がある場合は、次のものを作成できます。

ERP_BatchableInvoiceActioner.class、PR_BatchableEntitlementsActioner.class

バルクのケースを処理し、各バッチ内から統合クラスを呼び出し、クラス自体が成功/失敗を正しくルーティングすることを確認します。

また、このパターンは同期と非同期の両方のAPI呼び出しを処理できるようですが、一括処理の場合ほどではありません。

より短い回答:統合ターゲットごとにシングルトン。ただし、API呼び出しごとに(get/post/etc)...

1
DavidWaugh