web-dev-qa-db-ja.com

サービス層はどのようにすべきですか?

だから私はこれを持っているAndroidアプリが動作している場合、DAO /サービス/ UIレイヤーがデータベースからUIを「分離」することを正しく理解している場合。それに関して2つの問題があります:

1 /デカップリング

このように、DAOレイヤー/データベーススキーマに変更があった場合、サービスレイヤーに触れるだけで、UIはそのままになります。

よし、なぜ? DAOレイヤーの変更に対応するために、1レイヤーで変更する必要がありますが、UIレイヤーを変更する必要がないのはなぜですか?結局、私はまだサービス層を書き直す必要があります。

2/DAOごとに1つのサービスを作成しています

クライアント情報画面:クライアントに関する情報を表示します

だから私は画面にいます、私が現在持っている唯一の情報は「現在の介入ID」です

クライアントアドレスを取得するには、クライアントを知るためにInterventionEntityを取得する必要があります。次に、そのアドレスでClientEntityを取得するためにClientDaoが必要です。

2つのDAOにアクセスする必要がありますが、1つのサービスを呼び出します。それを実装するサービスを選択することは混乱を招きます。

画面ごとに1つのサービスを提供する方がいいのではないでしょうか。

InterventionDAOとClientDAOの両方を使用して「getClientAdress」を持つClientInfosScreenServiceがあります。

ありがとう。

3
sliders_alpha

1 /デカップリング

このように、DAOレイヤー/データベーススキーマに変更があった場合、サービスレイヤーに触れるだけで、UIはそのままになります。

よし、なぜ? DAOレイヤーの変更に対応するために、1レイヤーで変更する必要がありますが、UIレイヤーを変更する必要がないのはなぜですか?

各レイヤーabstractsが次のレイヤーであり、したがってcentralizes usageであることが多いと考えてください。

個人のメールアドレス([email protected])をすべて更新できる4つのビューがある例を考えてみましょう。それらの4つすべてに、ユーザーの電子メールアドレスを更新するロジックが含まれています。

変更を導入したいとします。ここで、メールを2つの別々のフィールド(EmailIdentity(人物)およびEmailDomain(example.com))として保存します。その人のメールアドレスの更新ロジックを変更する必要があります。 4つのビューがあります。つまり、4つのものを変更する必要があります。

DAOレイヤーがあった場合、oneUpdateEmailAddress(int personId, string emailAddress)メソッドがあったでしょう。したがって、同じ変更を実装する場合、必要なのは1つの変更だけです。

私が使用した例では、3つの変更のみを行い、4番目の場所が存在することを知らなかった場合、コンパイラーの問題が発生するため、何かを忘れていることがすぐにわかります。ただし、適用された変更が壊れない場合、コンパイルは成功し、他の更新を忘れたことは通知されません。

接線方向に、異なるレイヤーは異なるプロジェクトとして表されることがよくありますが、本質的には必要ありません。 UIプロジェクトに別のPersonUpdateHelperクラスが既にある場合、DAOレイヤーと呼ぶことができます。データベースとUIの間にある限り、クラスもレイヤーにすることができます(そのため、これら2つが直接対話することはありません)。
他の理由(ライブラリの依存関係、アクセス修飾子を有意義に使用してレイヤーの迂回を防止する機能など)のために、レイヤーとしてプロジェクトを使用することをお勧めしますが、そうではありません技術的には、レイヤーと見なされるための要件です


2/DAOごとに1つのサービスを作成しています

画面ごとに1つのサービスを提供する方がいいのではないでしょうか。

いいえ。前の例と同様に、人のメールアドレスの更新は4つの別々のビューで行われるため、4つのサービスで同じロジックを作成する必要があります(ビューごとに1つ)。

ただし、問題の根本的な根拠にはいくつかのメリットがあります。

2つのDAOにアクセスする必要がありますが、1つのサービスを呼び出します。それを実装するサービスを選択することは混乱を招きます。

私はこれに完全に同意します。しかし、私はここでdaoとサービスが同じスコープで機能する必要はないであることを指摘したいと思います。

