APIとアプリケーションの間でオブジェクトを共有するためのパターン


9

私のWebアプリケーションの設計について深刻な疑いがあります。

ビジネスロジックをインターフェイスから分離したかったので、データベースへのすべての要求を処理するWeb APIを作成しました。

これは、エンティティフレームワークと作業ユニットおよび汎用リポジトリパターンを備えたASP.NET Web APIです。これまでのところ、すべてが良好です。

問題

ヘルプが必要なのは、APIとアプリケーションの間でオブジェクトを共有する効率的な方法がわからない場合です。

エンティティオブジェクトを直接シリアル化したくありません。エンティティモデルが変更された場合、理由もなく大きなオブジェクトをシリアル化してしまう可能性があるため、これは悪い習慣だと思いました。

現在どのように実装されているか

インターフェイスはC#のASP.NET Webアプリケーションであり、APIはC#であるため、共有したいすべてのクラスの定義を含む共通ライブラリを作成しました。

私はAndroidアプリを開発するときにソリューションが機能しないことを知っています。Javaでクラスを再度作成する必要がありますが、それは私の最大の問題ではありません。

問題は、常にオブジェクトを変換しているような気がすることです。

これが私のワークフローの例です:

すべてのオブジェクトとフォームのデータ注釈を含むモデルから始め、ユーザーはそのモデルをコントローラーにPOSTします。

コントローラーでは、このモデルを共通ライブラリーのクラスに変換してから、そのオブジェクトをAPIに送信する必要があります。

次に、私のAPIのコントローラーが呼び出しをキャッチし、そのオブジェクトをエンティティオブジェクトに変換して、データベースを更新します。

だから私は3つのクラスを持っています

  1. 検証用のすべてのデータ注釈を含むビューのモデル(クライアント)
  2. オブジェクトを共有するための共通ライブラリクラス(DLL)
  3. エンティティークラス(API)

何か間違ったことをしているような気がします。よりエレガントなものはありますか?プロジェクトが大きくなりすぎる前に、この問題に対する適切な解決策があることを確認したいと思います。


私の質問が明確でない場合は、遠慮なく質問してください。
Marc

私にとって、どのアーキテクチャを実装したかは明らかではありません(多分それは.netの文言が私を困惑させています)-それは3層アーキテクチャですか?クライアント、サーバー、dbですか?
アンディ

はい、Web APIを使用するWebアプリケーションがあります。APIは、データベースを備えたビジネスロジックを備えたものです。
2014年

回答:


12

データベースオブジェクト、データ転送オブジェクト、検証ロジックを備えたクライアントオブジェクトなどの間で、常にオブジェクトを前後に変換しているように見えるかもしれませんが、いいえ、あなたは何も間違っていません。

これらの各オブジェクトは、同じ情報単位を表す場合がありますが、責任は大きく異なります。データベースオブジェクトは、データベースとの通信インターフェイスであり、データベースメタデータアノテーションやデータベース実装に関する不必要な詳細が含まれている場合とそうでない場合があるため、データベースレイヤーに保持する必要があります。

データ転送オブジェクトは、APIコンシューマーとの通信インターフェースです。異なる言語/プラットフォームから簡単に利用できるように、これらはできるだけクリーンである必要があります。これにより、サポートするAPIコンシューマーに応じて、これらの外観と動作に特定の制限が課される場合があります。

検証ロジックを備えたクライアントオブジェクトは、実際にはAPIプロジェクトの一部ではなく、コンシューマープロジェクトの一部です。これらは、サーバーが何も知らない(そして何も知らないはずの)クライアント固有のロジック(この場合は検証属性)を追加するため、この場合のデータ転送オブジェクトと同じにすることはできません。これらのオブジェクトは実際にはないため、APIの一部としてカウントします。これらは非常にコンシューマーアプリケーションに固有であり、APIを使用する一部のアプリケーションは実際にはこれらのオブジェクトを作成する必要すらなく、データ転送オブジェクトだけで存続することもできます。たとえば、検証の必要がない場合は、データ転送オブジェクトと完全に同一であるオブジェクトの追加レイヤーは必要ありません。

