2016-06-17 10 views
7

DDDが新しく、PUT動詞を使用して集約を更新する方法を理解しようとしています。REST経由のDDD更新

集約のすべてのプロパティにプライベートセッターがある場合は、ビジネス要件ごとに機能のセットを用意する必要があることは明らかです。例

supportTicket.Resolve(); 

それは、私が/api/tickets/5/resolveなどのエンドポイントでこれを達成することができることを私にとっては明らかですが、私はアトミック全体のチケットを更新するための方法を提供したい場合のために?その場合は

は一例として、ユーザは、以下の身体

{"status" : "RESOLVED", "Title":"Some crazy title"} 

/api/tickets/5にPUT要求を行うことができます私はApplicationSercvice

if(DTO.Status != null && dto.Status == "RESOLVED") 
    supportTicket.Resolve(); 
if(DTO.Title != null) 
    supportTicket.setNewTitle(DTO.title); 

にこのような何かをする必要がありますし、変更されたチケットのタイトルには、チケットが解決された場合に変更を防止するためのビジネスロジックがありますが、集計を更新する際に何らかの優先順位を考慮する必要がありますか、まったく間違って見ていますか?

+0

これはDDDよりAPIデザインが多いと思うが、この記事をチェックしてください:https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling-tl; dr; CRUDから脱出する。 – acid

答えて

6

Domain Driven Design for RESTful Systems - ジム・ウェバー

私はアトミック全体のチケットを更新するための方法を提供したい場合は?

チケット全体をアトミックに更新したい場合は、集約してください。あなたが本当に望むものがCRUDセマンティクスを持つキーバリューストアであるならば、集約はあなたの箱の間違ったツールです。

集約は、ドメインのビジネスルールが適用される場合にのみ意味を持ちます。あなたが必要とするものすべてがシャベルであれば、トラクターを建設しないでください。

は例として、ユーザは混乱を作るために起こっているに/ API /チケット/ 5

PUT要求を行うことができます。 CRUD実装では、新しい状態の表現を送信することによってリソースの現在の状態を置き換えることが適切です。しかし、集合体の状態はあなた/クライアント/パブリッシャーの制御下にないため、集合体にはまったく適していません。

より適切なイディオムは、ドメインに処理されたときに必要な変更を達成する副作用を持つメッセージをバスに発行することです。

PUT /api/tickets/5/messages/{messageId} 

今すぐあなたのアプリケーションサービスは、メッセージを見て、これはOKです集約

if(DTO.Status != null && dto.Status == "RESOLVED") 
    supportTicket.Resolve(); 
if(DTO.Title != null) 
    supportTicket.setNewTitle(DTO.title); 

にコマンドを送信し、実際にはそのはるかに一般的なことであるかについての明確なメッセージを作成します完了しました。

{ "messageType" : "ResolveWithNewTitle" 
, "status" : "RESOLVED" 
, "Title":"Some crazy title" 
} 

たり...

[ 
    { "messageType" : "ChangeTitle" 
    , "Title" : "Some crazy title" 
    } 
, { "messageType" : "ResolveTicket" 
    } 
] 

は基本的に、あなたはアプリに、それは本当のメッセージ検証を行うことができ、十分なコンテキストを与えたいです。

はのは、私は必要なビジネスロジックをカプセル化凝集体を持っていたとしましょう、それ以外にもそこアトミック更新機能のための新たな需要があると、私はこれに対処するための最良の方法を理解しようとしています。

だから、これに対処するための正しい方法は、ドメインレベルでそれに対処する最初のものです - 誰もが要件とどのようにユビキタス言語でそれを表現することを理解していることを確認し、ドメインの専門家で座って、

集約ルートに必要な新しいメソッドを実装します。

ドメインで正しくユースケースがサポートされていれば、前のパターンに従ってリソースを心配することができます。リソースは受信リクエストを受け取り、適切なコマンドを呼び出します。

+0

集計は理想的な解決策ではないと私は理解していますが、必要なビジネスロジックをカプセル化した集計があったとしますが、アトミック更新機能の新しい需要があり、これに対処する最善の方法を理解しようとしています。 – Robert

+0

@Robert CRUD操作と動作操作を同じ集約に混在させないでください。とにかくそれがどこで役に立つのかわかりません。 – plalx

+0

リソースを取得するときにHypermediaを実装し、そのリソースに対して実行可能なすべてのアクションを記述できるため、APIのコンシューマーは自分のビジネスロジックを見て、変更可能なこととそのやり方を正確に知ることができます。 – Robert

0

あなたはおそらく正しいでしょう。しかし、changeCommandModel(またはこのようなもの)を受け取ることで、 "change()"メソッドを作成して、ドメインオブジェクト内のビジネスルールを定義できるように、チケット内にそのようなロジックをカプセル化する方が賢明でしょう。

0
if (DTO.Status != null && dto.Status == "RESOLVED") 
        supportTicket.Resolve(DTO.title); 

私はパラメータをタイトルに取るために基礎となるメソッドを変更します。これにより解決アクションが明確になります。 2番目のifとdomainメソッドでの検証が必要です。それは本当に好みです、もっと重要なのはメッセージです。私は@VoiceOfUnreasonの2番目のオプションに同意します。

+0

これが唯一可能なシナリオであればこれはうまくいくかもしれませんが、ユーザーがいくつかのパラメーターを本体に送信してもこれは固執しません。 – Robert

2

タイトルを変更してチケットを解決する必要がありますか?もしそうでなければ、彼らはDDDにおいて同じ行動であってはならない。新しい名前が無効な場合はチケットを解決したくないので、チケットが解決できない場合は名前を変更したくないでしょう。

2つの呼び出しを行い、2つの別々のアクションを実行します。これはまた、タイトルがすぐに変更される可能性があるなどの柔軟性を可能にしますが、実際にチケットが解決される前にチケットを「解決」すると、複雑で時間がかかる(非同期の)ワークフローが開始されます。おそらくマネージャーにサインオフする必要がありますか?あなたはその呼び出しでそのミックスに結びついた "タイトル"を変更したくありません。

必要があれば、@ VoiceOfUnreasonのコメントごとに複数のコマンドを編成するために何かを作成します。

可能な限り、エンティティとの相互作用を最小限に抑えるのとは対照的に、物事を別々に保ち、ケースを使用するようにコードします。

関連する問題