7

たくさんの質問をお詫びしますが、それらはユニットとして扱われる場合にのみ最も意味があると感じました

注-すべての引用はDDDからのものです:ソフトウェアの中心にある複雑さへの取り組み(250ページと251ページ)

1)

操作は、コマンドとクエリの2つのカテゴリに大きく分けることができます。

..。

副作用を発生させずに結果を返す演算を関数と呼びます。関数は複数回呼び出すことができ、毎回同じ値を返します。

..。

明らかに、ほとんどのソフトウェアシステムでコマンドを回避することはできませんが、問題は2つの方法で軽減できます。まず、コマンドとクエリをさまざまな操作で厳密に分離しておくことができます。変更の原因となるメソッドがドメインデータを返さず、可能な限り単純に保たれていることを確認してください。観察可能な副作用を引き起こさない方法ですべてのクエリと計算を実行します

a)作成者は、クエリが副作用を生成しないため、クエリが関数であることを意味します。彼はまた、関数は常に同じ値を返すと述べています。これは、同じ入力に対して常に同じ出力が得られることを意味すると思いますか?

b)特定のドメインエンティティQandC(int entityId)をクエリするメソッドがあり、そこから特定の値を抽出し、それを使用して新しい値オブジェクトを初期化し、このVOを呼び出し元に返すと仮定します。状態を変えないので、上記の引用によると関数ではありませんか?QandC

c)しかし、著者はまた、同じ入力に対して関数は常に同じ出力を生成すると主張しますが、これは、の場合とは異なります。これは、QandCを複数回呼び出すとQandC、2つの呼び出しの間の時間にこれが発生すると仮定すると、異なる結果が生成されるためです。エンティティが変更または削除されました。このように、どのように私たちQandCは関数であると主張することができますか?

d)

変更の原因となるメソッドがドメインデータを返さないことを確認してください...

返される非VOの状態が将来の操作で変更される可能性があり、そのようなメソッドの副作用が予測できないという理由はありますか?

e)

変更の原因となるメソッドがドメインデータを返さないことを確認してください...

エンティティを返すクエリメソッドは、状態を変更しなくても関数と見なされますか?

2)

VALUE OBJECTSは不変です。つまり、作成時にのみ呼び出される初期化子を除いて、それらの操作はすべて関数です。

..。

ロジックまたは計算と状態変更を組み合わせた操作は、2つの別々の操作にリファクタリングする必要があります。しかし、定義上、この副作用の単純なコマンドメソッドへの分離は、エンティティにのみ適用されます。変更をクエリから分離するためのリファクタリングを完了した後、複雑な計算の責任をVALUEOBJECTに移すための2番目のリファクタリングを検討してください。多くの場合、既存の状態を変更する代わりにVALUE OBJECTを導出するか、責任全体をVALUE OBJECTに移動することで、副作用を完全に排除できます。

a)

VALUE OBJECTSは不変です。つまり、作成時にのみ呼び出される初期化子を除いて、すべての操作は関数です...しかし、定義上、この副作用の単純なコマンドメソッドへの分離はENTITIESにのみ適用されます。

著者は、VOで定義されたメソッドはすべて関数であると言っていると思います。これは、VOで定義されたメソッドがそれ自体の状態を変更できない場合でも、他の非VOオブジェクトの状態を変更できるためです。 ?!

b)エンティティで定義されたメソッドが状態を変更しないと仮定すると、エンティティで定義されていても、そのようなメソッドは関数であると見なしますか?

c)

...複雑な計算の責任をVALUEOBJECTに移すために、2番目のリファクタリングを検討してください。

なぜ著者は、複雑な計算を実行する関数のエンティティからのみリファクタリングする必要があると提案しているのですか?代わりに、より単純な関数もリファクタリングすべきではないのはなぜですか?

d)

...複雑な計算の責任をVALUEOBJECTに移すために、2番目のリファクタリングを検討してください。

いずれにせよ、なぜ著者は、エンティティから関数をリファクタリングしてVO内に配置する必要があると提案しているのでしょうか。この操作が関数である可能性があることをクライアントに明らかにするという理由だけで?

e)

多くの場合、既存の状態を変更する代わりにVALUE OBJECTを導出するか、責任全体をVALUE OBJECTに移動することで、副作用を完全に排除できます。

コマンド(つまり、状態を変更する操作)をVOに移動するかどうかを作成者が主張しているように見えるため、これは意味がありません。コマンドが状態を変更している場合でも、本質的に副作用を排除します。それで、どんな考えでも、著者は実際に何を言おうとしていましたか?

アップデート:

1b)

それは視点に依存します。データベースクエリは状態を変更しないため、副作用はありませんが、データが変更される可能性があることを指摘すると、本質的に決定論的ではありません。この本では、著者は、それ自体は外部呼び出しを行わない、値オブジェクトおよびエンティティに関連付けられた関数について言及しています。したがって、ルールはQandCには適用されません。

それで、作者は外部呼び出しを行わない関数だけを説明していました、そしてQandCそれ自体、作者が説明していたタイプの関数ではありませんか?