私には、3つのオブジェクトタイプのそれぞれが、明確なコーディングと優れた実践である単一の責任に非常にうまく対応しているようです。悲しいことに、クリーンなコードと優れたプラクティスは、多くの追加のコードを記述し、「単に」という理由で追加のフープを飛び越えていることを意味します。そしてコーディング中、これがあなたに与える価値を理解するのは難しいかもしれません-しかし、あなたがアプリケーションをリリースし、それをサポートし始めるか、次のバージョンのために新しい機能を追加するやいなや、あなたはおそらくあなたが時間をかけたことに感謝し始めるでしょう。そもそもこれらの懸念を適切に分離してください。(言うまでもなく、

このような異なるオブジェクトタイプ間の変換コードを書くのも嫌いですが、私の解決策は通常、次のいずれかです。

  • オブジェクト変換の大部分を行うライブラリを使用してください。たとえば、C#を使用している場合は、素晴らしいAutoMapperライブラリ(http://automapper.org/)を使用できます。このようなライブラリは他にもいくつかあると思いますが、AutoMapperはこれまでに見た中で最も強力なライブラリです。
  • オブジェクトの変換に役立つライブラリが見つからない場合は、それらの間で変換するためのユーティリティメソッドのセットを記述します。これはひどいかもしれませんが、長い目で見ればそれだけの価値があります。何かを初めて変換する必要があるときに変換メソッドを記述してください-待ってはいけません。

説明ありがとうございますが、それでもなかなか理解できません。データ転送のレイヤーに検証がない理由がわかりません。次のモバイルアプリの検証を忘れた場合はどうなりますか?少なくとも、データベースモデルで例外を実行するのではなく、APIを呼び出しても検証されません。よくわかりません。
Marc

1
APIレベルで検証するべきではないと言っているのではありません。正直に言うと、それは検証を行う最も重要な場所の1つです。アプリでの検証は、ユーザーが間違いを犯さないようにする「素晴らしい機能」にすぎません。データ転送オブジェクトの検証は、悪意のある誤ったデータを排除するためのものです。ただし、これらは異なるユースケースであるため、異なる検証フレームワークを使用する必要があり(アプリとAPIが同じ言語で記述されていない場合は、異なる検証フレームワーク使用します)、各レベルでわずかに異なるものを検証します(Cont 。次のコメント)
wasatz

1
したがって、データ転送オブジェクトを検証する必要があります。ただし、それらを検証する方法によって、他のフレームワークへの依存関係が誤って導入されないようにする必要もあります。そしてもちろん、前に述べたように、データ転送オブジェクトがまったく検証されているか、または同じフレームワークによって検証されているかは確かにわかりません。そのため、「2回検証」する必要があります。
wasatz 2014年

2
主に、アプリケーションとAPIを2つの完全に異なる別個のアプリケーションとして表示する必要があります。あなたはそれらを同時に開発しているかもしれません、そしてそれらは同じビジュアルスタジオソリューション/ Eclipseプロジェクトにあるかもしれません。しかし、それらは実際には2つの完全に別個のプログラムです。アプリケーションで作業しているときは、APIを作成したのが自分であることを "忘れて"、通常のサードパーティAPIと同じようにそれを使用してください。そうすることで、APIを使用するときに他の人がどのように感じるかを確認し、最悪の部分を早い段階で修正できる可能性が高くなります。
wasatz 2014年

1
もちろん、APIプロジェクトで作業する場合も同じことが言えます。多くのサードパーティ開発者が使用するサービスを書いていると想像してみてください。現在のアプリケーションについてあまり考えないようにしてください。むしろ、「提供しているサービス」をより意識し、APIを使用しているすべての人(自分を含む)がサーバーを殺そうとしている悪人であると想定してください。データベース全体を削除します。
wasatz 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.