サービスが1つのDAO(FooDao)のみに依存している場合、通常、サービスが同じ名前(FooService)を取ることが理にかなっています。ただし、サービスが1つ以上 DAO(FooDaoBarDao)に依存している場合、サービスの目的に基づいてサービスに名前を付ける必要があります。

実例を挙げましょう。私は配達用トラックの運転手がどの小包を配達したかを追跡するために使用するアプリケーションに取り組んでいます。

配送ドライバーには3つの異なる仕事があります。これらの仕事は、「サービスの目的」と言ったときに私が意味するものです。

  • 荷物をトラックに積み込む。
  • 小包を受取人に配達します。
  • 送信者から小包を取得する(後で配信される)。

ロードまたは配信の場合、Parcel(ステータスを変更するため)とSignature(受信者の署名を追加するため)の2つのエンティティを更新する必要があります。取得するときは、Parcelエンティティを更新するだけです(署名は必要ありません)。

これが私たちのセットアップです:

[〜#〜] dao [〜#〜]

  • ParcelDaoは[Parcels]テーブルの更新を処理します。
  • SignatureDaoは、[Signatures]テーブルの更新を処理します。

サービス

  • LoadingServiceは、ParcelDaoSignatureDaoの両方に依存します。
  • DeliveryServiceは、ParcelDaoSignatureDaoの両方に依存します。
  • RetrievalServiceParcelDaoに依存します。

ドライバは影響を受けるエンティティを気にしません。ドライバー(および彼のモバイルアプリケーション)は単にFinishLoading()を呼び出し、これが1つ以上のエンティティを更新するかどうかを気にしません。

これが、レイヤー分離が非常に役立つ理由です。外部の呼び出し元には、アプリケーションに機能的な機能(ロード/配信/取得)があるように見えます。しかし、アプリケーションの内部では、より複雑なデータロジックが使用されています外部の呼び出し元が知る必要はありません

2番目の例として、レストランは同様に料理人(DAO)、ウェイター(サービス)、およびUI(顧客)を分離します。

キッチンが忙しくても、お客さんが食べる部屋は静かで落ち着いています。料理人とお客様が同じ部屋に座っていると、お互いに邪魔になります。しかし、それらを個別の部屋に分離することで、それぞれが必要なもの(顧客にとっての平和で静かな場所、料理人のために迅速に作業できる機能)を持つことができ、料理人も顧客もその他部屋。

[〜#〜] dao [〜#〜]

キッチンを分離することは、すべてのキッチンを特定の料理に合わせることができることを意味します。

  • 寿司職人は自分のキッチンを持っています。
  • グリルシェフは自分のキッチンを持っています。
  • サラダは別のキッチンで作られています。
  • ワインはワインセラーに保管されます。

現実のレストランにはキッチンが1つしかないことが多いことを知っています。しかし、巨大なクルーズ船で見られるような大規模なキッチンを見ると、それぞれ独自の料理とスタッフがいるいくつかのキッチンがあることがわかります。

サービス

ウェイターは料理人と顧客の間の層として機能します。ウェイターがいるので、料理人と顧客がお互いに交流することはありません。ウェイターは、顧客が注文したものを知っています。ウェイターは食事をどこから入手する必要があるかを理解します。

  • ウェイターは適切なキッチンから食事を取り出します。彼らはワインを取りに来ません。
  • ソムリエ(ワインアドバイザー)がワインセラーからワインを取り出します。彼らは食事を取らない。

[〜#〜] ui [〜#〜]

顧客は、誰がどこで料理するかは気にしません。彼らは注文したものを食べたいだけです。

  • 顧客はウェイターが食べ物をテーブルに持ってくることを期待しています。
  • 顧客はソムリエが彼らが要求したワインを持って来ることを期待します。
  • 顧客はウェイターがどこから食べ物を手に入れたかは気にしません。 1か所で受け取った場合でも、複数の場所から受け取った場合でも、お客様には関係ありません。
3
Flater