1c)

QandC自体は状態を変更しません-副作用はありません。ただし、基になる状態は帯域外で変更される場合があります。このため、これは純粋関数ではありません。

しかし、それはまた、作者がそれらを定義したという意味でのサイドエフェクトフリー機能ではありませんか?

1d)

繰り返しますが、これはCQSに基づいています。

私は自分自身を繰り返していることを知っていますが、本の議論はCQSに基づいており、CQSは、いつか(他の操作によって)状態を変更することQandCによってエンティティが返される可能性があるため、副作用のない機能とは見なされないと思いますQandC未来?

1e)

CQRSの観点からはクエリと見なされますが、決定論がないため、VOの純粋関数が関数であるという意味で関数とは言えません。

  • あなたが何を言おうとしていたのかよくわかりません(紛らわしい部分は太字で示されています)。おそらくQandC、クエリと見なされますが、エンティティを返すために関数とは見なされず、そのような副作用は予測不可能であり、QandC本質的に非決定的です。

  • したがって、作成者は 、VOで定義された操作が非VOオブジェクトの状態を変更しようとしないという暗黙の仮定の下で、これらのステートメント( 1eの引用を参照)のみを作成していますか?

2d)

VOは不変であるため、純粋関数を格納するのに適した場所です。これは、ドメイン知識を技術的な制約から解放するためのもう1つのステップです。

  • 関数をエンティティからVOに移動することで、ドメイン知識を技術的な制約から解放するのに役立つ理由がわかりません(技術関連など、技術的な意味もよくわかりません)。

  • 関数をVOに入れる他の理由は、これが関数であることが(クライアントにとって)はるかに明白だからだと思いますか?

2e)

これは、イベントソーシングへのヒントだと思います。既存の状態を変更する代わりに、変更を表す新しいイベントを追加します。正味の副作用はまだありますが、既存の状態は安定しています。

最初にDDDに頭を悩ませたいので、偶数ソースプログラミングについては何も知らないことを告白しなければなりません。とにかく、作成者は、コマンドをVOに移動するだけで副作用が自動的に解消されることを示唆していませんでしたが、代わりにいくつかの追加アクション(イベントソーシングの実装など)を実行する必要があり、その部分について言及するのを「忘れた」だけでした。 ?

2回目の更新:

2d)

エンティティの特徴の1つは、そのアイデンティティです。ビジネスロジックをVOに配置することで、エンティティのアイデンティティのコンテキスト外でそれを考慮することができます。これにより、特にこのロジックのテストが容易になります。

私はあなたが言っていることを理解していますが(距離から概念を考えるとき)、一方で私は実際には理解していません。エンティティ内の関数がこのエンティティのIDによって影響を受けるのはなぜですか(この関数が純粋関数であると仮定すると、つまり、状態が変化せず、決定論的であると仮定します)。

2e)

はい、それは私の理解です-まだ正味の「副作用」があります。ただし、副作用を得るにはさまざまな方法があります。1つの方法は、既存の状態を変更することです。もう1つの方法は、状態の変化を、その変化を表すオブジェクトで明示的にすることです。

私-念のために...あなたの答えから、著者はコマンドをVOに移動するだけで副作用がなくなることを示唆していなかったと思いますか?

II-わかりました。正しく理解していれば、コマンドをVOに移動できます(VOは何の状態も変更しないため、副作用は発生しません)。VO内のこのコマンドは引き続き許可されます。ある種の副作用を生成しますが、この副作用は、状態の変更を明示的にすることで、何らかの形でより受け入れられます(またはより制御可能になります)(変更されたものはVOとして呼び出し元に返されると解釈します)?

3)状態を変更するメソッドSCがドメインオブジェクトを返さない理由をまだよく理解していないと言わざるを得ません。おそらく、非VOは将来の運用で変更される可能性があり、SCの副作用は非常に予測できないためですか?

3番目の更新:

状態の管理をエンティティに委任し、動作の実装をVOに委任すると、特定の利点が生まれます。1つは、責任の基本的な分割です。

a)メソッドがエンティティの動作を記述している(したがって、このメソッドを含むエンティティはSRPに準拠している)ため、エンティティに属している場合でも、それをVOに移動することをお勧めしますか?したがって、本質的に、エンティティの責任を2つのさらに小さな責任に分割しますか?

b)しかし、動作をVOに移行しても、基本的にこのエンティティは単なるデータコンテナになりません(エンティティは引き続きその状態を管理することを理解していますが、それでも...)?

ありがとうございました

4

1 に答える 1

5

1a)はい。クエリをコマンドから分離することに関する談話は、コマンドクエリ分離の原則に基づいています。

1b)それは視点に依存します。データベースクエリは状態を変更しないため、副作用はありませんが、データが変更される可能性があることを指摘すると、本質的に決定論的ではありません。この本では、著者は、それ自体は外部呼び出しを行わない、値オブジェクトおよびエンティティに関連付けられた関数について言及しています。したがって、ルールはに適用されませんQandC。ただし、決定論は、ある程度の「純粋さ」を提供するように作成することができます。たとえば、データがその期間中変更されないようにすることができるシリアル化可能なトランザクションを作成できます。

