8

私はDDDの原則に準拠しようとするいくつかのアプリケーションに取り組んできましたが、サービスレイヤーとリポジトリの間にコードの臭いのように感じる重複がある状況に陥ることに気づきました。

サービスレイヤーのほとんどの操作では、CRUD操作、GetAll、GetById、Create、Deleteなどへの直接マッピングのようです。アーキテクチャのフローはこれらの行内にあります。サービスレイヤーを呼び出すコントローラーがあります。バックエンドと通信するORMを呼び出すリポジトリを呼び出します。

したがって、たとえばGetAllはSLとリポジトリの両方に存在します。さて、GetAllが特定のアイテムを無視する必要があるという変更/ビジネス要件がある場合、どのようにそれを行うべきですか、リポジトリでこれらを無視する必要がありますか、それともサービスレイヤーに配置する必要があるビジネスロジックですか?ORMを直接呼び出すサービスレイヤーがあれば、生活は楽になりませんか?

要約すると、サービスレイヤーが一部のビジネスロジックを抽象化できることは理解していますが、ほとんどの場合、単純なCRUD操作を処理している場合は、リポジトリを削除する方が簡単ではないでしょうか。しかし、SLに複雑なビジネスロジックを持ついくつかのメソッドも含まれている場合、これらはリポジトリを経由する必要がありますか?優れた設計の観点から、一貫性を優先し、常にリポジトリを通過するか、単純に保ち、CRUD操作への単純な1対1のマッピングではない場合にのみリポジトリを使用する必要があります。

PS:似たような質問があるように見えますが、満足のいく答えは見つかりませんでした

4

4 に答える 4

10

サービスレイヤーとリポジトリの間にコードの臭いのような重複がある状況になってしまうことに気づきました。

彼らは異なることをするので、それはコードの臭いではありません。

ドメインまたはアプリケーションサービスは、リポジトリの実装とは異なるレイヤーに存在することに注意してください。レイヤーが存在するのには理由があります。異なるレイヤーのオブジェクトは同じ責任を持たず、同じネイバーと通信しません。リポジトリの実装は、オブジェクトの永続化の手段と緊密に結合されています。彼らはSQLステートメントを生成してリレーショナルデータベースと通信するかもしれませんし、ORMと通信するかもしれません...重要なことは、オブジェクトが永続化される方法を知っているということです。これはApplicationServicesには当てはまりません。

サービスレイヤーがORMを直接呼び出す場合、それは実際には2つの大きなことを行い、単一責任の原則に違反します。また、ORMを別のORMまたは別の永続化手段に変更することはより困難になります。

したがって、たとえばGetAllはSLとリポジトリの両方に存在します。さて、GetAllが特定のアイテムを無視する必要があるという変更/ビジネス要件がある場合、どのようにそれを行うべきですか、リポジトリでこれらを無視する必要がありますか、それともサービスレイヤーに配置する必要があるビジネスロジックですか?

GetAll()が特定の項目を無視する場合は、それを反映するために、サービスとリポジトリの両方で名前を変更することを強くお勧めしGetAllAllowedToUser()ますGetAllBut...()。したがって、メソッドの契約は明確になり、何が返されるかについての誤解を避けることができます。さらに、元の本物のGetAll()メソッドを保持することができますが、これはまだある程度役立つ可能性があります。

于 2012-09-17T08:47:41.227 に答える
9

ほとんどの場合、単純なCRUD操作を処理しているので、リポジトリを削除する方が簡単ではないでしょうか。

私見、私はリポジトリを取り除くとは言いません。CRUDを実行している場合は、DDDは(まったく)必要ありません。FowlerのエンタープライズパターンまたはEvansを読むと、どちらもDDDは非常に複雑なドメインロジックがある場合にのみ役立つと言っています。CRUDは複雑ではないため、DDDは必要ありません。

あなたが説明するのはコードの臭いです。でも、DDDの匂いではないと思います。過剰に設計されたコードが表示されているだけです。

于 2012-09-16T17:46:55.233 に答える
4

Dtryonの+1、また:

ここで、変更/ビジネス要件がある場合、GetAllは特定のアイテムを無視する必要があります

直接関係はなく、あなたがそれを例として使用したことは知っていますが、私はこれを正確に見てきました。すべてを取得しないGetAllというメソッドで終わらないでください。GetAllを保持し、GetAllを取得してから、GetAllLive、GetAllAvailable、またはそのようなものを取得します。

于 2012-09-16T17:57:05.540 に答える
0

たぶん「ファインダーパターン」(これが正しい用語かどうかわからない)があなたの問題を解決することができます。CQS(Command-Query-Separation)の原則によれば、(IMO、)クエリ操作は「ビジネスロジック」ではありません。インフラストラクチャレイヤーに特定の「ファインダー」を記述して、さまざまなクエリを実行し、クエリ以外のすべての操作(ビジネスロジック)をサービスレイヤーに残して、クライアント側でファインダーをサービスと同じように扱うことができます。
私の言語でごめんなさい:-(。

于 2014-02-02T15:58:31.597 に答える