1c)QandCそれ自体は状態を変更しません-副作用はありません。ただし、基になる状態は帯域外で変更される場合があります。このため、純粋関数ではありません。QandCただし、状態を変更しない制限は依然として価値があります。この値は、分散シナリオでのCQSのアプリケーションであるCQRSによって適切に示されます。

1d)繰り返しますが、これはCQSに基づいています。これに対する別の見方は、Tell-Don't-Askの原則です。ただし、これらの原則を理解していれば、ルールをIMOに曲げることができます。副作用のあるメソッドは、たとえば結果を表すVOを返す可能性があります。ただし、CQRS +イベントソーシングなどの特定のシナリオでは、コマンドがvoidを返すことが望ましい場合があります。

1e)CQRSの観点からはクエリと見なされますが、決定論がないため、VOの純粋関数が関数であるという意味で関数とは言えません。

2a)いいえ、VO関数は何の状態も変更してはならず、代わりに新しいオブジェクトを返す必要があります。

2b)はい。

2c)より複雑なシナリオでは、機能の純度がより重要になる傾向があるため。ただし、ご指摘のとおり、これは明確で決定的なルールではありません。手元のドメインに基づいているのと同じくらい、複雑さに基づいているべきではありません。

2d)VOは不変であるため、純粋関数を格納するのに適した場所です。これは、ドメイン知識を技術的な制約から解放するためのもう1つのステップです。

2e)これはイベントソーシングへのヒントだと思います。既存の状態を変更する代わりに、変更を表す新しいイベントを追加します。正味の副作用はまだありますが、既存の状態は安定しています。

アップデート

1b)はい。

1c)これは副作用のない関数ですが、同じ入力に対して常に同じ値を返すとは考えられないため、決定論的関数ではありません。たとえば、現在の時刻を返す関数は副作用のない関数ですが、後続の呼び出しで同じ値を返すことはありません。

1d)QandC副作用はないと考えることができますが、純粋ではありません。機能の純度を確認するもう1つの方法は、参照透過性です。つまり、プログラムの動作を変更せずに、関数呼び出しをその値に置き換えることができます。言い換えれば、質問をしても答えは変わりません。QandCそれを保証できますが、トランザクションなどのコンテキスト内でのみ可能です。したがって、QandCは関数と考えることができますが、特定のコンテキストでのみ可能です。

1e)紛らわしいのは、作成者がVOとエンティティの関数について具体的に話していることです。データベースクエリではなく、両方について話しているのです。私のステートメントは、特定の制限、つまりアンビエントトランザクションを前提として、データベースクエリとCQRSに議論を拡張します。

2d)私が言ったことが少し漠然としていて、怠惰になっていたことがわかります。エンティティの特徴の1つは、そのアイデンティティです。状態が変化する可能性がある間、ライフサイクル全体を通じてアイデンティティを維持します。ビジネスロジックをVOに配置することで、エンティティのIDのコンテキスト外でそれを考慮することができます。これにより、特にこのロジックのテストが容易になります。

2e)はい、それは私の理解です-まだ正味の「副作用」があります。ただし、副作用を得るにはさまざまな方法があります。1つの方法は、既存の状態を変更することです。もう1つの方法は、状態の変化を、その変化を表すオブジェクトで明示的にすることです。

更新2

2d)この特定の点については、議論することも、好みの問題にすることもできます。1つの視点は、アイデアが単一責任原則(SRP)に基づいているということです。エンティティの責任は、アイデンティティと行動および状態との関連付けです。動作は、入力と既存の状態を組み合わせて、状態遷移を生成します。状態の管理をエンティティに委任し、動作の実装をVOに委任すると、特定の利点が生まれます。1つは、責任の基本的な分割です。もう1つは、より微妙で、おそらくより議論の余地があります。論理はステートレスな方法で考えることができるという考えです。これにより、そのようなロジックについてより簡単に考えることができ、すべての変更が明示的で、隠れた状態がない数式について考えるようになります。

2e.1)はい、正味の副作用を排除すると行動が変化しますが、これは目標ではありません。

2e.2)はい。

3)voidを返すコマンドには、いくつかの利点があります。1つは、非同期シナリオで自然に熟達することです。結果を待つ必要はありません。もう1つは、戻り値がないため、操作を単一のコマンドオブジェクトとして表すことができることです。これは、CQRSおよびイベントソーシングにも適用されます。このような場合、コマンド出力は結果ではなくイベントとしてディスパッチされます。ただし、これらの要件が当てはまらない場合は、結果オブジェクトを返すことが適切な場合があります。

更新3

a)はい、これは特定のタイプのパーティショニングです。

b)エンティティの責任は、VOに委任し、結果として生じる状態の変化を適用することによって、動作を調整することです。

于 2013-01-24T21:25:51.220 に答える